diff --git a/.pvsconfig b/.pvsconfig index a9ab9c9f6..49c63ad73 100644 --- a/.pvsconfig +++ b/.pvsconfig @@ -44,3 +44,6 @@ # Functions that always return the same error code //-V:picopass_device_decrypt:1048 + +# Examples +//V_EXCLUDE_PATH applications/examples/ \ No newline at end of file diff --git a/applications/debug/unit_tests/rpc/rpc_test.c b/applications/debug/unit_tests/rpc/rpc_test.c index 76acf6be9..329f3b741 100644 --- a/applications/debug/unit_tests/rpc/rpc_test.c +++ b/applications/debug/unit_tests/rpc/rpc_test.c @@ -191,7 +191,7 @@ static void clean_directory(Storage* fs_api, const char* clean_dir) { size_t size = strlen(clean_dir) + strlen(name) + 1 + 1; char* fullname = malloc(size); snprintf(fullname, size, "%s/%s", clean_dir, name); - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { clean_directory(fs_api, fullname); } FS_Error error = storage_common_remove(fs_api, fullname); @@ -608,9 +608,8 @@ static void test_rpc_storage_list_create_expected_list( } if(path_contains_only_ascii(name)) { - list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? - PB_Storage_File_FileType_DIR : - PB_Storage_File_FileType_FILE; + list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; list->file[i].size = fileinfo.size; list->file[i].data = NULL; /* memory free inside rpc_encode_and_send() -> pb_release() */ @@ -873,7 +872,7 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) { if(error == FSE_OK) { response->which_content = PB_Main_storage_stat_response_tag; response->content.storage_stat_response.has_file = true; - response->content.storage_stat_response.file.type = (fileinfo.flags & FSF_DIRECTORY) ? + response->content.storage_stat_response.file.type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR : PB_Storage_File_FileType_FILE; response->content.storage_stat_response.file.size = fileinfo.size; diff --git a/applications/debug/unit_tests/storage/dirwalk_test.c b/applications/debug/unit_tests/storage/dirwalk_test.c index 97aaa3580..e0842a7a4 100644 --- a/applications/debug/unit_tests/storage/dirwalk_test.c +++ b/applications/debug/unit_tests/storage/dirwalk_test.c @@ -179,7 +179,7 @@ MU_TEST_1(test_dirwalk_full, Storage* storage) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { furi_string_right(path, strlen(EXT_PATH("dirwalk/"))); - mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo))); } dir_walk_free(dir_walk); @@ -204,7 +204,7 @@ MU_TEST_1(test_dirwalk_no_recursive, Storage* storage) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { furi_string_right(path, strlen(EXT_PATH("dirwalk/"))); - mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo))); } dir_walk_free(dir_walk); @@ -219,7 +219,7 @@ static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* filein UNUSED(ctx); // only files - if(!(fileinfo->flags & FSF_DIRECTORY)) { + if(!file_info_is_dir(fileinfo)) { // with ".test" in name if(strstr(name, ".test") != NULL) { return true; @@ -243,7 +243,7 @@ MU_TEST_1(test_dirwalk_filter, Storage* storage) { while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) { furi_string_right(path, strlen(EXT_PATH("dirwalk/"))); - mu_check(storage_test_paths_mark(paths, path, (fileinfo.flags & FSF_DIRECTORY))); + mu_check(storage_test_paths_mark(paths, path, file_info_is_dir(&fileinfo))); } dir_walk_free(dir_walk); diff --git a/applications/debug/unit_tests/storage/storage_test.c b/applications/debug/unit_tests/storage/storage_test.c index 115009701..582be7902 100644 --- a/applications/debug/unit_tests/storage/storage_test.c +++ b/applications/debug/unit_tests/storage/storage_test.c @@ -2,9 +2,40 @@ #include #include +// DO NOT USE THIS IN PRODUCTION CODE +// This is a hack to access internal storage functions and definitions +#include + +#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path) + #define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test") #define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX +#define STORAGE_TEST_DIR UNIT_TESTS_PATH("test_dir") + +static bool storage_file_create(Storage* storage, const char* path, const char* data) { + File* file = storage_file_alloc(storage); + bool result = false; + do { + if(!storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_NEW)) { + break; + } + + if(storage_file_write(file, data, strlen(data)) != strlen(data)) { + break; + } + + if(!storage_file_close(file)) { + break; + } + + result = true; + } while(0); + + storage_file_free(file); + return result; +} + static void storage_file_open_lock_setup() { Storage* storage = furi_record_open(RECORD_STORAGE); File* file = storage_file_alloc(storage); @@ -115,7 +146,7 @@ static int32_t storage_dir_locker(void* ctx) { File* file = storage_file_alloc(storage); furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR)); furi_semaphore_release(semaphore); - furi_delay_ms(1000); + furi_delay_ms(100); furi_check(storage_dir_close(file)); furi_record_close(RECORD_STORAGE); @@ -152,9 +183,21 @@ MU_TEST(storage_dir_open_lock) { mu_assert(result, "cannot open locked dir"); } +MU_TEST(storage_dir_exists_test) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + mu_check(!storage_dir_exists(storage, STORAGE_TEST_DIR)); + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, STORAGE_TEST_DIR)); + mu_check(storage_dir_exists(storage, STORAGE_TEST_DIR)); + mu_assert_int_eq(FSE_OK, storage_common_remove(storage, STORAGE_TEST_DIR)); + + furi_record_close(RECORD_STORAGE); +} + MU_TEST_SUITE(storage_dir) { MU_RUN_TEST(storage_dir_open_close); MU_RUN_TEST(storage_dir_open_lock); + MU_RUN_TEST(storage_dir_exists_test); } static const char* const storage_copy_test_paths[] = { @@ -303,9 +346,256 @@ MU_TEST_SUITE(storage_rename) { furi_record_close(RECORD_STORAGE); } +#define APPSDATA_APP_PATH(path) APPS_DATA_PATH "/" path + +static const char* storage_test_apps[] = { + "-_twilight_-", + "-_rainbow_-", + "-_pinkie_-", + "-_apple_-", + "-_flutter_-", + "-_rare_-", +}; + +static size_t storage_test_apps_count = COUNT_OF(storage_test_apps); + +static int32_t storage_test_app(void* arg) { + UNUSED(arg); + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_remove(storage, "/app/test"); + int32_t ret = storage_file_create(storage, "/app/test", "test"); + furi_record_close(RECORD_STORAGE); + return ret; +} + +MU_TEST(test_storage_data_path_apps) { + for(size_t i = 0; i < storage_test_apps_count; i++) { + FuriThread* thread = + furi_thread_alloc_ex(storage_test_apps[i], 1024, storage_test_app, NULL); + furi_thread_set_appid(thread, storage_test_apps[i]); + furi_thread_start(thread); + furi_thread_join(thread); + + mu_assert_int_eq(true, furi_thread_get_return_code(thread)); + + // Check if app data dir and file exists + Storage* storage = furi_record_open(RECORD_STORAGE); + FuriString* expected = furi_string_alloc(); + furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]); + + mu_check(storage_dir_exists(storage, furi_string_get_cstr(expected))); + furi_string_cat(expected, "/test"); + mu_check(storage_file_exists(storage, furi_string_get_cstr(expected))); + + furi_string_printf(expected, APPSDATA_APP_PATH("%s"), storage_test_apps[i]); + storage_simply_remove_recursive(storage, furi_string_get_cstr(expected)); + + furi_record_close(RECORD_STORAGE); + + furi_string_free(expected); + furi_thread_free(thread); + } +} + +MU_TEST(test_storage_data_path) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + File* file = storage_file_alloc(storage); + mu_check(storage_dir_open(file, "/app")); + mu_check(storage_dir_close(file)); + storage_file_free(file); + + // check that appsdata folder exists + mu_check(storage_dir_exists(storage, APPS_DATA_PATH)); + + // check that cli folder exists + mu_check(storage_dir_exists(storage, APPSDATA_APP_PATH("cli"))); + + storage_simply_remove(storage, APPSDATA_APP_PATH("cli")); + + furi_record_close(RECORD_STORAGE); +} + +MU_TEST(test_storage_common_migrate) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + // Setup test folders + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + + // Test migration from non existing + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + // Test migration from existing folder to non existing + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file1"), "test1")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file2.ext"), "test2")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file3.ext.ext"), "test3")); + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file1"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file2.ext"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext.ext"))); + mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + + // Test migration from existing folder to existing folder + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file1"), "test1")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file2.ext"), "test2")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old/file3.ext.ext"), "test3")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file1"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file2.ext"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext.ext"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file11"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file21.ext"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new/file3.ext1.ext"))); + mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + + // Test migration from empty folder to existing file + // Expected result: FSE_OK, folder removed, file untouched + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new"), "test1")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + + // Test migration from empty folder to existing folder + // Expected result: FSE_OK, old folder removed, new folder untouched + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_new"))); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + + // Test migration from existing file to non existing, no extension + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + + // Test migration from existing file to non existing, with extension + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old.file"), "test1")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old.file"), UNIT_TESTS_PATH("migrate_new.file"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new.file"))); + mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old.file"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old.file")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new.file")); + + // Test migration from existing file to existing file, no extension + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new"), "test2")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1")); + + // Test migration from existing file to existing file, with extension + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old.file"), "test1")); + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_new.file"), "test2")); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old.file"), UNIT_TESTS_PATH("migrate_new.file"))); + + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new.file"))); + mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old.file"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1.file"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old.file")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new.file")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1.file")); + + // Test migration from existing file to existing folder + mu_check(storage_file_create(storage, UNIT_TESTS_PATH("migrate_old"), "test1")); + mu_assert_int_eq(FSE_OK, storage_common_mkdir(storage, UNIT_TESTS_PATH("migrate_new"))); + + mu_assert_int_eq( + FSE_OK, + storage_common_migrate( + storage, UNIT_TESTS_PATH("migrate_old"), UNIT_TESTS_PATH("migrate_new"))); + + mu_check(storage_dir_exists(storage, UNIT_TESTS_PATH("migrate_new"))); + mu_check(!storage_file_exists(storage, UNIT_TESTS_PATH("migrate_old"))); + mu_check(storage_file_exists(storage, UNIT_TESTS_PATH("migrate_new1"))); + + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_old")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new")); + storage_simply_remove_recursive(storage, UNIT_TESTS_PATH("migrate_new1")); + + furi_record_close(RECORD_STORAGE); +} + +MU_TEST_SUITE(test_data_path) { + MU_RUN_TEST(test_storage_data_path); + MU_RUN_TEST(test_storage_data_path_apps); +} + +MU_TEST_SUITE(test_storage_common) { + MU_RUN_TEST(test_storage_common_migrate); +} + int run_minunit_test_storage() { MU_RUN_SUITE(storage_file); MU_RUN_SUITE(storage_dir); MU_RUN_SUITE(storage_rename); + MU_RUN_SUITE(test_data_path); + MU_RUN_SUITE(test_storage_common); return MU_EXIT_CODE; } diff --git a/applications/examples/example_apps_data/README.md b/applications/examples/example_apps_data/README.md new file mode 100644 index 000000000..fd8666077 --- /dev/null +++ b/applications/examples/example_apps_data/README.md @@ -0,0 +1,18 @@ +# Apps Data folder Example + +This example demonstrates how to utilize the Apps Data folder to store data that is not part of the app itself, such as user data, configuration files, and so forth. + +## What is the Apps Data Folder? + +The **Apps Data** folder is a folder used to store data for external apps that are not part of the main firmware. + +The path to the current application folder is related to the `appid` of the app. The `appid` is used to identify the app in the app store and is stored in the `application.fam` file. +The Apps Data folder is located only on the external storage, the SD card. + +For example, if the `appid` of the app is `snake_game`, the path to the Apps Data folder will be `/ext/apps_data/snake_game`. But using raw paths is not recommended, because the path to the Apps Data folder can change in the future. Use the `/app` alias instead. + +## How to get the path to the Apps Data folder? + +You can use `/app` alias to get the path to the current application data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `/app/config.txt`. But this way is not recommended, because even the `/app` alias can change in the future. + +We recommend to use the `APP_DATA_PATH` macro to get the path to the Apps Data folder. For example, if you want to open a file `config.txt` in the Apps Data folder, you can use the next path: `APP_DATA_PATH("config.txt")`. \ No newline at end of file diff --git a/applications/examples/example_apps_data/application.fam b/applications/examples/example_apps_data/application.fam new file mode 100644 index 000000000..f44dca97d --- /dev/null +++ b/applications/examples/example_apps_data/application.fam @@ -0,0 +1,9 @@ +App( + appid="example_apps_data", + name="Example: Apps Data", + apptype=FlipperAppType.EXTERNAL, + entry_point="example_apps_data_main", + requires=["gui"], + stack_size=1 * 1024, + fap_category="Examples", +) diff --git a/applications/examples/example_apps_data/example_apps_data.c b/applications/examples/example_apps_data/example_apps_data.c new file mode 100644 index 000000000..d6104c137 --- /dev/null +++ b/applications/examples/example_apps_data/example_apps_data.c @@ -0,0 +1,40 @@ +#include +#include + +// Define log tag +#define TAG "example_apps_data" + +// Application entry point +int32_t example_apps_data_main(void* p) { + // Mark argument as unused + UNUSED(p); + + // Open storage + Storage* storage = furi_record_open(RECORD_STORAGE); + + // Allocate file + File* file = storage_file_alloc(storage); + + // Get the path to the current application data folder + // That is: /ext/apps_data/ + // And it will create folders in the path if they don't exist + // In this example it will create /ext/apps_data/example_apps_data + // And file will be /ext/apps_data/example_apps_data/test.txt + + // Open file, write data and close it + if(!storage_file_open(file, APP_DATA_PATH("test.txt"), FSAM_WRITE, FSOM_CREATE_ALWAYS)) { + FURI_LOG_E(TAG, "Failed to open file"); + } + if(!storage_file_write(file, "Hello World!", strlen("Hello World!"))) { + FURI_LOG_E(TAG, "Failed to write to file"); + } + storage_file_close(file); + + // Deallocate file + storage_file_free(file); + + // Close storage + furi_record_close(RECORD_STORAGE); + + return 0; +} diff --git a/applications/main/archive/helpers/archive_browser.c b/applications/main/archive/helpers/archive_browser.c index c72220c6a..f93d9694d 100644 --- a/applications/main/archive/helpers/archive_browser.c +++ b/applications/main/archive/helpers/archive_browser.c @@ -451,7 +451,7 @@ static bool archive_is_dir_exists(FuriString* path) { FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) { - if(file_info.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&file_info)) { state = true; } } @@ -532,12 +532,16 @@ void archive_enter_dir(ArchiveBrowserView* browser, FuriString* path) { browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false); furi_string_set(browser->path, path); + file_browser_worker_folder_enter(browser->worker, path, idx_temp); } void archive_leave_dir(ArchiveBrowserView* browser) { furi_assert(browser); + size_t dirname_start = furi_string_search_rchar(browser->path, '/'); + furi_string_left(browser->path, dirname_start); + file_browser_worker_folder_exit(browser->worker); } diff --git a/applications/main/archive/helpers/archive_favorites.c b/applications/main/archive/helpers/archive_favorites.c index 8bbcb5213..f395ee5a1 100644 --- a/applications/main/archive/helpers/archive_favorites.c +++ b/applications/main/archive/helpers/archive_favorites.c @@ -160,7 +160,7 @@ bool archive_favorites_read(void* context) { if(storage_file_exists(storage, furi_string_get_cstr(buffer))) { storage_common_stat(storage, furi_string_get_cstr(buffer), &file_info); archive_add_file_item( - browser, (file_info.flags & FSF_DIRECTORY), furi_string_get_cstr(buffer)); + browser, file_info_is_dir(&file_info), furi_string_get_cstr(buffer)); file_count++; } else { need_refresh = true; diff --git a/applications/main/archive/helpers/archive_files.c b/applications/main/archive/helpers/archive_files.c index 83eb2a845..5f5d13fc3 100644 --- a/applications/main/archive/helpers/archive_files.c +++ b/applications/main/archive/helpers/archive_files.c @@ -96,7 +96,7 @@ void archive_delete_file(void* context, const char* format, ...) { bool res = false; - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { res = storage_simply_remove_recursive(fs_api, furi_string_get_cstr(filename)); } else { res = (storage_common_remove(fs_api, furi_string_get_cstr(filename)) == FSE_OK); diff --git a/applications/main/fap_loader/fap_loader_app.c b/applications/main/fap_loader/fap_loader_app.c index 7911aa068..e81a3ce4c 100644 --- a/applications/main/fap_loader/fap_loader_app.c +++ b/applications/main/fap_loader/fap_loader_app.c @@ -5,6 +5,7 @@ #include #include #include +#include #include #include "elf_cpp/elf_hashtable.h" #include "fap_loader_app.h" @@ -105,6 +106,12 @@ static bool fap_loader_run_selected_app(FapLoader* loader) { FURI_LOG_I(TAG, "FAP Loader is starting app"); FuriThread* thread = flipper_application_spawn(loader->app, NULL); + + FuriString* app_name = furi_string_alloc(); + path_extract_filename_no_ext(furi_string_get_cstr(loader->fap_path), app_name); + furi_thread_set_appid(thread, furi_string_get_cstr(app_name)); + furi_string_free(app_name); + furi_thread_start(thread); furi_thread_join(thread); diff --git a/applications/main/ibutton/ibutton.c b/applications/main/ibutton/ibutton.c index 85212f42b..79999adb2 100644 --- a/applications/main/ibutton/ibutton.c +++ b/applications/main/ibutton/ibutton.c @@ -1,10 +1,6 @@ -#include "ibutton.h" -#include "assets_icons.h" #include "ibutton_i.h" -#include "ibutton/scenes/ibutton_scene.h" + #include -#include -#include #include #define TAG "iButtonApp" @@ -34,50 +30,13 @@ static const NotificationSequence* ibutton_notification_sequences[] = { }; static void ibutton_make_app_folder(iButton* ibutton) { - if(!storage_simply_mkdir(ibutton->storage, IBUTTON_APP_FOLDER)) { + Storage* storage = furi_record_open(RECORD_STORAGE); + + if(!storage_simply_mkdir(storage, IBUTTON_APP_FOLDER)) { dialog_message_show_storage_error(ibutton->dialogs, "Cannot create\napp folder"); } -} -bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog) { - FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); - bool result = false; - FuriString* data; - data = furi_string_alloc(); - - do { - if(!flipper_format_file_open_existing(file, furi_string_get_cstr(key_path))) break; - - // header - uint32_t version; - if(!flipper_format_read_header(file, data, &version)) break; - if(furi_string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break; - if(version != 1) break; - - // key type - iButtonKeyType type; - if(!flipper_format_read_string(file, "Key type", data)) break; - if(!ibutton_key_get_type_by_string(furi_string_get_cstr(data), &type)) break; - - // key data - uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0}; - if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type))) - break; - - ibutton_key_set_type(ibutton->key, type); - ibutton_key_set_data(ibutton->key, key_data, IBUTTON_KEY_DATA_SIZE); - - result = true; - } while(false); - - flipper_format_free(file); - furi_string_free(data); - - if((!result) && (show_dialog)) { - dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); - } - - return result; + furi_record_close(RECORD_STORAGE); } static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) { @@ -87,14 +46,14 @@ static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) if(event == RpcAppEventSessionClose) { view_dispatcher_send_custom_event( ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose); - rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); - ibutton->rpc_ctx = NULL; + rpc_system_app_set_callback(ibutton->rpc, NULL, NULL); + ibutton->rpc = NULL; } else if(event == RpcAppEventAppExit) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit); } else if(event == RpcAppEventLoadFile) { view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad); } else { - rpc_system_app_confirm(ibutton->rpc_ctx, event, false); + rpc_system_app_confirm(ibutton->rpc, event, false); } } @@ -135,13 +94,13 @@ iButton* ibutton_alloc() { ibutton->gui = furi_record_open(RECORD_GUI); - ibutton->storage = furi_record_open(RECORD_STORAGE); ibutton->dialogs = furi_record_open(RECORD_DIALOGS); ibutton->notifications = furi_record_open(RECORD_NOTIFICATION); - ibutton->key = ibutton_key_alloc(); - ibutton->key_worker = ibutton_worker_alloc(); - ibutton_worker_start_thread(ibutton->key_worker); + ibutton->protocols = ibutton_protocols_alloc(); + ibutton->key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(ibutton->protocols)); + ibutton->worker = ibutton_worker_alloc(ibutton->protocols); + ibutton_worker_start_thread(ibutton->worker); ibutton->submenu = submenu_alloc(); view_dispatcher_add_view( @@ -163,9 +122,9 @@ iButton* ibutton_alloc() { view_dispatcher_add_view( ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget)); - ibutton->dialog_ex = dialog_ex_alloc(); + ibutton->loading = loading_alloc(); view_dispatcher_add_view( - ibutton->view_dispatcher, iButtonViewDialogEx, dialog_ex_get_view(ibutton->dialog_ex)); + ibutton->view_dispatcher, iButtonViewLoading, loading_get_view(ibutton->loading)); return ibutton; } @@ -173,8 +132,8 @@ iButton* ibutton_alloc() { void ibutton_free(iButton* ibutton) { furi_assert(ibutton); - view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewDialogEx); - dialog_ex_free(ibutton->dialog_ex); + view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewLoading); + loading_free(ibutton->loading); view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget); widget_free(ibutton->widget); @@ -194,9 +153,6 @@ void ibutton_free(iButton* ibutton) { view_dispatcher_free(ibutton->view_dispatcher); scene_manager_free(ibutton->scene_manager); - furi_record_close(RECORD_STORAGE); - ibutton->storage = NULL; - furi_record_close(RECORD_NOTIFICATION); ibutton->notifications = NULL; @@ -206,103 +162,83 @@ void ibutton_free(iButton* ibutton) { furi_record_close(RECORD_GUI); ibutton->gui = NULL; - ibutton_worker_stop_thread(ibutton->key_worker); - ibutton_worker_free(ibutton->key_worker); + ibutton_worker_stop_thread(ibutton->worker); + ibutton_worker_free(ibutton->worker); ibutton_key_free(ibutton->key); + ibutton_protocols_free(ibutton->protocols); furi_string_free(ibutton->file_path); free(ibutton); } -bool ibutton_file_select(iButton* ibutton) { - DialogsFileBrowserOptions browser_options; - dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px); - browser_options.base_path = IBUTTON_APP_FOLDER; +bool ibutton_load_key(iButton* ibutton) { + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewLoading); - bool success = dialog_file_browser_show( - ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options); + const bool success = ibutton_protocols_load( + ibutton->protocols, ibutton->key, furi_string_get_cstr(ibutton->file_path)); - if(success) { - success = ibutton_load_key_data(ibutton, ibutton->file_path, true); + if(!success) { + dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file"); + + } else { + FuriString* tmp = furi_string_alloc(); + + path_extract_filename(ibutton->file_path, tmp, true); + strncpy(ibutton->key_name, furi_string_get_cstr(tmp), IBUTTON_KEY_NAME_SIZE); + + furi_string_free(tmp); } return success; } -bool ibutton_save_key(iButton* ibutton, const char* key_name) { - // Create ibutton directory if necessary +bool ibutton_select_and_load_key(iButton* ibutton) { + DialogsFileBrowserOptions browser_options; + dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px); + browser_options.base_path = IBUTTON_APP_FOLDER; + + if(furi_string_empty(ibutton->file_path)) { + furi_string_set(ibutton->file_path, browser_options.base_path); + } + + return dialog_file_browser_show( + ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options) && + ibutton_load_key(ibutton); +} + +bool ibutton_save_key(iButton* ibutton) { + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewLoading); + ibutton_make_app_folder(ibutton); - FlipperFormat* file = flipper_format_file_alloc(ibutton->storage); iButtonKey* key = ibutton->key; + const bool success = + ibutton_protocols_save(ibutton->protocols, key, furi_string_get_cstr(ibutton->file_path)); - bool result = false; - - do { - // Check if we has old key - if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - // First remove old key - ibutton_delete_key(ibutton); - - // Remove old key name from path - size_t filename_start = furi_string_search_rchar(ibutton->file_path, '/'); - furi_string_left(ibutton->file_path, filename_start); - } - - furi_string_cat_printf(ibutton->file_path, "/%s%s", key_name, IBUTTON_APP_EXTENSION); - - // Open file for write - if(!flipper_format_file_open_always(file, furi_string_get_cstr(ibutton->file_path))) break; - - // Write header - if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break; - - // Write key type - if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom")) - break; - const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key)); - if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break; - - // Write data - if(!flipper_format_write_comment_cstr( - file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8")) - break; - - if(!flipper_format_write_hex( - file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key))) - break; - result = true; - - } while(false); - - flipper_format_free(file); - - if(!result) { //-V547 + if(!success) { dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file"); } - return result; + return success; } bool ibutton_delete_key(iButton* ibutton) { bool result = false; - result = storage_simply_remove(ibutton->storage, furi_string_get_cstr(ibutton->file_path)); + + Storage* storage = furi_record_open(RECORD_STORAGE); + result = storage_simply_remove(storage, furi_string_get_cstr(ibutton->file_path)); + furi_record_close(RECORD_STORAGE); + + ibutton_reset_key(ibutton); return result; } -void ibutton_text_store_set(iButton* ibutton, const char* text, ...) { - va_list args; - va_start(args, text); - - vsnprintf(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE, text, args); - - va_end(args); -} - -void ibutton_text_store_clear(iButton* ibutton) { - memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE + 1); +void ibutton_reset_key(iButton* ibutton) { + memset(ibutton->key_name, 0, IBUTTON_KEY_NAME_SIZE + 1); + furi_string_reset(ibutton->file_path); + ibutton_key_reset(ibutton->key); } void ibutton_notification_message(iButton* ibutton, uint32_t message) { @@ -310,36 +246,44 @@ void ibutton_notification_message(iButton* ibutton, uint32_t message) { notification_message(ibutton->notifications, ibutton_notification_sequences[message]); } -int32_t ibutton_app(void* p) { +void ibutton_submenu_callback(void* context, uint32_t index) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); +} + +void ibutton_widget_callback(GuiButtonType result, InputType type, void* context) { + iButton* ibutton = context; + if(type == InputTypeShort) { + view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); + } +} + +int32_t ibutton_app(void* arg) { iButton* ibutton = ibutton_alloc(); ibutton_make_app_folder(ibutton); bool key_loaded = false; - bool rpc_mode = false; - if(p && strlen(p)) { - uint32_t rpc_ctx = 0; - if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) { + if((arg != NULL) && (strlen(arg) != 0)) { + if(sscanf(arg, "RPC %lX", (uint32_t*)&ibutton->rpc) == 1) { FURI_LOG_D(TAG, "Running in RPC mode"); - ibutton->rpc_ctx = (void*)rpc_ctx; - rpc_mode = true; - rpc_system_app_set_callback(ibutton->rpc_ctx, ibutton_rpc_command_callback, ibutton); - rpc_system_app_send_started(ibutton->rpc_ctx); + + rpc_system_app_set_callback(ibutton->rpc, ibutton_rpc_command_callback, ibutton); + rpc_system_app_send_started(ibutton->rpc); + } else { - furi_string_set(ibutton->file_path, (const char*)p); - if(ibutton_load_key_data(ibutton, ibutton->file_path, true)) { - key_loaded = true; - // TODO: Display an error if the key from p could not be loaded - } + furi_string_set(ibutton->file_path, (const char*)arg); + key_loaded = ibutton_load_key(ibutton); } } - if(rpc_mode) { + if(ibutton->rpc != NULL) { view_dispatcher_attach_to_gui( ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc); DOLPHIN_DEED(DolphinDeedIbuttonEmulate); + } else { view_dispatcher_attach_to_gui( ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen); @@ -353,9 +297,9 @@ int32_t ibutton_app(void* p) { view_dispatcher_run(ibutton->view_dispatcher); - if(ibutton->rpc_ctx) { - rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL); - rpc_system_app_send_exited(ibutton->rpc_ctx); + if(ibutton->rpc) { + rpc_system_app_set_callback(ibutton->rpc, NULL, NULL); + rpc_system_app_send_exited(ibutton->rpc); } ibutton_free(ibutton); return 0; diff --git a/applications/main/ibutton/ibutton_cli.c b/applications/main/ibutton/ibutton_cli.c index 9ddb079dc..2b88b2007 100644 --- a/applications/main/ibutton/ibutton_cli.c +++ b/applications/main/ibutton/ibutton_cli.c @@ -1,11 +1,15 @@ #include #include -#include + #include -#include -#include +#include + #include +#include +#include +#include + static void ibutton_cli(Cli* cli, FuriString* args, void* context); static void onewire_cli(Cli* cli, FuriString* args, void* context); @@ -22,7 +26,7 @@ void ibutton_on_system_start() { #endif } -void ibutton_cli_print_usage() { +static void ibutton_cli_print_usage() { printf("Usage:\r\n"); printf("ikey read\r\n"); printf("ikey emulate \r\n"); @@ -34,30 +38,52 @@ void ibutton_cli_print_usage() { printf("\t are hex-formatted\r\n"); }; -bool ibutton_cli_get_key_type(FuriString* data, iButtonKeyType* type) { +static bool ibutton_cli_parse_key(iButtonProtocols* protocols, iButtonKey* key, FuriString* args) { bool result = false; + FuriString* name = furi_string_alloc(); - if(furi_string_cmp_str(data, "Dallas") == 0 || furi_string_cmp_str(data, "dallas") == 0) { - result = true; - *type = iButtonKeyDS1990; - } else if(furi_string_cmp_str(data, "Cyfral") == 0 || furi_string_cmp_str(data, "cyfral") == 0) { - result = true; - *type = iButtonKeyCyfral; - } else if(furi_string_cmp_str(data, "Metakom") == 0 || furi_string_cmp_str(data, "metakom") == 0) { - result = true; - *type = iButtonKeyMetakom; - } + do { + // Read protocol name + if(!args_read_string_and_trim(args, name)) break; + // Make the protocol name uppercase + const char first = furi_string_get_char(name, 0); + furi_string_set_char(name, 0, toupper((int)first)); + + const iButtonProtocolId id = + ibutton_protocols_get_id_by_name(protocols, furi_string_get_cstr(name)); + if(id == iButtonProtocolIdInvalid) break; + + ibutton_key_set_protocol_id(key, id); + + // Get the data pointer + iButtonEditableData data; + ibutton_protocols_get_editable_data(protocols, key, &data); + + // Read data + if(!args_read_hex_bytes(args, data.ptr, data.size)) break; + + result = true; + } while(false); + + furi_string_free(name); return result; } -void ibutton_cli_print_key_data(iButtonKey* key) { - const uint8_t* key_data = ibutton_key_get_data_p(key); - iButtonKeyType type = ibutton_key_get_type(key); +static void ibutton_cli_print_key(iButtonProtocols* protocols, iButtonKey* key) { + const char* name = ibutton_protocols_get_name(protocols, ibutton_key_get_protocol_id(key)); - printf("%s ", ibutton_key_get_string_by_type(type)); - for(size_t i = 0; i < ibutton_key_get_size_by_type(type); i++) { - printf("%02X", key_data[i]); + if(strncmp(name, "DS", 2) == 0) { + name = "Dallas"; + } + + printf("%s ", name); + + iButtonEditableData data; + ibutton_protocols_get_editable_data(protocols, key, &data); + + for(size_t i = 0; i < data.size; i++) { + printf("%02X", data.ptr[i]); } printf("\r\n"); @@ -71,9 +97,10 @@ static void ibutton_cli_worker_read_cb(void* context) { furi_event_flag_set(event, EVENT_FLAG_IBUTTON_COMPLETE); } -void ibutton_cli_read(Cli* cli) { - iButtonKey* key = ibutton_key_alloc(); - iButtonWorker* worker = ibutton_worker_alloc(); +static void ibutton_cli_read(Cli* cli) { + iButtonProtocols* protocols = ibutton_protocols_alloc(); + iButtonWorker* worker = ibutton_worker_alloc(protocols); + iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols)); FuriEventFlag* event = furi_event_flag_alloc(); ibutton_worker_start_thread(worker); @@ -81,32 +108,25 @@ void ibutton_cli_read(Cli* cli) { printf("Reading iButton...\r\nPress Ctrl+C to abort\r\n"); ibutton_worker_read_start(worker, key); + while(true) { uint32_t flags = furi_event_flag_wait(event, EVENT_FLAG_IBUTTON_COMPLETE, FuriFlagWaitAny, 100); if(flags & EVENT_FLAG_IBUTTON_COMPLETE) { - ibutton_cli_print_key_data(key); - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - if(!ibutton_key_dallas_crc_is_valid(key)) { - printf("Warning: invalid CRC\r\n"); - } - - if(!ibutton_key_dallas_is_1990_key(key)) { - printf("Warning: not a key\r\n"); - } - } + ibutton_cli_print_key(protocols, key); break; } if(cli_cmd_interrupt_received(cli)) break; } - ibutton_worker_stop(worker); + ibutton_worker_stop(worker); ibutton_worker_stop_thread(worker); - ibutton_worker_free(worker); + ibutton_key_free(key); + ibutton_worker_free(worker); + ibutton_protocols_free(protocols); furi_event_flag_free(event); }; @@ -124,48 +144,33 @@ static void ibutton_cli_worker_write_cb(void* context, iButtonWorkerWriteResult } void ibutton_cli_write(Cli* cli, FuriString* args) { - iButtonKey* key = ibutton_key_alloc(); - iButtonWorker* worker = ibutton_worker_alloc(); - iButtonKeyType type; - iButtonWriteContext write_context; - uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; - FuriString* data; + iButtonProtocols* protocols = ibutton_protocols_alloc(); + iButtonWorker* worker = ibutton_worker_alloc(protocols); + iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols)); + iButtonWriteContext write_context; write_context.event = furi_event_flag_alloc(); - data = furi_string_alloc(); ibutton_worker_start_thread(worker); ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context); do { - if(!args_read_string_and_trim(args, data)) { + if(!ibutton_cli_parse_key(protocols, key, args)) { ibutton_cli_print_usage(); break; } - if(!ibutton_cli_get_key_type(data, &type)) { + if(!(ibutton_protocols_get_features(protocols, ibutton_key_get_protocol_id(key)) & + iButtonProtocolFeatureWriteBlank)) { ibutton_cli_print_usage(); break; } - if(type != iButtonKeyDS1990) { - ibutton_cli_print_usage(); - break; - } - - if(!args_read_hex_bytes(args, key_data, ibutton_key_get_size_by_type(type))) { - ibutton_cli_print_usage(); - break; - } - - ibutton_key_set_type(key, type); - ibutton_key_set_data(key, key_data, ibutton_key_get_size_by_type(type)); - printf("Writing key "); - ibutton_cli_print_key_data(key); + ibutton_cli_print_key(protocols, key); printf("Press Ctrl+C to abort\r\n"); - ibutton_worker_write_start(worker, key); + ibutton_worker_write_blank_start(worker, key); while(true) { uint32_t flags = furi_event_flag_wait( write_context.event, EVENT_FLAG_IBUTTON_COMPLETE, FuriFlagWaitAny, 100); @@ -183,64 +188,53 @@ void ibutton_cli_write(Cli* cli, FuriString* args) { if(cli_cmd_interrupt_received(cli)) break; } - ibutton_worker_stop(worker); } while(false); - furi_string_free(data); + ibutton_worker_stop(worker); ibutton_worker_stop_thread(worker); - ibutton_worker_free(worker); + ibutton_key_free(key); + ibutton_worker_free(worker); + ibutton_protocols_free(protocols); furi_event_flag_free(write_context.event); -}; +} void ibutton_cli_emulate(Cli* cli, FuriString* args) { - iButtonKey* key = ibutton_key_alloc(); - iButtonWorker* worker = ibutton_worker_alloc(); - iButtonKeyType type; - uint8_t key_data[IBUTTON_KEY_DATA_SIZE]; - FuriString* data; + iButtonProtocols* protocols = ibutton_protocols_alloc(); + iButtonWorker* worker = ibutton_worker_alloc(protocols); + iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols)); - data = furi_string_alloc(); ibutton_worker_start_thread(worker); do { - if(!args_read_string_and_trim(args, data)) { + if(!ibutton_cli_parse_key(protocols, key, args)) { ibutton_cli_print_usage(); break; } - if(!ibutton_cli_get_key_type(data, &type)) { - ibutton_cli_print_usage(); - break; - } - - if(!args_read_hex_bytes(args, key_data, ibutton_key_get_size_by_type(type))) { - ibutton_cli_print_usage(); - break; - } - - ibutton_key_set_type(key, type); - ibutton_key_set_data(key, key_data, ibutton_key_get_size_by_type(type)); - printf("Emulating key "); - ibutton_cli_print_key_data(key); + ibutton_cli_print_key(protocols, key); printf("Press Ctrl+C to abort\r\n"); ibutton_worker_emulate_start(worker, key); + while(!cli_cmd_interrupt_received(cli)) { furi_delay_ms(100); }; - ibutton_worker_stop(worker); + } while(false); - furi_string_free(data); + ibutton_worker_stop(worker); ibutton_worker_stop_thread(worker); - ibutton_worker_free(worker); + ibutton_key_free(key); + ibutton_worker_free(worker); + ibutton_protocols_free(protocols); }; -static void ibutton_cli(Cli* cli, FuriString* args, void* context) { +void ibutton_cli(Cli* cli, FuriString* args, void* context) { + UNUSED(cli); UNUSED(context); FuriString* cmd; cmd = furi_string_alloc(); @@ -264,7 +258,7 @@ static void ibutton_cli(Cli* cli, FuriString* args, void* context) { furi_string_free(cmd); } -void onewire_cli_print_usage() { +static void onewire_cli_print_usage() { printf("Usage:\r\n"); printf("onewire search\r\n"); }; @@ -281,7 +275,7 @@ static void onewire_cli_search(Cli* cli) { furi_hal_power_enable_otg(); while(!done) { - if(onewire_host_search(onewire, address, NORMAL_SEARCH) != 1) { + if(onewire_host_search(onewire, address, OneWireHostSearchModeNormal) != 1) { printf("Search finished\r\n"); onewire_host_reset_search(onewire); done = true; diff --git a/applications/main/ibutton/ibutton_custom_event.h b/applications/main/ibutton/ibutton_custom_event.h index 1e2f0300d..28bcb94a0 100644 --- a/applications/main/ibutton/ibutton_custom_event.h +++ b/applications/main/ibutton/ibutton_custom_event.h @@ -6,6 +6,7 @@ enum iButtonCustomEvent { iButtonCustomEventBack, iButtonCustomEventTextEditResult, + iButtonCustomEventByteEditChanged, iButtonCustomEventByteEditResult, iButtonCustomEventWorkerEmulated, iButtonCustomEventWorkerRead, diff --git a/applications/main/ibutton/ibutton_i.h b/applications/main/ibutton/ibutton_i.h index 0a8099351..8ad0b90e4 100644 --- a/applications/main/ibutton/ibutton_i.h +++ b/applications/main/ibutton/ibutton_i.h @@ -4,31 +4,40 @@ #include #include -#include -#include #include -#include +#include #include +#include + +#include #include #include +#include +#include #include #include -#include #include #include #include +#include + +#include #include "ibutton_custom_event.h" #include "scenes/ibutton_scene.h" -#define IBUTTON_FILE_NAME_SIZE 100 -#define IBUTTON_TEXT_STORE_SIZE 128 - #define IBUTTON_APP_FOLDER ANY_PATH("ibutton") #define IBUTTON_APP_EXTENSION ".ibtn" -#define IBUTTON_APP_FILE_TYPE "Flipper iButton key" + +#define IBUTTON_KEY_NAME_SIZE 22 + +typedef enum { + iButtonWriteModeInvalid, + iButtonWriteModeBlank, + iButtonWriteModeCopy, +} iButtonWriteMode; struct iButton { SceneManager* scene_manager; @@ -38,21 +47,22 @@ struct iButton { Storage* storage; DialogsApp* dialogs; NotificationApp* notifications; + RpcAppSystem* rpc; - iButtonWorker* key_worker; iButtonKey* key; + iButtonWorker* worker; + iButtonProtocols* protocols; + iButtonWriteMode write_mode; FuriString* file_path; - char text_store[IBUTTON_TEXT_STORE_SIZE + 1]; + char key_name[IBUTTON_KEY_NAME_SIZE + 1]; Submenu* submenu; ByteInput* byte_input; TextInput* text_input; Popup* popup; Widget* widget; - DialogEx* dialog_ex; - - void* rpc_ctx; + Loading* loading; }; typedef enum { @@ -61,7 +71,7 @@ typedef enum { iButtonViewTextInput, iButtonViewPopup, iButtonViewWidget, - iButtonViewDialogEx, + iButtonViewLoading, } iButtonView; typedef enum { @@ -78,10 +88,12 @@ typedef enum { iButtonNotificationMessageBlinkStop, } iButtonNotificationMessage; -bool ibutton_file_select(iButton* ibutton); -bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog); -bool ibutton_save_key(iButton* ibutton, const char* key_name); +bool ibutton_select_and_load_key(iButton* ibutton); +bool ibutton_load_key(iButton* ibutton); +bool ibutton_save_key(iButton* ibutton); bool ibutton_delete_key(iButton* ibutton); -void ibutton_text_store_set(iButton* ibutton, const char* text, ...); -void ibutton_text_store_clear(iButton* ibutton); +void ibutton_reset_key(iButton* ibutton); void ibutton_notification_message(iButton* ibutton, uint32_t message); + +void ibutton_submenu_callback(void* context, uint32_t index); +void ibutton_widget_callback(GuiButtonType result, InputType type, void* context); diff --git a/applications/main/ibutton/scenes/ibutton_scene_add_type.c b/applications/main/ibutton/scenes/ibutton_scene_add_type.c index 38373999c..55e05f20d 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_add_type.c +++ b/applications/main/ibutton/scenes/ibutton_scene_add_type.c @@ -1,54 +1,57 @@ #include "../ibutton_i.h" -enum SubmenuIndex { - SubmenuIndexCyfral, - SubmenuIndexDallas, - SubmenuIndexMetakom, -}; - -void ibutton_scene_add_type_submenu_callback(void* context, uint32_t index) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); -} - void ibutton_scene_add_type_on_enter(void* context) { iButton* ibutton = context; Submenu* submenu = ibutton->submenu; - submenu_add_item( - submenu, "Cyfral", SubmenuIndexCyfral, ibutton_scene_add_type_submenu_callback, ibutton); - submenu_add_item( - submenu, "Dallas", SubmenuIndexDallas, ibutton_scene_add_type_submenu_callback, ibutton); - submenu_add_item( - submenu, "Metakom", SubmenuIndexMetakom, ibutton_scene_add_type_submenu_callback, ibutton); + FuriString* tmp = furi_string_alloc(); - submenu_set_selected_item( - submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddType)); + for(uint32_t protocol_id = 0; protocol_id < ibutton_protocols_get_protocol_count(); + ++protocol_id) { + if((strcmp( + ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id), + ibutton_protocols_get_name(ibutton->protocols, protocol_id)) != 0) && + (strcmp(ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id), "N/A") != + 0)) { + furi_string_printf( + tmp, + "%s %s", + ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id), + ibutton_protocols_get_name(ibutton->protocols, protocol_id)); + } else { + furi_string_printf( + tmp, "%s", ibutton_protocols_get_name(ibutton->protocols, protocol_id)); + } + + submenu_add_item( + submenu, furi_string_get_cstr(tmp), protocol_id, ibutton_submenu_callback, context); + } + + const uint32_t prev_protocol_id = + scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddType); + submenu_set_selected_item(submenu, prev_protocol_id); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); + furi_string_free(tmp); } bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) { iButton* ibutton = context; iButtonKey* key = ibutton->key; + bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneAddType, event.event); - consumed = true; - if(event.event == SubmenuIndexCyfral) { - ibutton_key_set_type(key, iButtonKeyCyfral); - } else if(event.event == SubmenuIndexDallas) { - ibutton_key_set_type(key, iButtonKeyDS1990); - } else if(event.event == SubmenuIndexMetakom) { - ibutton_key_set_type(key, iButtonKeyMetakom); - } else { - furi_crash("Unknown key type"); - } + const iButtonProtocolId protocol_id = event.event; - furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER); - ibutton_key_clear_data(key); + ibutton_key_reset(key); + ibutton_key_set_protocol_id(key, protocol_id); + ibutton_protocols_apply_edits(ibutton->protocols, key); + + scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneAddType, protocol_id); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); + + consumed = true; } return consumed; diff --git a/applications/main/ibutton/scenes/ibutton_scene_add_value.c b/applications/main/ibutton/scenes/ibutton_scene_add_value.c index ccac76121..dc340771b 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_add_value.c +++ b/applications/main/ibutton/scenes/ibutton_scene_add_value.c @@ -1,42 +1,52 @@ #include "../ibutton_i.h" -void ibutton_scene_add_type_byte_input_callback(void* context) { +static void ibutton_scene_add_type_byte_input_callback(void* context) { iButton* ibutton = context; view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult); } +static void ibutton_scene_add_type_byte_changed_callback(void* context) { + iButton* ibutton = context; + view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditChanged); +} + void ibutton_scene_add_value_on_enter(void* context) { iButton* ibutton = context; - iButtonKey* key = ibutton->key; - uint8_t* new_key_data = malloc(IBUTTON_KEY_DATA_SIZE); + byte_input_set_header_text(ibutton->byte_input, "Enter the key"); - scene_manager_set_scene_state( - ibutton->scene_manager, iButtonSceneAddValue, (uint32_t)new_key_data); - memcpy(new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)); + iButtonEditableData editable_data; + ibutton_protocols_get_editable_data(ibutton->protocols, ibutton->key, &editable_data); byte_input_set_result_callback( ibutton->byte_input, ibutton_scene_add_type_byte_input_callback, - NULL, - ibutton, - new_key_data, - ibutton_key_get_data_size(key)); + ibutton_scene_add_type_byte_changed_callback, + context, + editable_data.ptr, + editable_data.size); - byte_input_set_header_text(ibutton->byte_input, "Enter the key"); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewByteInput); } bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) { iButton* ibutton = context; - uint8_t* new_key_data = - (uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue); + SceneManager* scene_manager = ibutton->scene_manager; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == iButtonCustomEventByteEditResult) { - ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE); - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); + scene_manager_next_scene(scene_manager, iButtonSceneSaveName); + } else if(event.event == iButtonCustomEventByteEditChanged) { + ibutton_protocols_apply_edits(ibutton->protocols, ibutton->key); + } + } else if(event.type == SceneManagerEventTypeBack) { + // User cancelled editing, reload the key from storage + if(scene_manager_has_previous_scene(scene_manager, iButtonSceneSavedKeyMenu)) { + if(!ibutton_load_key(ibutton)) { + consumed = scene_manager_search_and_switch_to_previous_scene( + scene_manager, iButtonSceneStart); + } } } @@ -45,10 +55,7 @@ bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) { void ibutton_scene_add_value_on_exit(void* context) { iButton* ibutton = context; - uint8_t* new_key_data = - (uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue); byte_input_set_result_callback(ibutton->byte_input, NULL, NULL, NULL, NULL, 0); byte_input_set_header_text(ibutton->byte_input, NULL); - free(new_key_data); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_config.h b/applications/main/ibutton/scenes/ibutton_scene_config.h index 87fa1a036..79f6791b3 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_config.h +++ b/applications/main/ibutton/scenes/ibutton_scene_config.h @@ -6,8 +6,7 @@ ADD_SCENE(ibutton, info, Info) ADD_SCENE(ibutton, read, Read) ADD_SCENE(ibutton, read_key_menu, ReadKeyMenu) ADD_SCENE(ibutton, read_success, ReadSuccess) -ADD_SCENE(ibutton, read_crc_error, ReadCRCError) -ADD_SCENE(ibutton, read_not_key_error, ReadNotKeyError) +ADD_SCENE(ibutton, read_error, ReadError) ADD_SCENE(ibutton, select_key, SelectKey) ADD_SCENE(ibutton, add_type, AddType) ADD_SCENE(ibutton, add_value, AddValue) @@ -18,4 +17,5 @@ ADD_SCENE(ibutton, delete_confirm, DeleteConfirm) ADD_SCENE(ibutton, delete_success, DeleteSuccess) ADD_SCENE(ibutton, retry_confirm, RetryConfirm) ADD_SCENE(ibutton, exit_confirm, ExitConfirm) +ADD_SCENE(ibutton, view_data, ViewData) ADD_SCENE(ibutton, rpc, Rpc) diff --git a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c index 3d609e833..587cb748c 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c +++ b/applications/main/ibutton/scenes/ibutton_scene_delete_confirm.c @@ -1,74 +1,29 @@ #include "../ibutton_i.h" #include -static void ibutton_scene_delete_confirm_widget_callback( - GuiButtonType result, - InputType type, - void* context) { - iButton* ibutton = context; - if(type == InputTypeShort) { - view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); - } -} - void ibutton_scene_delete_confirm_on_enter(void* context) { iButton* ibutton = context; - Widget* widget = ibutton->widget; iButtonKey* key = ibutton->key; - const uint8_t* key_data = ibutton_key_get_data_p(key); + Widget* widget = ibutton->widget; - FuriString* key_name; - key_name = furi_string_alloc(); - path_extract_filename(ibutton->file_path, key_name, true); + FuriString* tmp = furi_string_alloc(); - ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", furi_string_get_cstr(key_name)); - widget_add_text_box_element( - widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true); + widget_add_button_element(widget, GuiButtonTypeLeft, "Back", ibutton_widget_callback, context); widget_add_button_element( - widget, GuiButtonTypeLeft, "Cancel", ibutton_scene_delete_confirm_widget_callback, ibutton); - widget_add_button_element( - widget, - GuiButtonTypeRight, - "Delete", - ibutton_scene_delete_confirm_widget_callback, - ibutton); + widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context); - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - ibutton_text_store_set( - ibutton, - "%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - widget_add_string_element( - widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Dallas"); - break; - - case iButtonKeyCyfral: - ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); - widget_add_string_element( - widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Cyfral"); - break; - - case iButtonKeyMetakom: - ibutton_text_store_set( - ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - widget_add_string_element( - widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Metakom"); - break; - } + furi_string_printf(tmp, "Delete %s?", ibutton->key_name); widget_add_string_element( - widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store); + widget, 128 / 2, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp)); + + furi_string_reset(tmp); + ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp); + + widget_add_string_multiline_element( + widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); - - furi_string_free(key_name); + furi_string_free(tmp); } bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) { @@ -81,8 +36,10 @@ bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent even if(event.event == GuiButtonTypeRight) { if(ibutton_delete_key(ibutton)) { scene_manager_next_scene(scene_manager, iButtonSceneDeleteSuccess); + } else { + dialog_message_show_storage_error(ibutton->dialogs, "Cannot delete\nkey file"); + scene_manager_previous_scene(scene_manager); } - //TODO: What if the key could not be deleted? } else if(event.event == GuiButtonTypeLeft) { scene_manager_previous_scene(scene_manager); } @@ -93,6 +50,5 @@ bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent even void ibutton_scene_delete_confirm_on_exit(void* context) { iButton* ibutton = context; - ibutton_text_store_clear(ibutton); widget_reset(ibutton->widget); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_emulate.c b/applications/main/ibutton/scenes/ibutton_scene_emulate.c index 6f6ffcf57..713b8331c 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_emulate.c +++ b/applications/main/ibutton/scenes/ibutton_scene_emulate.c @@ -14,61 +14,32 @@ static void ibutton_scene_emulate_callback(void* context, bool emulated) { void ibutton_scene_emulate_on_enter(void* context) { iButton* ibutton = context; - Widget* widget = ibutton->widget; iButtonKey* key = ibutton->key; - const uint8_t* key_data = ibutton_key_get_data_p(key); + Widget* widget = ibutton->widget; + FuriString* tmp = furi_string_alloc(); - FuriString* key_name; - key_name = furi_string_alloc(); - if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); - } + widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44); - // check that stored key has name - if(!furi_string_empty(key_name)) { - ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); - } else { - // if not, show key data - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - ibutton_text_store_set( - ibutton, - "%02X %02X %02X %02X\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - break; - case iButtonKeyCyfral: - ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); - break; - case iButtonKeyMetakom: - ibutton_text_store_set( - ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - break; - } - } + furi_string_printf( + tmp, + "%s\n[%s]", + furi_string_empty(ibutton->file_path) ? "Unsaved Key" : ibutton->key_name, + ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key))); + + widget_add_text_box_element( + widget, 52, 38, 75, 26, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true); widget_add_string_multiline_element( - widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nemulating"); - widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44); - widget_add_text_box_element( - widget, 54, 39, 75, 22, AlignCenter, AlignCenter, ibutton->text_store, true); + widget, 88, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nemulating"); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); - - ibutton_worker_emulate_set_callback( - ibutton->key_worker, ibutton_scene_emulate_callback, ibutton); - ibutton_worker_emulate_start(ibutton->key_worker, key); - - furi_string_free(key_name); + ibutton_worker_emulate_set_callback(ibutton->worker, ibutton_scene_emulate_callback, ibutton); + ibutton_worker_emulate_start(ibutton->worker, key); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + + furi_string_free(tmp); } bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) { @@ -78,8 +49,7 @@ bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeTick) { uint32_t cnt = scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate); if(cnt > 0) { - cnt--; - if(cnt == 0) { + if(--cnt == 0) { ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink); } scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneEmulate, cnt); @@ -101,7 +71,7 @@ bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) { void ibutton_scene_emulate_on_exit(void* context) { iButton* ibutton = context; - ibutton_worker_stop(ibutton->key_worker); + ibutton_worker_stop(ibutton->worker); widget_reset(ibutton->widget); ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_info.c b/applications/main/ibutton/scenes/ibutton_scene_info.c index 15648f6f2..cf44d6a86 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_info.c +++ b/applications/main/ibutton/scenes/ibutton_scene_info.c @@ -1,66 +1,54 @@ #include "../ibutton_i.h" -#include void ibutton_scene_info_on_enter(void* context) { iButton* ibutton = context; - Widget* widget = ibutton->widget; iButtonKey* key = ibutton->key; + Widget* widget = ibutton->widget; - const uint8_t* key_data = ibutton_key_get_data_p(key); + const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key); - FuriString* key_name; - key_name = furi_string_alloc(); - path_extract_filename(ibutton->file_path, key_name, true); + FuriString* tmp = furi_string_alloc(); + + furi_string_printf( + tmp, + "\e#%s [%s]\e#", + ibutton->key_name, + ibutton_protocols_get_name(ibutton->protocols, protocol_id)); - ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); widget_add_text_box_element( - widget, 0, 0, 128, 23, AlignCenter, AlignCenter, ibutton->text_store, true); + widget, 0, 2, 128, 12, AlignLeft, AlignTop, furi_string_get_cstr(tmp), true); - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - ibutton_text_store_set( - ibutton, - "%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - widget_add_string_element(widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Dallas"); - break; + furi_string_reset(tmp); + ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp); - case iButtonKeyMetakom: - ibutton_text_store_set( - ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - widget_add_string_element( - widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Metakom"); - break; + widget_add_string_multiline_element( + widget, 0, 16, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); - case iButtonKeyCyfral: - ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); - widget_add_string_element(widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Cyfral"); - break; + if(ibutton_protocols_get_features(ibutton->protocols, protocol_id) & + iButtonProtocolFeatureExtData) { + widget_add_button_element( + widget, GuiButtonTypeRight, "More", ibutton_widget_callback, context); } - widget_add_string_element( - widget, 64, 50, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); - - furi_string_free(key_name); + furi_string_free(tmp); } bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); - return false; + iButton* ibutton = context; + bool consumed = false; + + if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneViewData); + } + } + + return consumed; } void ibutton_scene_info_on_exit(void* context) { iButton* ibutton = context; - ibutton_text_store_clear(ibutton); widget_reset(ibutton->widget); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_read.c b/applications/main/ibutton/scenes/ibutton_scene_read.c index 1ccd2562b..96bee7961 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_read.c +++ b/applications/main/ibutton/scenes/ibutton_scene_read.c @@ -11,14 +11,13 @@ void ibutton_scene_read_on_enter(void* context) { iButton* ibutton = context; Popup* popup = ibutton->popup; iButtonKey* key = ibutton->key; - iButtonWorker* worker = ibutton->key_worker; + iButtonWorker* worker = ibutton->worker; popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); popup_set_icon(popup, 0, 5, XTREME_ASSETS()->I_DolphinWait_61x59); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); - furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER); ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton); ibutton_worker_read_start(worker, key); @@ -36,25 +35,14 @@ bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) { } else if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == iButtonCustomEventWorkerRead) { - bool success = false; - iButtonKey* key = ibutton->key; - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - if(!ibutton_key_dallas_crc_is_valid(key)) { - scene_manager_next_scene(scene_manager, iButtonSceneReadCRCError); - } else if(!ibutton_key_dallas_is_1990_key(key)) { - scene_manager_next_scene(scene_manager, iButtonSceneReadNotKeyError); - } else { - success = true; - } - } else { - success = true; - } - - if(success) { + if(ibutton_protocols_is_valid(ibutton->protocols, ibutton->key)) { ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess); scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess); + DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess); + + } else { + scene_manager_next_scene(scene_manager, iButtonSceneReadError); } } } @@ -65,7 +53,7 @@ bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) { void ibutton_scene_read_on_exit(void* context) { iButton* ibutton = context; Popup* popup = ibutton->popup; - ibutton_worker_stop(ibutton->key_worker); + ibutton_worker_stop(ibutton->worker); popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); popup_set_icon(popup, 0, 0, NULL); diff --git a/applications/main/ibutton/scenes/ibutton_scene_read_crc_error.c b/applications/main/ibutton/scenes/ibutton_scene_read_crc_error.c deleted file mode 100644 index f822ff6a2..000000000 --- a/applications/main/ibutton/scenes/ibutton_scene_read_crc_error.c +++ /dev/null @@ -1,70 +0,0 @@ -#include "../ibutton_i.h" -#include - -static void ibutton_scene_read_crc_error_dialog_ex_callback(DialogExResult result, void* context) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); -} - -void ibutton_scene_read_crc_error_on_enter(void* context) { - iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; - iButtonKey* key = ibutton->key; - const uint8_t* key_data = ibutton_key_get_data_p(key); - - ibutton_text_store_set( - ibutton, - "%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7], - maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); - - dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_crc_error_dialog_ex_callback); - dialog_ex_set_context(dialog_ex, ibutton); - - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); - - ibutton_notification_message(ibutton, iButtonNotificationMessageError); - ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn); -} - -bool ibutton_scene_read_crc_error_on_event(void* context, SceneManagerEvent event) { - iButton* ibutton = context; - SceneManager* scene_manager = ibutton->scene_manager; - bool consumed = false; - - if(event.type == SceneManagerEventTypeBack) { - consumed = true; - scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm); - } else if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - if(event.event == DialogExResultRight) { - scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); - } else if(event.event == DialogExResultLeft) { - scene_manager_previous_scene(scene_manager); - } - } - - return consumed; -} - -void ibutton_scene_read_crc_error_on_exit(void* context) { - iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; - - ibutton_text_store_clear(ibutton); - - dialog_ex_reset(dialog_ex); - - ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff); -} diff --git a/applications/main/ibutton/scenes/ibutton_scene_read_error.c b/applications/main/ibutton/scenes/ibutton_scene_read_error.c new file mode 100644 index 000000000..e966384bf --- /dev/null +++ b/applications/main/ibutton/scenes/ibutton_scene_read_error.c @@ -0,0 +1,58 @@ +#include "../ibutton_i.h" +#include + +void ibutton_scene_read_error_on_enter(void* context) { + iButton* ibutton = context; + iButtonKey* key = ibutton->key; + + Widget* widget = ibutton->widget; + + FuriString* tmp = furi_string_alloc(); + + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", ibutton_widget_callback, context); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", ibutton_widget_callback, context); + + widget_add_string_element( + widget, 128 / 2, 2, AlignCenter, AlignTop, FontPrimary, "Read Error"); + + ibutton_protocols_render_error(ibutton->protocols, key, tmp); + + widget_add_string_multiline_element( + widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); + + ibutton_notification_message(ibutton, iButtonNotificationMessageError); + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + furi_string_free(tmp); +} + +bool ibutton_scene_read_error_on_event(void* context, SceneManagerEvent event) { + iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; + bool consumed = false; + + if(event.type == SceneManagerEventTypeBack) { + consumed = true; + scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm); + + } else if(event.type == SceneManagerEventTypeCustom) { + consumed = true; + if(event.event == GuiButtonTypeLeft) { + scene_manager_previous_scene(scene_manager); + } else if(event.event == GuiButtonTypeRight) { + scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); + } + } + + return consumed; +} + +void ibutton_scene_read_error_on_exit(void* context) { + iButton* ibutton = context; + + ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff); + widget_reset(ibutton->widget); +} diff --git a/applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c b/applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c index 0a8ecfa55..716f72c7d 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c +++ b/applications/main/ibutton/scenes/ibutton_scene_read_key_menu.c @@ -4,7 +4,9 @@ typedef enum { SubmenuIndexSave, SubmenuIndexEmulate, - SubmenuIndexWrite, + SubmenuIndexViewData, + SubmenuIndexWriteBlank, + SubmenuIndexWriteCopy, } SubmenuIndex; void ibutton_scene_read_key_menu_submenu_callback(void* context, uint32_t index) { @@ -16,6 +18,9 @@ void ibutton_scene_read_key_menu_on_enter(void* context) { iButton* ibutton = context; Submenu* submenu = ibutton->submenu; + const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(ibutton->key); + const uint32_t features = ibutton_protocols_get_features(ibutton->protocols, protocol_id); + submenu_add_item( submenu, "Save", SubmenuIndexSave, ibutton_scene_read_key_menu_submenu_callback, ibutton); submenu_add_item( @@ -24,36 +29,66 @@ void ibutton_scene_read_key_menu_on_enter(void* context) { SubmenuIndexEmulate, ibutton_scene_read_key_menu_submenu_callback, ibutton); - if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) { + + if(features & iButtonProtocolFeatureExtData) { submenu_add_item( submenu, - "Write", - SubmenuIndexWrite, + "View Data", + SubmenuIndexViewData, ibutton_scene_read_key_menu_submenu_callback, ibutton); } + + if(features & iButtonProtocolFeatureWriteBlank) { + submenu_add_item( + submenu, + "Write Blank", + SubmenuIndexWriteBlank, + ibutton_scene_read_key_menu_submenu_callback, + ibutton); + } + + if(features & iButtonProtocolFeatureWriteCopy) { + submenu_add_item( + submenu, + "Write Copy", + SubmenuIndexWriteCopy, + ibutton_scene_read_key_menu_submenu_callback, + ibutton); + } + submenu_set_selected_item( submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneReadKeyMenu)); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); } bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) { iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state( - ibutton->scene_manager, iButtonSceneReadKeyMenu, event.event); + scene_manager_set_scene_state(scene_manager, iButtonSceneReadKeyMenu, event.event); consumed = true; + if(event.event == SubmenuIndexSave) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName); + scene_manager_next_scene(scene_manager, iButtonSceneSaveName); } else if(event.event == SubmenuIndexEmulate) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + scene_manager_next_scene(scene_manager, iButtonSceneEmulate); DOLPHIN_DEED(DolphinDeedIbuttonEmulate); - } else if(event.event == SubmenuIndexWrite) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); + } else if(event.event == SubmenuIndexViewData) { + scene_manager_next_scene(scene_manager, iButtonSceneViewData); + } else if(event.event == SubmenuIndexWriteBlank) { + ibutton->write_mode = iButtonWriteModeBlank; + scene_manager_next_scene(scene_manager, iButtonSceneWrite); + } else if(event.event == SubmenuIndexWriteCopy) { + ibutton->write_mode = iButtonWriteModeCopy; + scene_manager_next_scene(scene_manager, iButtonSceneWrite); } + } else if(event.event == SceneManagerEventTypeBack) { + scene_manager_set_scene_state( + ibutton->scene_manager, iButtonSceneReadKeyMenu, SubmenuIndexSave); + // Event is not consumed } return consumed; diff --git a/applications/main/ibutton/scenes/ibutton_scene_read_not_key_error.c b/applications/main/ibutton/scenes/ibutton_scene_read_not_key_error.c deleted file mode 100644 index 8a7528031..000000000 --- a/applications/main/ibutton/scenes/ibutton_scene_read_not_key_error.c +++ /dev/null @@ -1,71 +0,0 @@ -#include "../ibutton_i.h" -#include - -static void - ibutton_scene_read_not_key_error_dialog_ex_callback(DialogExResult result, void* context) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); -} - -void ibutton_scene_read_not_key_error_on_enter(void* context) { - iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; - iButtonKey* key = ibutton->key; - const uint8_t* key_data = ibutton_key_get_data_p(key); - - ibutton_text_store_set( - ibutton, - "THIS IS NOT A KEY\n%02X %02X %02X %02X %02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7], - maxim_crc8(key_data, 7, MAXIM_CRC8_INIT)); - - dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter); - dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_not_key_error_dialog_ex_callback); - dialog_ex_set_context(dialog_ex, ibutton); - - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); - - ibutton_notification_message(ibutton, iButtonNotificationMessageError); - ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn); -} - -bool ibutton_scene_read_not_key_error_on_event(void* context, SceneManagerEvent event) { - iButton* ibutton = context; - SceneManager* scene_manager = ibutton->scene_manager; - bool consumed = false; - - if(event.type == SceneManagerEventTypeBack) { - consumed = true; - scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm); - } else if(event.type == SceneManagerEventTypeCustom) { - consumed = true; - if(event.event == DialogExResultRight) { - scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); - } else if(event.event == DialogExResultLeft) { - scene_manager_previous_scene(scene_manager); - } - } - - return consumed; -} - -void ibutton_scene_read_not_key_error_on_exit(void* context) { - iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; - - ibutton_text_store_clear(ibutton); - - dialog_ex_reset(dialog_ex); - - ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff); -} diff --git a/applications/main/ibutton/scenes/ibutton_scene_read_success.c b/applications/main/ibutton/scenes/ibutton_scene_read_success.c index 749e7af37..2e50bc996 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_read_success.c +++ b/applications/main/ibutton/scenes/ibutton_scene_read_success.c @@ -1,55 +1,40 @@ #include "../ibutton_i.h" -#include -static void ibutton_scene_read_success_dialog_ex_callback(DialogExResult result, void* context) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, result); -} +#include void ibutton_scene_read_success_on_enter(void* context) { iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; iButtonKey* key = ibutton->key; - const uint8_t* key_data = ibutton_key_get_data_p(key); + Widget* widget = ibutton->widget; - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - ibutton_text_store_set( - ibutton, - "Dallas\n%02X %02X %02X %02X\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - break; - case iButtonKeyCyfral: - ibutton_text_store_set(ibutton, "Cyfral\n%02X %02X", key_data[0], key_data[1]); - break; - case iButtonKeyMetakom: - ibutton_text_store_set( - ibutton, - "Metakom\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3]); - break; - } + FuriString* tmp = furi_string_alloc(); - dialog_ex_set_text(dialog_ex, ibutton->text_store, 95, 30, AlignCenter, AlignCenter); - dialog_ex_set_left_button_text(dialog_ex, "Retry"); - dialog_ex_set_right_button_text(dialog_ex, "More"); - dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63); - dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_success_dialog_ex_callback); - dialog_ex_set_context(dialog_ex, ibutton); + const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx); + widget_add_button_element( + widget, GuiButtonTypeLeft, "Retry", ibutton_widget_callback, context); + widget_add_button_element( + widget, GuiButtonTypeRight, "More", ibutton_widget_callback, context); + furi_string_printf( + tmp, + "%s[%s]", + ibutton_protocols_get_name(ibutton->protocols, protocol_id), + ibutton_protocols_get_manufacturer(ibutton->protocols, protocol_id)); + + widget_add_string_element( + widget, 0, 2, AlignLeft, AlignTop, FontPrimary, furi_string_get_cstr(tmp)); + + furi_string_reset(tmp); + ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp); + + widget_add_string_multiline_element( + widget, 0, 16, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp)); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn); + + furi_string_free(tmp); } bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) { @@ -62,9 +47,9 @@ bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm); } else if(event.type == SceneManagerEventTypeCustom) { consumed = true; - if(event.event == DialogExResultRight) { + if(event.event == GuiButtonTypeRight) { scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu); - } else if(event.event == DialogExResultLeft) { + } else if(event.event == GuiButtonTypeLeft) { scene_manager_next_scene(scene_manager, iButtonSceneRetryConfirm); } } @@ -74,11 +59,8 @@ bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) void ibutton_scene_read_success_on_exit(void* context) { iButton* ibutton = context; - DialogEx* dialog_ex = ibutton->dialog_ex; - ibutton_text_store_clear(ibutton); - - dialog_ex_reset(dialog_ex); + widget_reset(ibutton->widget); ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff); } diff --git a/applications/main/ibutton/scenes/ibutton_scene_rpc.c b/applications/main/ibutton/scenes/ibutton_scene_rpc.c index b25b1b8dd..9205eb4b4 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_rpc.c +++ b/applications/main/ibutton/scenes/ibutton_scene_rpc.c @@ -1,6 +1,4 @@ #include "../ibutton_i.h" -#include -#include void ibutton_scene_rpc_on_enter(void* context) { iButton* ibutton = context; @@ -17,8 +15,6 @@ void ibutton_scene_rpc_on_enter(void* context) { } bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { - UNUSED(context); - UNUSED(event); iButton* ibutton = context; Popup* popup = ibutton->popup; @@ -26,40 +22,32 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; - if(event.event == iButtonCustomEventRpcLoad) { - const char* arg = rpc_system_app_get_data(ibutton->rpc_ctx); - bool result = false; - if(arg && (furi_string_empty(ibutton->file_path))) { - furi_string_set(ibutton->file_path, arg); - if(ibutton_load_key_data(ibutton, ibutton->file_path, false)) { - ibutton_worker_emulate_start(ibutton->key_worker, ibutton->key); - FuriString* key_name; - key_name = furi_string_alloc(); - if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); - } - if(!furi_string_empty(key_name)) { - ibutton_text_store_set( - ibutton, "emulating\n%s", furi_string_get_cstr(key_name)); - } else { - ibutton_text_store_set(ibutton, "emulating"); - } - popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop); + if(event.event == iButtonCustomEventRpcLoad) { + bool result = false; + const char* file_path = rpc_system_app_get_data(ibutton->rpc); + + if(file_path && (furi_string_empty(ibutton->file_path))) { + furi_string_set(ibutton->file_path, file_path); + + if(ibutton_load_key(ibutton)) { + popup_set_text(popup, ibutton->key_name, 82, 32, AlignCenter, AlignTop); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + ibutton_worker_emulate_start(ibutton->worker, ibutton->key); - furi_string_free(key_name); result = true; - } else { - furi_string_reset(ibutton->file_path); } } - rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventLoadFile, result); + + rpc_system_app_confirm(ibutton->rpc, RpcAppEventLoadFile, result); + } else if(event.event == iButtonCustomEventRpcExit) { - rpc_system_app_confirm(ibutton->rpc_ctx, RpcAppEventAppExit, true); + rpc_system_app_confirm(ibutton->rpc, RpcAppEventAppExit, true); scene_manager_stop(ibutton->scene_manager); view_dispatcher_stop(ibutton->view_dispatcher); + } else if(event.event == iButtonCustomEventRpcSessionClose) { scene_manager_stop(ibutton->scene_manager); view_dispatcher_stop(ibutton->view_dispatcher); diff --git a/applications/main/ibutton/scenes/ibutton_scene_save_name.c b/applications/main/ibutton/scenes/ibutton_scene_save_name.c index 5f25a0002..4ad0315e5 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_save_name.c +++ b/applications/main/ibutton/scenes/ibutton_scene_save_name.c @@ -1,6 +1,8 @@ #include "../ibutton_i.h" -#include + +#include #include + #include static void ibutton_scene_save_name_text_input_callback(void* context) { @@ -12,17 +14,10 @@ void ibutton_scene_save_name_on_enter(void* context) { iButton* ibutton = context; TextInput* text_input = ibutton->text_input; - FuriString* key_name; - key_name = furi_string_alloc(); - if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); - } + const bool is_new_file = furi_string_empty(ibutton->file_path); - const bool key_name_is_empty = furi_string_empty(key_name); - if(key_name_is_empty) { - set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE); - } else { - ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); + if(is_new_file) { + set_random_name(ibutton->key_name, IBUTTON_KEY_NAME_SIZE); } text_input_set_header_text(text_input, "Name the key"); @@ -30,23 +25,15 @@ void ibutton_scene_save_name_on_enter(void* context) { text_input, ibutton_scene_save_name_text_input_callback, ibutton, - ibutton->text_store, + ibutton->key_name, IBUTTON_KEY_NAME_SIZE, - key_name_is_empty); + is_new_file); - FuriString* folder_path; - folder_path = furi_string_alloc(); - - path_extract_dirname(furi_string_get_cstr(ibutton->file_path), folder_path); - - ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( - furi_string_get_cstr(folder_path), IBUTTON_APP_EXTENSION, furi_string_get_cstr(key_name)); + ValidatorIsFile* validator_is_file = + validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, ibutton->key_name); text_input_set_validator(text_input, validator_is_file_callback, validator_is_file); view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput); - - furi_string_free(key_name); - furi_string_free(folder_path); } bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { @@ -56,8 +43,16 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { if(event.type == SceneManagerEventTypeCustom) { consumed = true; if(event.event == iButtonCustomEventTextEditResult) { - if(ibutton_save_key(ibutton, ibutton->text_store)) { + furi_string_printf( + ibutton->file_path, + "%s/%s%s", + IBUTTON_APP_FOLDER, + ibutton->key_name, + IBUTTON_APP_EXTENSION); + + if(ibutton_save_key(ibutton)) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess); + if(scene_manager_has_previous_scene( ibutton->scene_manager, iButtonSceneSavedKeyMenu)) { // Nothing, do not count editing as saving @@ -67,6 +62,7 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) { } else { DOLPHIN_DEED(DolphinDeedIbuttonSave); } + } else { const uint32_t possible_scenes[] = { iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType}; diff --git a/applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c b/applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c index e4c9c350a..80fca28b5 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c +++ b/applications/main/ibutton/scenes/ibutton_scene_saved_key_menu.c @@ -3,72 +3,70 @@ enum SubmenuIndex { SubmenuIndexEmulate, - SubmenuIndexWrite, + SubmenuIndexWriteBlank, + SubmenuIndexWriteCopy, SubmenuIndexEdit, SubmenuIndexDelete, SubmenuIndexInfo, }; -void ibutton_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); -} - void ibutton_scene_saved_key_menu_on_enter(void* context) { iButton* ibutton = context; Submenu* submenu = ibutton->submenu; - submenu_add_item( - submenu, - "Emulate", - SubmenuIndexEmulate, - ibutton_scene_saved_key_menu_submenu_callback, - ibutton); - if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) { + const uint32_t features = ibutton_protocols_get_features( + ibutton->protocols, ibutton_key_get_protocol_id(ibutton->key)); + + submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, ibutton_submenu_callback, ibutton); + + if(features & iButtonProtocolFeatureWriteBlank) { submenu_add_item( - submenu, - "Write", - SubmenuIndexWrite, - ibutton_scene_saved_key_menu_submenu_callback, - ibutton); + submenu, "Write Blank", SubmenuIndexWriteBlank, ibutton_submenu_callback, ibutton); } - submenu_add_item( - submenu, "Edit", SubmenuIndexEdit, ibutton_scene_saved_key_menu_submenu_callback, ibutton); - submenu_add_item( - submenu, - "Delete", - SubmenuIndexDelete, - ibutton_scene_saved_key_menu_submenu_callback, - ibutton); - submenu_add_item( - submenu, "Info", SubmenuIndexInfo, ibutton_scene_saved_key_menu_submenu_callback, ibutton); + + if(features & iButtonProtocolFeatureWriteCopy) { + submenu_add_item( + submenu, "Write Copy", SubmenuIndexWriteCopy, ibutton_submenu_callback, ibutton); + } + + submenu_add_item(submenu, "Edit", SubmenuIndexEdit, ibutton_submenu_callback, ibutton); + submenu_add_item(submenu, "Delete", SubmenuIndexDelete, ibutton_submenu_callback, ibutton); + submenu_add_item(submenu, "Info", SubmenuIndexInfo, ibutton_submenu_callback, ibutton); submenu_set_selected_item( submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneSavedKeyMenu)); - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu); } bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) { iButton* ibutton = context; + SceneManager* scene_manager = ibutton->scene_manager; bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - scene_manager_set_scene_state( - ibutton->scene_manager, iButtonSceneSavedKeyMenu, event.event); + scene_manager_set_scene_state(scene_manager, iButtonSceneSavedKeyMenu, event.event); consumed = true; if(event.event == SubmenuIndexEmulate) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate); + scene_manager_next_scene(scene_manager, iButtonSceneEmulate); DOLPHIN_DEED(DolphinDeedIbuttonEmulate); - } else if(event.event == SubmenuIndexWrite) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite); + } else if(event.event == SubmenuIndexWriteBlank) { + ibutton->write_mode = iButtonWriteModeBlank; + scene_manager_next_scene(scene_manager, iButtonSceneWrite); + } else if(event.event == SubmenuIndexWriteCopy) { + ibutton->write_mode = iButtonWriteModeCopy; + scene_manager_next_scene(scene_manager, iButtonSceneWrite); } else if(event.event == SubmenuIndexEdit) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue); + scene_manager_next_scene(scene_manager, iButtonSceneAddValue); } else if(event.event == SubmenuIndexDelete) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneDeleteConfirm); + scene_manager_next_scene(scene_manager, iButtonSceneDeleteConfirm); } else if(event.event == SubmenuIndexInfo) { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneInfo); + scene_manager_next_scene(scene_manager, iButtonSceneInfo); } + + } else if(event.type == SceneManagerEventTypeBack) { + scene_manager_set_scene_state( + scene_manager, iButtonSceneSavedKeyMenu, SubmenuIndexEmulate); + // Event is not consumed } return consumed; diff --git a/applications/main/ibutton/scenes/ibutton_scene_select_key.c b/applications/main/ibutton/scenes/ibutton_scene_select_key.c index 32169a9c0..ebd504b1f 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_select_key.c +++ b/applications/main/ibutton/scenes/ibutton_scene_select_key.c @@ -3,11 +3,11 @@ void ibutton_scene_select_key_on_enter(void* context) { iButton* ibutton = context; - if(!ibutton_file_select(ibutton)) { + if(ibutton_select_and_load_key(ibutton)) { + scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSavedKeyMenu); + } else { scene_manager_search_and_switch_to_previous_scene( ibutton->scene_manager, iButtonSceneStart); - } else { - scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSavedKeyMenu); } } diff --git a/applications/main/ibutton/scenes/ibutton_scene_start.c b/applications/main/ibutton/scenes/ibutton_scene_start.c index b8f6b07d6..37bf96f39 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_start.c +++ b/applications/main/ibutton/scenes/ibutton_scene_start.c @@ -8,21 +8,15 @@ enum SubmenuIndex { SubmenuIndexAdd, }; -void ibutton_scene_start_submenu_callback(void* context, uint32_t index) { - iButton* ibutton = context; - view_dispatcher_send_custom_event(ibutton->view_dispatcher, index); -} - void ibutton_scene_start_on_enter(void* context) { iButton* ibutton = context; Submenu* submenu = ibutton->submenu; - submenu_add_item( - submenu, "Read", SubmenuIndexRead, ibutton_scene_start_submenu_callback, ibutton); - submenu_add_item( - submenu, "Saved", SubmenuIndexSaved, ibutton_scene_start_submenu_callback, ibutton); - submenu_add_item( - submenu, "Add Manually", SubmenuIndexAdd, ibutton_scene_start_submenu_callback, ibutton); + ibutton_reset_key(ibutton); + + submenu_add_item(submenu, "Read", SubmenuIndexRead, ibutton_submenu_callback, ibutton); + submenu_add_item(submenu, "Saved", SubmenuIndexSaved, ibutton_submenu_callback, ibutton); + submenu_add_item(submenu, "Add Manually", SubmenuIndexAdd, ibutton_submenu_callback, ibutton); submenu_set_selected_item( submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneStart)); @@ -41,7 +35,6 @@ bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead); DOLPHIN_DEED(DolphinDeedIbuttonRead); } else if(event.event == SubmenuIndexSaved) { - furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER); scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey); } else if(event.event == SubmenuIndexAdd) { scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType); diff --git a/applications/main/ibutton/scenes/ibutton_scene_view_data.c b/applications/main/ibutton/scenes/ibutton_scene_view_data.c new file mode 100644 index 000000000..7e063d7ec --- /dev/null +++ b/applications/main/ibutton/scenes/ibutton_scene_view_data.c @@ -0,0 +1,26 @@ +#include "../ibutton_i.h" + +void ibutton_scene_view_data_on_enter(void* context) { + iButton* ibutton = context; + iButtonKey* key = ibutton->key; + Widget* widget = ibutton->widget; + + FuriString* tmp = furi_string_alloc(); + ibutton_protocols_render_data(ibutton->protocols, key, tmp); + + widget_add_text_scroll_element(widget, 0, 0, 128, 64, furi_string_get_cstr(tmp)); + + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + furi_string_free(tmp); +} + +bool ibutton_scene_view_data_on_event(void* context, SceneManagerEvent event) { + UNUSED(context); + UNUSED(event); + return false; +} + +void ibutton_scene_view_data_on_exit(void* context) { + iButton* ibutton = context; + widget_reset(ibutton->widget); +} diff --git a/applications/main/ibutton/scenes/ibutton_scene_write.c b/applications/main/ibutton/scenes/ibutton_scene_write.c index cdea04db3..541aa1c52 100644 --- a/applications/main/ibutton/scenes/ibutton_scene_write.c +++ b/applications/main/ibutton/scenes/ibutton_scene_write.c @@ -1,5 +1,4 @@ #include "../ibutton_i.h" -#include "toolbox/path.h" typedef enum { iButtonSceneWriteStateDefault, @@ -13,61 +12,46 @@ static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult void ibutton_scene_write_on_enter(void* context) { iButton* ibutton = context; + furi_assert(ibutton->write_mode != iButtonWriteModeInvalid); + iButtonKey* key = ibutton->key; + iButtonWorker* worker = ibutton->worker; + const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key); + Widget* widget = ibutton->widget; - iButtonWorker* worker = ibutton->key_worker; + FuriString* tmp = furi_string_alloc(); - const uint8_t* key_data = ibutton_key_get_data_p(key); + widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44); - FuriString* key_name; - key_name = furi_string_alloc(); - if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) { - path_extract_filename(ibutton->file_path, key_name, true); - } + furi_string_printf( + tmp, + "%s\n[%s]", + ibutton->key_name, + ibutton_protocols_get_name(ibutton->protocols, protocol_id)); - // check that stored key has name - if(!furi_string_empty(key_name)) { - ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name)); - } else { - // if not, show key data - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - ibutton_text_store_set( - ibutton, - "%02X %02X %02X %02X\n%02X %02X %02X %02X", - key_data[0], - key_data[1], - key_data[2], - key_data[3], - key_data[4], - key_data[5], - key_data[6], - key_data[7]); - break; - case iButtonKeyCyfral: - ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]); - break; - case iButtonKeyMetakom: - ibutton_text_store_set( - ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); - break; - } + widget_add_text_box_element( + widget, 52, 38, 75, 26, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true); + + ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton); + + furi_string_set(tmp, "iButton\nwriting "); + + if(ibutton->write_mode == iButtonWriteModeBlank) { + furi_string_cat(tmp, "Blank"); + ibutton_worker_write_blank_start(worker, key); + + } else if(ibutton->write_mode == iButtonWriteModeCopy) { + furi_string_cat(tmp, "Copy"); + ibutton_worker_write_copy_start(worker, key); } widget_add_string_multiline_element( - widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nwriting"); - widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44); - widget_add_text_box_element( - widget, 54, 39, 75, 22, AlignCenter, AlignCenter, ibutton->text_store, true); - - view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); - - ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton); - ibutton_worker_write_start(worker, key); - - furi_string_free(key_name); + widget, 88, 10, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp)); ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart); + view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget); + + furi_string_free(tmp); } bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) { @@ -94,7 +78,9 @@ bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) { void ibutton_scene_write_on_exit(void* context) { iButton* ibutton = context; - ibutton_worker_stop(ibutton->key_worker); + ibutton->write_mode = iButtonWriteModeInvalid; + + ibutton_worker_stop(ibutton->worker); widget_reset(ibutton->widget); ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop); diff --git a/applications/main/subghz/helpers/subghz_types.h b/applications/main/subghz/helpers/subghz_types.h index 6e42c1523..3c5982427 100644 --- a/applications/main/subghz/helpers/subghz_types.h +++ b/applications/main/subghz/helpers/subghz_types.h @@ -54,6 +54,7 @@ typedef enum { SubGhzLoadKeyStateOK, SubGhzLoadKeyStateParseErr, SubGhzLoadKeyStateOnlyRx, + SubGhzLoadKeyStateProtocolDescriptionErr, } SubGhzLoadKeyState; /** SubGhzLock */ diff --git a/applications/main/subghz/scenes/subghz_scene_receiver_info.c b/applications/main/subghz/scenes/subghz_scene_receiver_info.c index fd28421a8..90046eb9d 100644 --- a/applications/main/subghz/scenes/subghz_scene_receiver_info.c +++ b/applications/main/subghz/scenes/subghz_scene_receiver_info.c @@ -27,8 +27,9 @@ static bool subghz_scene_receiver_info_update_parser(void* context) { subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( subghz->txrx->receiver, subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); + if(subghz->txrx->decoder_result) { - // In this case flipper format was changed to short file content + //todo we are trying to deserialize without checking for errors, since it is assumed that we just received this chignal subghz_protocol_decoder_base_deserialize( subghz->txrx->decoder_result, subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen)); @@ -138,7 +139,6 @@ bool subghz_scene_receiver_info_on_event(void* context, SceneManagerEvent event) subghz, subghz_history_get_raw_data( subghz->txrx->history, subghz->txrx->idx_menu_chosen))) { - scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx); if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) { subghz_tx_stop(subghz); } diff --git a/applications/main/subghz/scenes/subghz_scene_set_type.c b/applications/main/subghz/scenes/subghz_scene_set_type.c index 5c5d5db3b..bc76ee146 100644 --- a/applications/main/subghz/scenes/subghz_scene_set_type.c +++ b/applications/main/subghz/scenes/subghz_scene_set_type.c @@ -36,8 +36,9 @@ bool subghz_scene_set_type_submenu_gen_data_protocol( do { Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data); stream_clean(fff_data_stream); - if(!subghz_protocol_decoder_base_serialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset)) { + if(subghz_protocol_decoder_base_serialize( + subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset) != + SubGhzProtocolStatusOk) { FURI_LOG_E(TAG, "Unable to serialize"); break; } @@ -363,8 +364,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexSomfyTelis: subghz->txrx->transmitter = subghz_transmitter_alloc_init( subghz->txrx->environment, SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME); - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); if(subghz->txrx->transmitter) { subghz_protocol_somfy_telis_create_data( subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), @@ -387,8 +387,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexDoorHan_433_92: subghz->txrx->transmitter = subghz_transmitter_alloc_init( subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), @@ -436,8 +435,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexNiceFlorS_433_92: subghz->txrx->transmitter = subghz_transmitter_alloc_init( subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME); - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); if(subghz->txrx->transmitter) { subghz_protocol_nice_flor_s_create_data( subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), @@ -461,8 +459,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexNiceOne_433_92: subghz->txrx->transmitter = subghz_transmitter_alloc_init( subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME); - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); if(subghz->txrx->transmitter) { subghz_protocol_nice_flor_s_create_data( subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), @@ -486,8 +483,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) { case SubmenuIndexNiceSmilo_433_92: subghz->txrx->transmitter = subghz_transmitter_alloc_init( subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME); - subghz_preset_init( - subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0); + subghz_preset_init(subghz, "AM650", 433920000, NULL, 0); if(subghz->txrx->transmitter) { subghz_protocol_keeloq_create_data( subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter), diff --git a/applications/main/subghz/scenes/subghz_scene_transmitter.c b/applications/main/subghz/scenes/subghz_scene_transmitter.c index 00839170c..34685a8e5 100644 --- a/applications/main/subghz/scenes/subghz_scene_transmitter.c +++ b/applications/main/subghz/scenes/subghz_scene_transmitter.c @@ -14,9 +14,8 @@ void subghz_scene_transmitter_callback(SubGhzCustomEvent event, void* context) { } bool subghz_scene_transmitter_update_data_show(void* context) { - //ToDo Fix SubGhz* subghz = context; - + bool ret = false; if(subghz->txrx->decoder_result) { FuriString* key_str; FuriString* frequency_str; @@ -27,30 +26,29 @@ bool subghz_scene_transmitter_update_data_show(void* context) { modulation_str = furi_string_alloc(); uint8_t show_button = 0; - subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data); - subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, key_str); + if(subghz_protocol_decoder_base_deserialize( + subghz->txrx->decoder_result, subghz->txrx->fff_data) == SubGhzProtocolStatusOk) { + subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, key_str); - if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) == - SubGhzProtocolFlag_Send) { - show_button = 1; + if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) == + SubGhzProtocolFlag_Send) { + show_button = 1; + } + + subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); + subghz_view_transmitter_add_data_to_show( + subghz->subghz_transmitter, + furi_string_get_cstr(key_str), + furi_string_get_cstr(frequency_str), + furi_string_get_cstr(modulation_str), + show_button); + ret = true; } - - subghz_get_frequency_modulation(subghz, frequency_str, modulation_str); - subghz_view_transmitter_add_data_to_show( - subghz->subghz_transmitter, - furi_string_get_cstr(key_str), - furi_string_get_cstr(frequency_str), - furi_string_get_cstr(modulation_str), - show_button); - furi_string_free(frequency_str); furi_string_free(modulation_str); furi_string_free(key_str); - - return true; } - return false; + return ret; } void subghz_scene_transmitter_on_enter(void* context) { diff --git a/applications/main/subghz/subghz_i.c b/applications/main/subghz/subghz_i.c index c1a1a92ae..579a16520 100644 --- a/applications/main/subghz/subghz_i.c +++ b/applications/main/subghz/subghz_i.c @@ -154,7 +154,6 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { FURI_LOG_E(TAG, "Missing Protocol"); break; } - //ToDo FIX if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) { FURI_LOG_E(TAG, "Unable Repeat"); break; @@ -164,7 +163,8 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { subghz->txrx->environment, furi_string_get_cstr(temp_str)); if(subghz->txrx->transmitter) { - if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format)) { + if(subghz_transmitter_deserialize(subghz->txrx->transmitter, flipper_format) == + SubGhzProtocolStatusOk) { if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "") != 0) { subghz_begin( subghz, @@ -187,7 +187,12 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) { //Start TX furi_hal_subghz_start_async_tx( subghz_transmitter_yield, subghz->txrx->transmitter); + } else { + subghz_dialog_message_show_only_rx(subghz); } + } else { + dialog_message_show_storage_error( + subghz->dialogs, "Error in protocol\nparameters\ndescription"); } } if(!ret) { @@ -335,8 +340,10 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { subghz->txrx->decoder_result = subghz_receiver_search_decoder_base_by_name( subghz->txrx->receiver, furi_string_get_cstr(temp_str)); if(subghz->txrx->decoder_result) { - if(!subghz_protocol_decoder_base_deserialize( - subghz->txrx->decoder_result, subghz->txrx->fff_data)) { + SubGhzProtocolStatus status = subghz_protocol_decoder_base_deserialize( + subghz->txrx->decoder_result, subghz->txrx->fff_data); + if(status != SubGhzProtocolStatusOk) { + load_key_state = SubGhzLoadKeyStateProtocolDescriptionErr; break; } } else { @@ -357,6 +364,12 @@ bool subghz_key_load(SubGhz* subghz, const char* file_path, bool show_dialog) { dialog_message_show_storage_error(subghz->dialogs, "Cannot parse\nfile"); } return false; + case SubGhzLoadKeyStateProtocolDescriptionErr: + if(show_dialog) { + dialog_message_show_storage_error( + subghz->dialogs, "Error in protocol\nparameters\ndescription"); + } + return false; case SubGhzLoadKeyStateOnlyRx: if(show_dialog) { diff --git a/applications/plugins/hid_app/hid.c b/applications/plugins/hid_app/hid.c index 7f63f0cc6..949ff63b3 100644 --- a/applications/plugins/hid_app/hid.c +++ b/applications/plugins/hid_app/hid.c @@ -376,7 +376,17 @@ int32_t hid_ble_app(void* p) { // Wait 2nd core to update nvm storage furi_delay_ms(200); - bt_keys_storage_set_storage_path(app->bt, HID_BT_KEYS_STORAGE_PATH); + // Migrate data from old sd-card folder + Storage* storage = furi_record_open(RECORD_STORAGE); + + storage_common_migrate( + storage, + EXT_PATH("apps/Tools/" HID_BT_KEYS_STORAGE_NAME), + APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); + + bt_keys_storage_set_storage_path(app->bt, APP_DATA_PATH(HID_BT_KEYS_STORAGE_NAME)); + + furi_record_close(RECORD_STORAGE); if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) { FURI_LOG_E(TAG, "Failed to switch to HID profile"); diff --git a/applications/plugins/hid_app/hid.h b/applications/plugins/hid_app/hid.h index fe32a199b..8ed1664a3 100644 --- a/applications/plugins/hid_app/hid.h +++ b/applications/plugins/hid_app/hid.h @@ -23,7 +23,7 @@ #include "views/hid_mouse_jiggler.h" #include "views/hid_tiktok.h" -#define HID_BT_KEYS_STORAGE_PATH EXT_PATH("apps/Tools/.bt_hid.keys") +#define HID_BT_KEYS_STORAGE_NAME ".bt_hid.keys" typedef enum { HidTransportUsb, diff --git a/applications/plugins/ibtn_fuzzer/ibtnfuzzer.h b/applications/plugins/ibtn_fuzzer/ibtnfuzzer.h index 1db527f65..8e671fae0 100644 --- a/applications/plugins/ibtn_fuzzer/ibtnfuzzer.h +++ b/applications/plugins/ibtn_fuzzer/ibtnfuzzer.h @@ -78,7 +78,8 @@ typedef struct { uint8_t key_index; iButtonWorker* worker; iButtonKey* key; - iButtonKeyType keytype; + iButtonProtocolId keytype; + iButtonProtocols* protocols; bool workr_rund; bool enter_rerun; bool attack_stop_called; diff --git a/applications/plugins/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c b/applications/plugins/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c index e45035d6b..1cab8b04e 100644 --- a/applications/plugins/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c +++ b/applications/plugins/ibtn_fuzzer/scene/ibtnfuzzer_scene_run_attack.c @@ -72,14 +72,15 @@ void ibtnfuzzer_scene_run_attack_on_enter(iBtnFuzzerState* context) { context->time_between_cards = 8; context->attack_step = 0; context->attack_stop_called = false; - context->key = ibutton_key_alloc(); - context->worker = ibutton_worker_alloc(); + context->protocols = ibutton_protocols_alloc(); + context->key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(context->protocols)); + context->worker = ibutton_worker_alloc(context->protocols); if(context->proto == Metakom) { - context->keytype = iButtonKeyMetakom; + context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Metakom"); } else if(context->proto == Cyfral) { - context->keytype = iButtonKeyCyfral; + context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Cyfral"); } else { - context->keytype = iButtonKeyDS1990; + context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "DS1990"); } context->workr_rund = false; } @@ -90,8 +91,9 @@ void ibtnfuzzer_scene_run_attack_on_exit(iBtnFuzzerState* context) { ibutton_worker_stop_thread(context->worker); context->workr_rund = false; } - ibutton_worker_free(context->worker); ibutton_key_free(context->key); + ibutton_worker_free(context->worker); + ibutton_protocols_free(context->protocols); notification_message(context->notify, &sequence_blink_stop); } @@ -99,9 +101,14 @@ void ibtnfuzzer_scene_run_attack_on_tick(iBtnFuzzerState* context) { if(context->is_attacking) { if(1 == counter) { ibutton_worker_start_thread(context->worker); - ibutton_key_set_type(context->key, context->keytype); - ibutton_key_set_data( - context->key, context->payload, ibutton_key_get_size_by_type(context->keytype)); + ibutton_key_set_protocol_id(context->key, context->keytype); + iButtonEditableData data; + ibutton_protocols_get_editable_data(context->protocols, context->key, &data); + data.size = sizeof(context->payload); + for(size_t i = 0; i < data.size; i++) { + data.ptr[i] = context->payload[i]; + } + ibutton_worker_emulate_start(context->worker, context->key); context->workr_rund = true; } else if(0 == counter) { diff --git a/applications/plugins/picopass/helpers/iclass_elite_dict.c b/applications/plugins/picopass/helpers/iclass_elite_dict.c index 455eb23c1..e8c13dd1d 100644 --- a/applications/plugins/picopass/helpers/iclass_elite_dict.c +++ b/applications/plugins/picopass/helpers/iclass_elite_dict.c @@ -3,8 +3,8 @@ #include #include -#define ICLASS_ELITE_DICT_FLIPPER_PATH EXT_PATH("picopass/assets/iclass_elite_dict.txt") -#define ICLASS_ELITE_DICT_USER_PATH EXT_PATH("picopass/assets/iclass_elite_dict_user.txt") +#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt") +#define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt") #define TAG "IclassEliteDict" @@ -21,10 +21,10 @@ bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) { bool dict_present = false; if(dict_type == IclassEliteDictTypeFlipper) { - dict_present = storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_PATH, NULL) == - FSE_OK; + dict_present = + (storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK); } else if(dict_type == IclassEliteDictTypeUser) { - dict_present = storage_common_stat(storage, ICLASS_ELITE_DICT_USER_PATH, NULL) == FSE_OK; + dict_present = (storage_common_stat(storage, ICLASS_ELITE_DICT_USER_NAME, NULL) == FSE_OK); } furi_record_close(RECORD_STORAGE); @@ -36,27 +36,26 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) { IclassEliteDict* dict = malloc(sizeof(IclassEliteDict)); Storage* storage = furi_record_open(RECORD_STORAGE); dict->stream = buffered_file_stream_alloc(storage); - furi_record_close(RECORD_STORAGE); FuriString* next_line = furi_string_alloc(); bool dict_loaded = false; do { if(dict_type == IclassEliteDictTypeFlipper) { if(!buffered_file_stream_open( - dict->stream, ICLASS_ELITE_DICT_FLIPPER_PATH, FSAM_READ, FSOM_OPEN_EXISTING)) { + dict->stream, ICLASS_ELITE_DICT_FLIPPER_NAME, FSAM_READ, FSOM_OPEN_EXISTING)) { buffered_file_stream_close(dict->stream); break; } } else if(dict_type == IclassEliteDictTypeUser) { if(!buffered_file_stream_open( - dict->stream, ICLASS_ELITE_DICT_USER_PATH, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { + dict->stream, ICLASS_ELITE_DICT_USER_NAME, FSAM_READ_WRITE, FSOM_OPEN_ALWAYS)) { buffered_file_stream_close(dict->stream); break; } } // Read total amount of keys - while(true) { + while(true) { //-V547 if(!stream_read_line(dict->stream, next_line)) break; if(furi_string_get_char(next_line, 0) == '#') continue; if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) continue; @@ -69,12 +68,13 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) { FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys); } while(false); - if(!dict_loaded) { + if(!dict_loaded) { //-V547 buffered_file_stream_close(dict->stream); free(dict); dict = NULL; } + furi_record_close(RECORD_STORAGE); furi_string_free(next_line); return dict; diff --git a/applications/plugins/picopass/picopass.c b/applications/plugins/picopass/picopass.c index bedaf38ef..c1428b2fb 100644 --- a/applications/plugins/picopass/picopass.c +++ b/applications/plugins/picopass/picopass.c @@ -171,6 +171,12 @@ void picopass_show_loading_popup(void* context, bool show) { } } +static void picopass_migrate_from_old_folder() { + Storage* storage = furi_record_open(RECORD_STORAGE); + storage_common_migrate(storage, "/ext/picopass", STORAGE_APP_DATA_PATH_PREFIX); + furi_record_close(RECORD_STORAGE); +} + bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) { bool result = size > 0; while(size > 0) { @@ -183,6 +189,8 @@ bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) int32_t picopass_app(void* p) { UNUSED(p); + picopass_migrate_from_old_folder(); + Picopass* picopass = picopass_alloc(); scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart); diff --git a/applications/plugins/picopass/picopass_device.c b/applications/plugins/picopass/picopass_device.c index a5414b92b..0c48505ec 100644 --- a/applications/plugins/picopass/picopass_device.c +++ b/applications/plugins/picopass/picopass_device.c @@ -48,13 +48,9 @@ static bool picopass_device_save_file( if(use_load_path && !furi_string_empty(dev->load_path)) { // Get directory name path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str); - // Create picopass directory if necessary - if(!storage_simply_mkdir(dev->storage, furi_string_get_cstr(temp_str))) break; // Make path to file to save furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension); } else { - // Create picopass directory if necessary - if(!storage_simply_mkdir(dev->storage, PICOPASS_APP_FOLDER)) break; // First remove picopass device file if it was saved furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension); } @@ -126,10 +122,11 @@ static bool picopass_device_save_file( bool picopass_device_save(PicopassDevice* dev, const char* dev_name) { if(dev->format == PicopassDeviceSaveFormatHF) { return picopass_device_save_file( - dev, dev_name, PICOPASS_APP_FOLDER, PICOPASS_APP_EXTENSION, true); + dev, dev_name, STORAGE_APP_DATA_PATH_PREFIX, PICOPASS_APP_EXTENSION, true); } else if(dev->format == PicopassDeviceSaveFormatLF) { return picopass_device_save_file(dev, dev_name, ANY_PATH("lfrfid"), ".rfid", true); } + return false; } @@ -225,13 +222,12 @@ void picopass_device_free(PicopassDevice* picopass_dev) { bool picopass_file_select(PicopassDevice* dev) { furi_assert(dev); - // Input events and views are managed by file_browser FuriString* picopass_app_folder; - picopass_app_folder = furi_string_alloc_set(PICOPASS_APP_FOLDER); + picopass_app_folder = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px); - browser_options.base_path = PICOPASS_APP_FOLDER; + browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; bool res = dialog_file_browser_show( dev->dialogs, dev->load_path, picopass_app_folder, &browser_options); @@ -274,7 +270,7 @@ bool picopass_device_delete(PicopassDevice* dev, bool use_load_path) { furi_string_set(file_path, dev->load_path); } else { furi_string_printf( - file_path, "%s/%s%s", PICOPASS_APP_FOLDER, dev->dev_name, PICOPASS_APP_EXTENSION); + file_path, APP_DATA_PATH("%s%s"), dev->dev_name, PICOPASS_APP_EXTENSION); } if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break; deleted = true; diff --git a/applications/plugins/picopass/picopass_device.h b/applications/plugins/picopass/picopass_device.h index 99f1ceea6..d7d0977df 100644 --- a/applications/plugins/picopass/picopass_device.h +++ b/applications/plugins/picopass/picopass_device.h @@ -24,7 +24,6 @@ #define PICOPASS_AIA_BLOCK_INDEX 5 #define PICOPASS_PACS_CFG_BLOCK_INDEX 6 -#define PICOPASS_APP_FOLDER ANY_PATH("picopass") #define PICOPASS_APP_EXTENSION ".picopass" #define PICOPASS_APP_SHADOW_EXTENSION ".pas" @@ -81,7 +80,6 @@ typedef struct { PicopassDeviceSaveFormat format; PicopassLoadingCallback loading_cb; void* loading_cb_ctx; - } PicopassDevice; PicopassDevice* picopass_device_alloc(); diff --git a/applications/plugins/picopass/scenes/picopass_scene_save_name.c b/applications/plugins/picopass/scenes/picopass_scene_save_name.c index 59f33c79a..baf882b80 100644 --- a/applications/plugins/picopass/scenes/picopass_scene_save_name.c +++ b/applications/plugins/picopass/scenes/picopass_scene_save_name.c @@ -31,12 +31,10 @@ void picopass_scene_save_name_on_enter(void* context) { dev_name_empty); FuriString* folder_path; - folder_path = furi_string_alloc(); + folder_path = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); if(furi_string_end_with(picopass->dev->load_path, PICOPASS_APP_EXTENSION)) { path_extract_dirname(furi_string_get_cstr(picopass->dev->load_path), folder_path); - } else { - furi_string_set(folder_path, PICOPASS_APP_FOLDER); } ValidatorIsFile* validator_is_file = validator_is_file_alloc_init( diff --git a/applications/plugins/pocsag_pager/protocols/pcsg_generic.c b/applications/plugins/pocsag_pager/protocols/pcsg_generic.c index 890ed43d7..5425fd512 100644 --- a/applications/plugins/pocsag_pager/protocols/pcsg_generic.c +++ b/applications/plugins/pocsag_pager/protocols/pcsg_generic.c @@ -21,12 +21,12 @@ void pcsg_block_generic_get_preset_name(const char* preset_name, FuriString* pre furi_string_set(preset_str, preset_name_temp); } -bool pcsg_block_generic_serialize( +SubGhzProtocolStatus pcsg_block_generic_serialize( PCSGBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); do { @@ -75,15 +75,16 @@ bool pcsg_block_generic_serialize( break; } - res = true; + res = SubGhzProtocolStatusOk; } while(false); furi_string_free(temp_str); return res; } -bool pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_data = furi_string_alloc(); FuriString* temp_data2 = furi_string_alloc(); @@ -113,7 +114,7 @@ bool pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* f instance->result_msg = furi_string_alloc_set(temp_data); } - res = true; + res = SubGhzProtocolStatusOk; } while(0); furi_string_free(temp_data); diff --git a/applications/plugins/pocsag_pager/protocols/pcsg_generic.h b/applications/plugins/pocsag_pager/protocols/pcsg_generic.h index ff925b6c9..126b54ffe 100644 --- a/applications/plugins/pocsag_pager/protocols/pcsg_generic.h +++ b/applications/plugins/pocsag_pager/protocols/pcsg_generic.h @@ -35,7 +35,7 @@ void pcsg_block_generic_get_preset_name(const char* preset_name, FuriString* pre * @param preset The modulation on which the signal was received, SubGhzRadioPreset * @return true On success */ -bool pcsg_block_generic_serialize( +SubGhzProtocolStatus pcsg_block_generic_serialize( PCSGBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -46,7 +46,8 @@ bool pcsg_block_generic_serialize( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format); +SubGhzProtocolStatus + pcsg_block_generic_deserialize(PCSGBlockGeneric* instance, FlipperFormat* flipper_format); float pcsg_block_generic_fahrenheit_to_celsius(float fahrenheit); diff --git a/applications/plugins/pocsag_pager/protocols/pocsag.c b/applications/plugins/pocsag_pager/protocols/pocsag.c index 69d09d554..ca210c2a4 100644 --- a/applications/plugins/pocsag_pager/protocols/pocsag.c +++ b/applications/plugins/pocsag_pager/protocols/pocsag.c @@ -288,7 +288,7 @@ uint8_t subghz_protocol_decoder_pocsag_get_hash_data(void* context) { return hash; } -bool subghz_protocol_decoder_pocsag_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_pocsag_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -296,31 +296,35 @@ bool subghz_protocol_decoder_pocsag_serialize( SubGhzProtocolDecoderPocsag* instance = context; uint32_t msg_len; - if(!pcsg_block_generic_serialize(&instance->generic, flipper_format, preset)) return false; + if(SubGhzProtocolStatusOk != + pcsg_block_generic_serialize(&instance->generic, flipper_format, preset)) + return SubGhzProtocolStatusError; msg_len = furi_string_size(instance->done_msg); if(!flipper_format_write_uint32(flipper_format, "MsgLen", &msg_len, 1)) { FURI_LOG_E(TAG, "Error adding MsgLen"); - return false; + return SubGhzProtocolStatusError; } uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg); if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) { FURI_LOG_E(TAG, "Error adding Msg"); - return false; + return SubGhzProtocolStatusError; } - return true; + return SubGhzProtocolStatusOk; } -bool subghz_protocol_decoder_pocsag_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_pocsag_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPocsag* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; uint32_t msg_len; uint8_t* buf; do { - if(!pcsg_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + pcsg_block_generic_deserialize(&instance->generic, flipper_format)) { break; } @@ -338,7 +342,7 @@ bool subghz_protocol_decoder_pocsag_deserialize(void* context, FlipperFormat* fl furi_string_set_strn(instance->done_msg, (const char*)buf, msg_len); free(buf); - ret = true; + ret = SubGhzProtocolStatusOk; } while(false); return ret; } diff --git a/applications/plugins/spi_mem_manager/scenes/spi_mem_scene_start.c b/applications/plugins/spi_mem_manager/scenes/spi_mem_scene_start.c index b664df687..38d064a4d 100644 --- a/applications/plugins/spi_mem_manager/scenes/spi_mem_scene_start.c +++ b/applications/plugins/spi_mem_manager/scenes/spi_mem_scene_start.c @@ -60,7 +60,7 @@ bool spi_mem_scene_start_on_event(void* context, SceneManagerEvent event) { scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect); success = true; } else if(event.event == SPIMemSceneStartSubmenuIndexSaved) { - furi_string_set(app->file_path, SPI_MEM_FILE_FOLDER); + furi_string_set(app->file_path, STORAGE_APP_DATA_PATH_PREFIX); scene_manager_next_scene(app->scene_manager, SPIMemSceneSelectFile); success = true; } else if(event.event == SPIMemSceneStartSubmenuIndexErase) { diff --git a/applications/plugins/spi_mem_manager/spi_mem_app.c b/applications/plugins/spi_mem_manager/spi_mem_app.c index 63531b74c..96c3632d0 100644 --- a/applications/plugins/spi_mem_manager/spi_mem_app.c +++ b/applications/plugins/spi_mem_manager/spi_mem_app.c @@ -16,9 +16,9 @@ static bool spi_mem_back_event_callback(void* context) { } SPIMemApp* spi_mem_alloc(void) { - SPIMemApp* instance = malloc(sizeof(SPIMemApp)); + SPIMemApp* instance = malloc(sizeof(SPIMemApp)); //-V799 - instance->file_path = furi_string_alloc(); + instance->file_path = furi_string_alloc_set(STORAGE_APP_DATA_PATH_PREFIX); instance->gui = furi_record_open(RECORD_GUI); instance->notifications = furi_record_open(RECORD_NOTIFICATION); instance->view_dispatcher = view_dispatcher_alloc(); @@ -37,7 +37,8 @@ SPIMemApp* spi_mem_alloc(void) { instance->text_input = text_input_alloc(); instance->mode = SPIMemModeUnknown; - furi_string_set(instance->file_path, SPI_MEM_FILE_FOLDER); + // Migrate data from old sd-card folder + storage_common_migrate(instance->storage, EXT_PATH("spimem"), STORAGE_APP_DATA_PATH_PREFIX); view_dispatcher_enable_queue(instance->view_dispatcher); view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance); @@ -70,7 +71,7 @@ SPIMemApp* spi_mem_alloc(void) { furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_external); scene_manager_next_scene(instance->scene_manager, SPIMemSceneStart); return instance; -} +} //-V773 void spi_mem_free(SPIMemApp* instance) { view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewSubmenu); @@ -105,7 +106,6 @@ void spi_mem_free(SPIMemApp* instance) { int32_t spi_mem_app(void* p) { UNUSED(p); SPIMemApp* instance = spi_mem_alloc(); - spi_mem_file_create_folder(instance); view_dispatcher_run(instance->view_dispatcher); spi_mem_free(instance); return 0; diff --git a/applications/plugins/spi_mem_manager/spi_mem_app_i.h b/applications/plugins/spi_mem_manager/spi_mem_app_i.h index 4ce056175..285ca66d2 100644 --- a/applications/plugins/spi_mem_manager/spi_mem_app_i.h +++ b/applications/plugins/spi_mem_manager/spi_mem_app_i.h @@ -24,7 +24,6 @@ #define TAG "SPIMem" #define SPI_MEM_FILE_EXTENSION ".bin" -#define SPI_MEM_FILE_FOLDER EXT_PATH("spimem") #define SPI_MEM_FILE_NAME_SIZE 100 #define SPI_MEM_TEXT_BUFFER_SIZE 128 diff --git a/applications/plugins/spi_mem_manager/spi_mem_files.c b/applications/plugins/spi_mem_manager/spi_mem_files.c index a7374da19..9b787bd7f 100644 --- a/applications/plugins/spi_mem_manager/spi_mem_files.c +++ b/applications/plugins/spi_mem_manager/spi_mem_files.c @@ -1,11 +1,5 @@ #include "spi_mem_app_i.h" -void spi_mem_file_create_folder(SPIMemApp* app) { - if(!storage_simply_mkdir(app->storage, SPI_MEM_FILE_FOLDER)) { - dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder"); - } -} - bool spi_mem_file_delete(SPIMemApp* app) { return (storage_simply_remove(app->storage, furi_string_get_cstr(app->file_path))); } @@ -13,7 +7,7 @@ bool spi_mem_file_delete(SPIMemApp* app) { bool spi_mem_file_select(SPIMemApp* app) { DialogsFileBrowserOptions browser_options; dialog_file_browser_set_basic_options(&browser_options, SPI_MEM_FILE_EXTENSION, &I_Dip8_10px); - browser_options.base_path = SPI_MEM_FILE_FOLDER; + browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX; bool success = dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options); return success; diff --git a/applications/plugins/spi_mem_manager/spi_mem_files.h b/applications/plugins/spi_mem_manager/spi_mem_files.h index 0e735d951..6a529d327 100644 --- a/applications/plugins/spi_mem_manager/spi_mem_files.h +++ b/applications/plugins/spi_mem_manager/spi_mem_files.h @@ -1,7 +1,6 @@ #pragma once #include "spi_mem_app.h" -void spi_mem_file_create_folder(SPIMemApp* app); bool spi_mem_file_select(SPIMemApp* app); bool spi_mem_file_create(SPIMemApp* app, const char* file_name); bool spi_mem_file_delete(SPIMemApp* app); diff --git a/applications/plugins/weather_station/helpers/weather_station_types.h b/applications/plugins/weather_station/helpers/weather_station_types.h index 1f5612e2e..111465978 100644 --- a/applications/plugins/weather_station/helpers/weather_station_types.h +++ b/applications/plugins/weather_station/helpers/weather_station_types.h @@ -3,7 +3,7 @@ #include #include -#define WS_VERSION_APP "0.7" +#define WS_VERSION_APP "0.8" #define WS_DEVELOPED "SkorP" #define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware" diff --git a/applications/plugins/weather_station/protocols/acurite_592txr.c b/applications/plugins/weather_station/protocols/acurite_592txr.c index 5384a3c91..874f6dd33 100644 --- a/applications/plugins/weather_station/protocols/acurite_592txr.c +++ b/applications/plugins/weather_station/protocols/acurite_592txr.c @@ -258,7 +258,7 @@ uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_acurite_592txr_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_592txr_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -267,22 +267,14 @@ bool ws_protocol_decoder_acurite_592txr_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderAcurite_592TXR* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_acurite_592txr_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_acurite_592txr_const.min_count_bit_for_found); } void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/acurite_592txr.h b/applications/plugins/weather_station/protocols/acurite_592txr.h index ac0371d89..1071d1cf7 100644 --- a/applications/plugins/weather_station/protocols/acurite_592txr.h +++ b/applications/plugins/weather_station/protocols/acurite_592txr.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_acurite_592txr_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_592txr_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_592txr_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_592txr_serialize( * Deserialize data WSProtocolDecoderAcurite_592TXR. * @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_acurite_592txr_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/acurite_606tx.c b/applications/plugins/weather_station/protocols/acurite_606tx.c index 4cb5d18b8..e0d405c66 100644 --- a/applications/plugins/weather_station/protocols/acurite_606tx.c +++ b/applications/plugins/weather_station/protocols/acurite_606tx.c @@ -199,7 +199,7 @@ uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_acurite_606tx_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_606tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -208,22 +208,14 @@ bool ws_protocol_decoder_acurite_606tx_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderAcurite_606TX* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_acurite_606tx_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_acurite_606tx_const.min_count_bit_for_found); } void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/acurite_606tx.h b/applications/plugins/weather_station/protocols/acurite_606tx.h index 5bab3bcb7..15b6d1eb5 100644 --- a/applications/plugins/weather_station/protocols/acurite_606tx.h +++ b/applications/plugins/weather_station/protocols/acurite_606tx.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_acurite_606tx_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_606tx_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_606tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_606tx_serialize( * Deserialize data WSProtocolDecoderAcurite_606TX. * @param context Pointer to a WSProtocolDecoderAcurite_606TX instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_acurite_606tx_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/acurite_609txc.c b/applications/plugins/weather_station/protocols/acurite_609txc.c index aeb0785eb..853b78446 100644 --- a/applications/plugins/weather_station/protocols/acurite_609txc.c +++ b/applications/plugins/weather_station/protocols/acurite_609txc.c @@ -199,7 +199,7 @@ uint8_t ws_protocol_decoder_acurite_609txc_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_acurite_609txc_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_609txc_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -208,22 +208,14 @@ bool ws_protocol_decoder_acurite_609txc_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderAcurite_609TXC* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_acurite_609txc_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_acurite_609txc_const.min_count_bit_for_found); } void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/acurite_609txc.h b/applications/plugins/weather_station/protocols/acurite_609txc.h index f87c20e9b..3e3b9cee8 100644 --- a/applications/plugins/weather_station/protocols/acurite_609txc.h +++ b/applications/plugins/weather_station/protocols/acurite_609txc.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_acurite_609txc_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_609txc_serialize( +SubGhzProtocolStatus ws_protocol_decoder_acurite_609txc_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_609txc_serialize( * Deserialize data WSProtocolDecoderAcurite_609TXC. * @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_acurite_609txc_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/ambient_weather.c b/applications/plugins/weather_station/protocols/ambient_weather.c index e3c85f40b..588a7f82a 100644 --- a/applications/plugins/weather_station/protocols/ambient_weather.c +++ b/applications/plugins/weather_station/protocols/ambient_weather.c @@ -228,7 +228,7 @@ uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_ambient_weather_serialize( +SubGhzProtocolStatus ws_protocol_decoder_ambient_weather_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -237,22 +237,14 @@ bool ws_protocol_decoder_ambient_weather_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderAmbient_Weather* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_ambient_weather_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_ambient_weather_const.min_count_bit_for_found); } void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/ambient_weather.h b/applications/plugins/weather_station/protocols/ambient_weather.h index 04cc5819c..1694403cd 100644 --- a/applications/plugins/weather_station/protocols/ambient_weather.h +++ b/applications/plugins/weather_station/protocols/ambient_weather.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_ambient_weather_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_ambient_weather_serialize( +SubGhzProtocolStatus ws_protocol_decoder_ambient_weather_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_ambient_weather_serialize( * Deserialize data WSProtocolDecoderAmbient_Weather. * @param context Pointer to a WSProtocolDecoderAmbient_Weather instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_ambient_weather_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/auriol_hg0601a.c b/applications/plugins/weather_station/protocols/auriol_hg0601a.c index d5f89fc8b..813fe1526 100644 --- a/applications/plugins/weather_station/protocols/auriol_hg0601a.c +++ b/applications/plugins/weather_station/protocols/auriol_hg0601a.c @@ -210,7 +210,7 @@ uint8_t ws_protocol_decoder_auriol_th_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_auriol_th_serialize( +SubGhzProtocolStatus ws_protocol_decoder_auriol_th_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -219,22 +219,12 @@ bool ws_protocol_decoder_auriol_th_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderAuriol_TH* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_auriol_th_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_auriol_th_const.min_count_bit_for_found); } void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/auriol_hg0601a.h b/applications/plugins/weather_station/protocols/auriol_hg0601a.h index c23007c1a..155bb07fc 100644 --- a/applications/plugins/weather_station/protocols/auriol_hg0601a.h +++ b/applications/plugins/weather_station/protocols/auriol_hg0601a.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_auriol_th_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderAuriol_TH instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_auriol_th_serialize( +SubGhzProtocolStatus ws_protocol_decoder_auriol_th_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_auriol_th_serialize( * Deserialize data WSProtocolDecoderAuriol_TH. * @param context Pointer to a WSProtocolDecoderAuriol_TH instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_auriol_th_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/gt_wt_02.c b/applications/plugins/weather_station/protocols/gt_wt_02.c index cbe119192..d333164b4 100644 --- a/applications/plugins/weather_station/protocols/gt_wt_02.c +++ b/applications/plugins/weather_station/protocols/gt_wt_02.c @@ -217,7 +217,7 @@ uint8_t ws_protocol_decoder_gt_wt_02_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_gt_wt_02_serialize( +SubGhzProtocolStatus ws_protocol_decoder_gt_wt_02_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -226,22 +226,12 @@ bool ws_protocol_decoder_gt_wt_02_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderGT_WT02* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_gt_wt_02_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_gt_wt_02_const.min_count_bit_for_found); } void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/gt_wt_02.h b/applications/plugins/weather_station/protocols/gt_wt_02.h index f17d5baa0..e13576d21 100644 --- a/applications/plugins/weather_station/protocols/gt_wt_02.h +++ b/applications/plugins/weather_station/protocols/gt_wt_02.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_gt_wt_02_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderGT_WT02 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_gt_wt_02_serialize( +SubGhzProtocolStatus ws_protocol_decoder_gt_wt_02_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_gt_wt_02_serialize( * Deserialize data WSProtocolDecoderGT_WT02. * @param context Pointer to a WSProtocolDecoderGT_WT02 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_gt_wt_02_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/gt_wt_03.c b/applications/plugins/weather_station/protocols/gt_wt_03.c index 7831cf069..30430b839 100644 --- a/applications/plugins/weather_station/protocols/gt_wt_03.c +++ b/applications/plugins/weather_station/protocols/gt_wt_03.c @@ -292,7 +292,7 @@ uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_gt_wt_03_serialize( +SubGhzProtocolStatus ws_protocol_decoder_gt_wt_03_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -301,22 +301,12 @@ bool ws_protocol_decoder_gt_wt_03_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderGT_WT03* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_gt_wt_03_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_gt_wt_03_const.min_count_bit_for_found); } void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/gt_wt_03.h b/applications/plugins/weather_station/protocols/gt_wt_03.h index fd9536e34..d566bb399 100644 --- a/applications/plugins/weather_station/protocols/gt_wt_03.h +++ b/applications/plugins/weather_station/protocols/gt_wt_03.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_gt_wt_03_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderGT_WT03 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_gt_wt_03_serialize( +SubGhzProtocolStatus ws_protocol_decoder_gt_wt_03_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_gt_wt_03_serialize( * Deserialize data WSProtocolDecoderGT_WT03. * @param context Pointer to a WSProtocolDecoderGT_WT03 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_gt_wt_03_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/infactory.c b/applications/plugins/weather_station/protocols/infactory.c index 53a656d73..4b0e6602a 100644 --- a/applications/plugins/weather_station/protocols/infactory.c +++ b/applications/plugins/weather_station/protocols/infactory.c @@ -248,7 +248,7 @@ uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_infactory_serialize( +SubGhzProtocolStatus ws_protocol_decoder_infactory_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -257,22 +257,12 @@ bool ws_protocol_decoder_infactory_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderInfactory* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_infactory_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_infactory_const.min_count_bit_for_found); } void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/infactory.h b/applications/plugins/weather_station/protocols/infactory.h index 2792ab987..9431a067e 100644 --- a/applications/plugins/weather_station/protocols/infactory.h +++ b/applications/plugins/weather_station/protocols/infactory.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderInfactory instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_infactory_serialize( +SubGhzProtocolStatus ws_protocol_decoder_infactory_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_infactory_serialize( * Deserialize data WSProtocolDecoderInfactory. * @param context Pointer to a WSProtocolDecoderInfactory instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_infactory_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx.c b/applications/plugins/weather_station/protocols/lacrosse_tx.c index 8d8a24e24..f4b850d76 100644 --- a/applications/plugins/weather_station/protocols/lacrosse_tx.c +++ b/applications/plugins/weather_station/protocols/lacrosse_tx.c @@ -281,7 +281,7 @@ uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_lacrosse_tx_serialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -290,22 +290,12 @@ bool ws_protocol_decoder_lacrosse_tx_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderLaCrosse_TX* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_lacrosse_tx_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_lacrosse_tx_const.min_count_bit_for_found); } void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx.h b/applications/plugins/weather_station/protocols/lacrosse_tx.h index e88455689..151282b3a 100644 --- a/applications/plugins/weather_station/protocols/lacrosse_tx.h +++ b/applications/plugins/weather_station/protocols/lacrosse_tx.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_lacrosse_tx_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_lacrosse_tx_serialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_lacrosse_tx_serialize( * Deserialize data WSProtocolDecoderLaCrosse_TX. * @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_lacrosse_tx_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c index e4b612250..5d007b12f 100644 --- a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c +++ b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.c @@ -247,7 +247,7 @@ uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -256,24 +256,15 @@ bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderLaCrosse_TX141THBv2* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found); } void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.h b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.h index 941b01058..036db0548 100644 --- a/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.h +++ b/applications/plugins/weather_station/protocols/lacrosse_tx141thbv2.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_lacrosse_tx141thbv2_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,9 @@ bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize( * Deserialize data WSProtocolDecoderLaCrosse_TX141THBv2. * @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( +SubGhzProtocolStatus ws_protocol_decoder_lacrosse_tx141thbv2_deserialize( void* context, FlipperFormat* flipper_format); diff --git a/applications/plugins/weather_station/protocols/nexus_th.c b/applications/plugins/weather_station/protocols/nexus_th.c index 38f2fe895..14ba8b273 100644 --- a/applications/plugins/weather_station/protocols/nexus_th.c +++ b/applications/plugins/weather_station/protocols/nexus_th.c @@ -216,7 +216,7 @@ uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_nexus_th_serialize( +SubGhzProtocolStatus ws_protocol_decoder_nexus_th_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -225,22 +225,12 @@ bool ws_protocol_decoder_nexus_th_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderNexus_TH* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_nexus_th_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_nexus_th_const.min_count_bit_for_found); } void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/nexus_th.h b/applications/plugins/weather_station/protocols/nexus_th.h index 5450f0040..6c2715b85 100644 --- a/applications/plugins/weather_station/protocols/nexus_th.h +++ b/applications/plugins/weather_station/protocols/nexus_th.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_nexus_th_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderNexus_TH instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_nexus_th_serialize( +SubGhzProtocolStatus ws_protocol_decoder_nexus_th_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_nexus_th_serialize( * Deserialize data WSProtocolDecoderNexus_TH. * @param context Pointer to a WSProtocolDecoderNexus_TH instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_nexus_th_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/oregon2.c b/applications/plugins/weather_station/protocols/oregon2.c index 8ca80bbe2..313748ccf 100644 --- a/applications/plugins/weather_station/protocols/oregon2.c +++ b/applications/plugins/weather_station/protocols/oregon2.c @@ -302,17 +302,19 @@ uint8_t ws_protocol_decoder_oregon2_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_oregon2_serialize( +SubGhzProtocolStatus ws_protocol_decoder_oregon2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); WSProtocolDecoderOregon2* instance = context; - if(!ws_block_generic_serialize(&instance->generic, flipper_format, preset)) return false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + ret = ws_block_generic_serialize(&instance->generic, flipper_format, preset); + if(ret != SubGhzProtocolStatusOk) return ret; uint32_t temp = instance->var_bits; if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) { FURI_LOG_E(TAG, "Error adding VarBits"); - return false; + return SubGhzProtocolStatusErrorParserOthers; } if(!flipper_format_write_hex( flipper_format, @@ -320,22 +322,25 @@ bool ws_protocol_decoder_oregon2_serialize( (const uint8_t*)&instance->var_data, sizeof(instance->var_data))) { FURI_LOG_E(TAG, "Error adding VarData"); - return false; + return SubGhzProtocolStatusErrorParserOthers; } - return true; + return ret; } -bool ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderOregon2* instance = context; - bool ret = false; uint32_t temp_data; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = ws_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) { FURI_LOG_E(TAG, "Missing VarLen"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } instance->var_bits = (uint8_t)temp_data; @@ -345,13 +350,14 @@ bool ws_protocol_decoder_oregon2_deserialize(void* context, FlipperFormat* flipp (uint8_t*)&instance->var_data, sizeof(instance->var_data))) { //-V1051 FURI_LOG_E(TAG, "Missing VarData"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(instance->generic.data_count_bit != ws_oregon2_const.min_count_bit_for_found) { FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } - ret = true; } while(false); return ret; } diff --git a/applications/plugins/weather_station/protocols/oregon_v1.c b/applications/plugins/weather_station/protocols/oregon_v1.c index 1ed9da205..03215bbf5 100644 --- a/applications/plugins/weather_station/protocols/oregon_v1.c +++ b/applications/plugins/weather_station/protocols/oregon_v1.c @@ -283,7 +283,7 @@ uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_oregon_v1_serialize( +SubGhzProtocolStatus ws_protocol_decoder_oregon_v1_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -292,22 +292,12 @@ bool ws_protocol_decoder_oregon_v1_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderOregon_V1* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_oregon_v1_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_oregon_v1_const.min_count_bit_for_found); } void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/oregon_v1.h b/applications/plugins/weather_station/protocols/oregon_v1.h index c9aa5af48..48937601d 100644 --- a/applications/plugins/weather_station/protocols/oregon_v1.h +++ b/applications/plugins/weather_station/protocols/oregon_v1.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_oregon_v1_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderOregon_V1 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_oregon_v1_serialize( +SubGhzProtocolStatus ws_protocol_decoder_oregon_v1_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_oregon_v1_serialize( * Deserialize data WSProtocolDecoderOregon_V1. * @param context Pointer to a WSProtocolDecoderOregon_V1 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_oregon_v1_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/thermopro_tx4.c b/applications/plugins/weather_station/protocols/thermopro_tx4.c index 0882bc33d..24e883e60 100644 --- a/applications/plugins/weather_station/protocols/thermopro_tx4.c +++ b/applications/plugins/weather_station/protocols/thermopro_tx4.c @@ -211,7 +211,7 @@ uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_thermopro_tx4_serialize( +SubGhzProtocolStatus ws_protocol_decoder_thermopro_tx4_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -220,22 +220,14 @@ bool ws_protocol_decoder_thermopro_tx4_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderThermoPRO_TX4* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - ws_protocol_thermopro_tx4_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + ws_protocol_thermopro_tx4_const.min_count_bit_for_found); } void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/thermopro_tx4.h b/applications/plugins/weather_station/protocols/thermopro_tx4.h index 1feae58d3..526648d1e 100644 --- a/applications/plugins/weather_station/protocols/thermopro_tx4.h +++ b/applications/plugins/weather_station/protocols/thermopro_tx4.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_thermopro_tx4_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_thermopro_tx4_serialize( +SubGhzProtocolStatus ws_protocol_decoder_thermopro_tx4_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_thermopro_tx4_serialize( * Deserialize data WSProtocolDecoderThermoPRO_TX4. * @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_thermopro_tx4_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/tx_8300.c b/applications/plugins/weather_station/protocols/tx_8300.c index ee0412ba9..3a06ce49d 100644 --- a/applications/plugins/weather_station/protocols/tx_8300.c +++ b/applications/plugins/weather_station/protocols/tx_8300.c @@ -246,7 +246,7 @@ uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool ws_protocol_decoder_tx_8300_serialize( +SubGhzProtocolStatus ws_protocol_decoder_tx_8300_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -255,21 +255,12 @@ bool ws_protocol_decoder_tx_8300_serialize( return ws_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); WSProtocolDecoderTX_8300* instance = context; - bool ret = false; - do { - if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != ws_protocol_tx_8300_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return ws_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, ws_protocol_tx_8300_const.min_count_bit_for_found); } void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) { diff --git a/applications/plugins/weather_station/protocols/tx_8300.h b/applications/plugins/weather_station/protocols/tx_8300.h index ec198e80f..088ccd7c0 100644 --- a/applications/plugins/weather_station/protocols/tx_8300.h +++ b/applications/plugins/weather_station/protocols/tx_8300.h @@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_tx_8300_get_hash_data(void* context); * @param context Pointer to a WSProtocolDecoderTX_8300 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_protocol_decoder_tx_8300_serialize( +SubGhzProtocolStatus ws_protocol_decoder_tx_8300_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -67,9 +67,10 @@ bool ws_protocol_decoder_tx_8300_serialize( * Deserialize data WSProtocolDecoderTX_8300. * @param context Pointer to a WSProtocolDecoderTX_8300 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_protocol_decoder_tx_8300_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/applications/plugins/weather_station/protocols/ws_generic.c b/applications/plugins/weather_station/protocols/ws_generic.c index 8a88ed52f..026856a9e 100644 --- a/applications/plugins/weather_station/protocols/ws_generic.c +++ b/applications/plugins/weather_station/protocols/ws_generic.c @@ -21,12 +21,12 @@ void ws_block_generic_get_preset_name(const char* preset_name, FuriString* prese furi_string_set(preset_str, preset_name_temp); } -bool ws_block_generic_serialize( +SubGhzProtocolStatus ws_block_generic_serialize( WSBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); do { @@ -34,11 +34,13 @@ bool ws_block_generic_serialize( if(!flipper_format_write_header_cstr( flipper_format, WS_KEY_FILE_TYPE, WS_KEY_FILE_VERSION)) { FURI_LOG_E(TAG, "Unable to add header"); + res = SubGhzProtocolStatusErrorParserHeader; break; } if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { FURI_LOG_E(TAG, "Unable to add Frequency"); + res = SubGhzProtocolStatusErrorParserFrequency; break; } @@ -46,34 +48,40 @@ bool ws_block_generic_serialize( if(!flipper_format_write_string_cstr( flipper_format, "Preset", furi_string_get_cstr(temp_str))) { FURI_LOG_E(TAG, "Unable to add Preset"); + res = SubGhzProtocolStatusErrorParserPreset; break; } if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { if(!flipper_format_write_string_cstr( flipper_format, "Custom_preset_module", "CC1101")) { FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } if(!flipper_format_write_hex( flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } } if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) { FURI_LOG_E(TAG, "Unable to add Protocol"); + res = SubGhzProtocolStatusErrorParserProtocolName; break; } uint32_t temp_data = instance->id; if(!flipper_format_write_uint32(flipper_format, "Id", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Id"); + res = SubGhzProtocolStatusErrorParserOthers; break; } temp_data = instance->data_count_bit; if(!flipper_format_write_uint32(flipper_format, "Bit", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } @@ -84,18 +92,21 @@ bool ws_block_generic_serialize( if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Data"); + res = SubGhzProtocolStatusErrorParserOthers; break; } temp_data = instance->battery_low; if(!flipper_format_write_uint32(flipper_format, "Batt", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Battery_low"); + res = SubGhzProtocolStatusErrorParserOthers; break; } temp_data = instance->humidity; if(!flipper_format_write_uint32(flipper_format, "Hum", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Humidity"); + res = SubGhzProtocolStatusErrorParserOthers; break; } @@ -107,52 +118,60 @@ bool ws_block_generic_serialize( temp_data = curr_ts; if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add timestamp"); + res = SubGhzProtocolStatusErrorParserOthers; break; } temp_data = instance->channel; if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Channel"); + res = SubGhzProtocolStatusErrorParserOthers; break; } temp_data = instance->btn; if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) { FURI_LOG_E(TAG, "Unable to add Btn"); + res = SubGhzProtocolStatusErrorParserOthers; break; } float temp = instance->temp; if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) { FURI_LOG_E(TAG, "Unable to add Temperature"); + res = SubGhzProtocolStatusErrorParserOthers; break; } - res = true; + res = SubGhzProtocolStatusOk; } while(false); furi_string_free(temp_str); return res; } -bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; uint32_t temp_data = 0; do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "Id", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Id"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->id = (uint32_t)temp_data; if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } instance->data_count_bit = (uint8_t)temp_data; @@ -160,6 +179,7 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Missing Data"); + res = SubGhzProtocolStatusErrorParserOthers; break; } @@ -169,30 +189,35 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp if(!flipper_format_read_uint32(flipper_format, "Batt", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Battery_low"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->battery_low = (uint8_t)temp_data; if(!flipper_format_read_uint32(flipper_format, "Hum", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Humidity"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->humidity = (uint8_t)temp_data; if(!flipper_format_read_uint32(flipper_format, "Ts", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing timestamp"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->timestamp = (uint32_t)temp_data; if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Channel"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->channel = (uint8_t)temp_data; if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Btn"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->btn = (uint8_t)temp_data; @@ -200,12 +225,32 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp float temp; if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) { FURI_LOG_E(TAG, "Missing Temperature"); + res = SubGhzProtocolStatusErrorParserOthers; break; } instance->temp = temp; - res = true; + res = SubGhzProtocolStatusOk; } while(0); return res; +} + +SubGhzProtocolStatus ws_block_generic_deserialize_check_count_bit( + WSBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit) { + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = ws_block_generic_deserialize(instance, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + if(instance->data_count_bit != count_bit) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + } while(false); + return ret; } \ No newline at end of file diff --git a/applications/plugins/weather_station/protocols/ws_generic.h b/applications/plugins/weather_station/protocols/ws_generic.h index 47cfa74b3..ff047fae6 100644 --- a/applications/plugins/weather_station/protocols/ws_generic.h +++ b/applications/plugins/weather_station/protocols/ws_generic.h @@ -48,9 +48,9 @@ void ws_block_generic_get_preset_name(const char* preset_name, FuriString* prese * @param instance Pointer to a WSBlockGeneric instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool ws_block_generic_serialize( +SubGhzProtocolStatus ws_block_generic_serialize( WSBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -59,9 +59,22 @@ bool ws_block_generic_serialize( * Deserialize data WSBlockGeneric. * @param instance Pointer to a WSBlockGeneric instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format); +SubGhzProtocolStatus + ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipper_format); + +/** + * Deserialize data WSBlockGeneric. + * @param instance Pointer to a WSBlockGeneric instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param count_bit Count bit protocol + * @return status + */ +SubGhzProtocolStatus ws_block_generic_deserialize_check_count_bit( + WSBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit); #ifdef __cplusplus } diff --git a/applications/services/applications.h b/applications/services/applications.h index acbfea312..871e9af54 100644 --- a/applications/services/applications.h +++ b/applications/services/applications.h @@ -11,6 +11,7 @@ typedef enum { typedef struct { const FuriThreadCallback app; const char* name; + const char* appid; const size_t stack_size; const Icon* icon; const FlipperApplicationFlag flags; diff --git a/applications/services/bt/bt_service/bt_api.c b/applications/services/bt/bt_service/bt_api.c index e3cf78cc7..2f56b50a3 100644 --- a/applications/services/bt/bt_service/bt_api.c +++ b/applications/services/bt/bt_service/bt_api.c @@ -45,7 +45,14 @@ void bt_keys_storage_set_storage_path(Bt* bt, const char* keys_storage_path) { furi_assert(bt->keys_storage); furi_assert(keys_storage_path); - bt_keys_storage_set_file_path(bt->keys_storage, keys_storage_path); + Storage* storage = furi_record_open(RECORD_STORAGE); + FuriString* path = furi_string_alloc_set(keys_storage_path); + storage_common_resolve_path_and_ensure_app_directory(storage, path); + + bt_keys_storage_set_file_path(bt->keys_storage, furi_string_get_cstr(path)); + + furi_string_free(path); + furi_record_close(RECORD_STORAGE); } void bt_keys_storage_set_default_path(Bt* bt) { diff --git a/applications/services/cli/cli_commands.c b/applications/services/cli/cli_commands.c index 75400bd38..a8d1b7e67 100644 --- a/applications/services/cli/cli_commands.c +++ b/applications/services/cli/cli_commands.c @@ -382,11 +382,18 @@ void cli_command_ps(Cli* cli, FuriString* args, void* context) { FuriThreadId threads_ids[threads_num_max]; uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max); printf( - "%-20s %-14s %-8s %-8s %s\r\n", "Name", "Stack start", "Heap", "Stack", "Stack min free"); + "%-20s %-20s %-14s %-8s %-8s %s\r\n", + "AppID", + "Name", + "Stack start", + "Heap", + "Stack", + "Stack min free"); for(uint8_t i = 0; i < thread_num; i++) { TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i]; printf( - "%-20s 0x%-12lx %-8zu %-8lu %-8lu\r\n", + "%-20s %-20s 0x%-12lx %-8zu %-8lu %-8lu\r\n", + furi_thread_get_appid(threads_ids[i]), furi_thread_get_name(threads_ids[i]), (uint32_t)tcb->pxStack, memmgr_heap_get_thread_memory(threads_ids[i]), diff --git a/applications/services/dialogs/dialogs_api.c b/applications/services/dialogs/dialogs_api.c index ca2435b9b..4723a1f91 100644 --- a/applications/services/dialogs/dialogs_api.c +++ b/applications/services/dialogs/dialogs_api.c @@ -2,6 +2,7 @@ #include "dialogs_i.h" #include #include +#include /****************** File browser ******************/ @@ -13,6 +14,22 @@ bool dialog_file_browser_show( FuriApiLock lock = api_lock_alloc_locked(); furi_check(lock != NULL); + Storage* storage = furi_record_open(RECORD_STORAGE); + FuriString* base_path = furi_string_alloc(); + + if(options && options->base_path) { + furi_string_set(base_path, options->base_path); + storage_common_resolve_path_and_ensure_app_directory(storage, base_path); + } + + if(result_path) { + storage_common_resolve_path_and_ensure_app_directory(storage, result_path); + } + + if(path) { + storage_common_resolve_path_and_ensure_app_directory(storage, path); + } + DialogsAppData data = { .file_browser = { .extension = options ? options->extension : "", @@ -24,7 +41,7 @@ bool dialog_file_browser_show( .preselected_filename = path, .item_callback = options ? options->item_loader_callback : NULL, .item_callback_context = options ? options->item_loader_context : NULL, - .base_path = options ? options->base_path : NULL, + .base_path = furi_string_get_cstr(base_path), }}; DialogsAppReturn return_data; @@ -39,6 +56,9 @@ bool dialog_file_browser_show( furi_message_queue_put(context->message_queue, &message, FuriWaitForever) == FuriStatusOk); api_lock_wait_unlock_and_free(lock); + furi_record_close(RECORD_STORAGE); + furi_string_free(base_path); + return return_data.bool_value; } diff --git a/applications/services/gui/modules/file_browser_worker.c b/applications/services/gui/modules/file_browser_worker.c index 9d219429b..326040020 100644 --- a/applications/services/gui/modules/file_browser_worker.c +++ b/applications/services/gui/modules/file_browser_worker.c @@ -60,7 +60,7 @@ static bool browser_path_is_file(FuriString* path) { FileInfo file_info; Storage* storage = furi_record_open(RECORD_STORAGE); if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) { - if((file_info.flags & FSF_DIRECTORY) == 0) { + if(!file_info_is_dir(&file_info)) { state = true; } } @@ -119,7 +119,7 @@ static bool browser_folder_check_and_switch(FuriString* path) { while(1) { // Check if folder is existing and navigate back if not if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) { - if(file_info.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&file_info)) { break; } } @@ -161,7 +161,7 @@ static bool browser_folder_init( if((storage_file_get_error(directory) == FSE_OK) && (name_temp[0] != '\0')) { total_files_cnt++; furi_string_set(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + if(browser_filter_by_name(browser, name_str, file_info_is_dir(&file_info))) { if(!furi_string_empty(filename)) { if(furi_string_cmp(name_str, filename) == 0) { *file_idx = *item_cnt; @@ -218,7 +218,7 @@ static bool browser_folder_load_chunked( } if(storage_file_get_error(directory) == FSE_OK) { furi_string_set(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + if(browser_filter_by_name(browser, name_str, file_info_is_dir(&file_info))) { items_cnt++; } } else { @@ -240,14 +240,14 @@ static bool browser_folder_load_chunked( } if(storage_file_get_error(directory) == FSE_OK) { furi_string_set(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + if(browser_filter_by_name(browser, name_str, file_info_is_dir(&file_info))) { furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp); if(browser->list_item_cb) { browser->list_item_cb( browser->cb_ctx, name_str, items_cnt, - (file_info.flags & FSF_DIRECTORY), + file_info_is_dir(&file_info), false); } items_cnt++; @@ -295,15 +295,11 @@ static bool browser_folder_load_full(BrowserWorker* browser, FuriString* path) { while(storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX) && storage_file_get_error(directory) == FSE_OK) { furi_string_set(name_str, name_temp); - if(browser_filter_by_name(browser, name_str, (file_info.flags & FSF_DIRECTORY))) { + if(browser_filter_by_name(browser, name_str, file_info_is_dir(&file_info))) { furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp); if(browser->list_item_cb) { browser->list_item_cb( - browser->cb_ctx, - name_str, - items_cnt, - (file_info.flags & FSF_DIRECTORY), - false); + browser->cb_ctx, name_str, items_cnt, file_info_is_dir(&file_info), false); } items_cnt++; } diff --git a/applications/services/gui/modules/widget.h b/applications/services/gui/modules/widget.h index a78c4ce06..f86b14cc9 100644 --- a/applications/services/gui/modules/widget.h +++ b/applications/services/gui/modules/widget.h @@ -115,6 +115,7 @@ void widget_add_text_box_element( * @param[in] text Formatted text. Default format: align left, Secondary font. * The following formats are available: * "\e#Bold text" - sets bold font before until next '\n' symbol + * "\e*Monospaced text\e*" - sets monospaced font before until next '\n' symbol * "\ecCenter-aligned text" - sets center horizontal align until the next '\n' symbol * "\erRight-aligned text" - sets right horizontal align until the next '\n' symbol */ diff --git a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c index 5d522c74b..4c9c39dff 100644 --- a/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c +++ b/applications/services/gui/modules/widget_elements/widget_element_text_scroll.c @@ -37,6 +37,8 @@ static bool line->horizontal = AlignRight; } else if(ctrl_symbol == '#') { line->font = FontPrimary; + } else if(ctrl_symbol == '*') { + line->font = FontKeyboard; } furi_string_right(text, 2); processed = true; diff --git a/applications/services/loader/loader.c b/applications/services/loader/loader.c index caaf9f11b..5f2d8a2e7 100644 --- a/applications/services/loader/loader.c +++ b/applications/services/loader/loader.c @@ -29,6 +29,8 @@ static bool } furi_thread_set_name(loader_instance->application_thread, loader_instance->application->name); + furi_thread_set_appid( + loader_instance->application_thread, loader_instance->application->appid); furi_thread_set_stack_size( loader_instance->application_thread, loader_instance->application->stack_size); furi_thread_set_context( diff --git a/applications/services/rpc/rpc_storage.c b/applications/services/rpc/rpc_storage.c index c4493cc74..c3a4a0470 100644 --- a/applications/services/rpc/rpc_storage.c +++ b/applications/services/rpc/rpc_storage.c @@ -201,7 +201,7 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex if(error == FSE_OK) { response->which_content = PB_Main_storage_stat_response_tag; response->content.storage_stat_response.has_file = true; - response->content.storage_stat_response.file.type = (fileinfo.flags & FSF_DIRECTORY) ? + response->content.storage_stat_response.file.type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR : PB_Storage_File_FileType_FILE; response->content.storage_stat_response.file.size = fileinfo.size; @@ -291,9 +291,8 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex rpc_send_and_release(session, &response); i = 0; } - list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ? - PB_Storage_File_FileType_DIR : - PB_Storage_File_FileType_FILE; + list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR : + PB_Storage_File_FileType_FILE; list->file[i].size = fileinfo.size; list->file[i].data = NULL; list->file[i].name = name; @@ -458,7 +457,7 @@ static bool rpc_system_storage_is_dir_is_empty(Storage* fs_api, const char* path FileInfo fileinfo; bool is_dir_is_empty = true; FS_Error error = storage_common_stat(fs_api, path, &fileinfo); - if((error == FSE_OK) && (fileinfo.flags & FSF_DIRECTORY)) { + if((error == FSE_OK) && file_info_is_dir(&fileinfo)) { File* dir = storage_file_alloc(fs_api); if(storage_dir_open(dir, path)) { char* name = malloc(MAX_NAME_LENGTH); diff --git a/applications/services/storage/filesystem_api.c b/applications/services/storage/filesystem_api.c index b979967ac..30b20ede4 100644 --- a/applications/services/storage/filesystem_api.c +++ b/applications/services/storage/filesystem_api.c @@ -36,3 +36,7 @@ const char* filesystem_api_error_get_desc(FS_Error error_id) { } return result; } + +bool file_info_is_dir(const FileInfo* file_info) { + return (file_info->flags & FSF_DIRECTORY); +} \ No newline at end of file diff --git a/applications/services/storage/filesystem_api_defines.h b/applications/services/storage/filesystem_api_defines.h index b73e6eb33..cd24b8825 100644 --- a/applications/services/storage/filesystem_api_defines.h +++ b/applications/services/storage/filesystem_api_defines.h @@ -1,5 +1,6 @@ #pragma once #include +#include #ifdef __cplusplus extern "C" { @@ -40,10 +41,10 @@ typedef enum { FSF_DIRECTORY = (1 << 0), /**< Directory */ } FS_Flags; -/** Structure that hold file index and returned api errors */ +/** Structure that hold file index and returned api errors */ typedef struct File File; -/** Structure that hold file info */ +/** Structure that hold file info */ typedef struct { uint8_t flags; /**< flags from FS_Flags enum */ uint64_t size; /**< file size */ @@ -55,6 +56,12 @@ typedef struct { */ const char* filesystem_api_error_get_desc(FS_Error error_id); +/** Checks if file info is directory + * @param file_info file info pointer + * @return bool is directory + */ +bool file_info_is_dir(const FileInfo* file_info); + #ifdef __cplusplus } #endif diff --git a/applications/services/storage/storage.h b/applications/services/storage/storage.h index df85a40b8..da583ce50 100644 --- a/applications/services/storage/storage.h +++ b/applications/services/storage/storage.h @@ -10,10 +10,12 @@ extern "C" { #define STORAGE_INT_PATH_PREFIX "/int" #define STORAGE_EXT_PATH_PREFIX "/ext" #define STORAGE_ANY_PATH_PREFIX "/any" +#define STORAGE_APP_DATA_PATH_PREFIX "/app" #define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path #define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path #define ANY_PATH(path) STORAGE_ANY_PATH_PREFIX "/" path +#define APP_DATA_PATH(path) STORAGE_APP_DATA_PATH_PREFIX "/" path #define RECORD_STORAGE "storage" @@ -175,6 +177,15 @@ bool storage_dir_read(File* file, FileInfo* fileinfo, char* name, uint16_t name_ */ bool storage_dir_rewind(File* file); +/** + * @brief Check that dir exists + * + * @param storage + * @param path + * @return bool + */ +bool storage_dir_exists(Storage* storage, const char* path); + /******************* Common Functions *******************/ /** Retrieves unix timestamp of last access @@ -246,6 +257,36 @@ FS_Error storage_common_fs_info( uint64_t* total_space, uint64_t* free_space); +/** + * @brief Parse aliases in path and replace them with real path + * Also will create special folders if they are not exist + * + * @param storage + * @param path + * @return bool + */ +void storage_common_resolve_path_and_ensure_app_directory(Storage* storage, FuriString* path); + +/** + * @brief Move content of one folder to another, with rename of all conflicting files. + * Source folder will be deleted if the migration is successful. + * + * @param storage + * @param source + * @param dest + * @return FS_Error + */ +FS_Error storage_common_migrate(Storage* storage, const char* source, const char* dest); + +/** + * @brief Check that file or dir exists + * + * @param storage + * @param path + * @return bool + */ +bool storage_common_exists(Storage* storage, const char* path); + /******************* Error Functions *******************/ /** Retrieves the error text from the error id diff --git a/applications/services/storage/storage_cli.c b/applications/services/storage/storage_cli.c index ff2055697..8e2dcdbbb 100644 --- a/applications/services/storage/storage_cli.c +++ b/applications/services/storage/storage_cli.c @@ -131,7 +131,7 @@ static void storage_cli_list(Cli* cli, FuriString* path) { while(storage_dir_read(file, &fileinfo, name, MAX_NAME_LENGTH)) { read_done = true; - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { printf("\t[D] %s\r\n", name); } else { printf("\t[F] %s %lub\r\n", name, (uint32_t)(fileinfo.size)); @@ -169,7 +169,7 @@ static void storage_cli_tree(Cli* cli, FuriString* path) { while(dir_walk_read(dir_walk, name, &fileinfo) == DirWalkOK) { read_done = true; - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { printf("\t[D] %s\r\n", furi_string_get_cstr(name)); } else { printf( @@ -383,7 +383,7 @@ static void storage_cli_stat(Cli* cli, FuriString* path) { FS_Error error = storage_common_stat(api, furi_string_get_cstr(path), &fileinfo); if(error == FSE_OK) { - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { printf("Directory\r\n"); } else { printf("File, size: %lub\r\n", (uint32_t)(fileinfo.size)); diff --git a/applications/services/storage/storage_external_api.c b/applications/services/storage/storage_external_api.c index c5dfd533e..8d8220f81 100644 --- a/applications/services/storage/storage_external_api.c +++ b/applications/services/storage/storage_external_api.c @@ -39,12 +39,6 @@ .file = file, \ }}; -#define S_API_DATA_PATH \ - SAData data = { \ - .path = { \ - .path = path, \ - }}; - #define S_RETURN_BOOL (return_data.bool_value); #define S_RETURN_UINT16 (return_data.uint16_value); #define S_RETURN_UINT64 (return_data.uint64_value); @@ -70,6 +64,7 @@ static bool storage_file_open_internal( .path = path, .access_mode = access_mode, .open_mode = open_mode, + .thread_id = furi_thread_get_current_id(), }}; file->type = FileTypeOpenFile; @@ -249,7 +244,7 @@ bool storage_file_exists(Storage* storage, const char* path) { FileInfo fileinfo; FS_Error error = storage_common_stat(storage, path, &fileinfo); - if(error == FSE_OK && !(fileinfo.flags & FSF_DIRECTORY)) { + if(error == FSE_OK && !file_info_is_dir(&fileinfo)) { exist = true; } @@ -266,6 +261,7 @@ static bool storage_dir_open_internal(File* file, const char* path) { .dopen = { .file = file, .path = path, + .thread_id = furi_thread_get_current_id(), }}; file->type = FileTypeOpenDir; @@ -349,12 +345,28 @@ bool storage_dir_rewind(File* file) { return S_RETURN_BOOL; } +bool storage_dir_exists(Storage* storage, const char* path) { + bool exist = false; + FileInfo fileinfo; + FS_Error error = storage_common_stat(storage, path, &fileinfo); + + if(error == FSE_OK && file_info_is_dir(&fileinfo)) { + exist = true; + } + + return exist; +} /****************** COMMON ******************/ FS_Error storage_common_timestamp(Storage* storage, const char* path, uint32_t* timestamp) { S_API_PROLOGUE; - SAData data = {.ctimestamp = {.path = path, .timestamp = timestamp}}; + SAData data = { + .ctimestamp = { + .path = path, + .timestamp = timestamp, + .thread_id = furi_thread_get_current_id(), + }}; S_API_MESSAGE(StorageCommandCommonTimestamp); S_API_EPILOGUE; @@ -363,8 +375,12 @@ FS_Error storage_common_timestamp(Storage* storage, const char* path, uint32_t* FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* fileinfo) { S_API_PROLOGUE; - - SAData data = {.cstat = {.path = path, .fileinfo = fileinfo}}; + SAData data = { + .cstat = { + .path = path, + .fileinfo = fileinfo, + .thread_id = furi_thread_get_current_id(), + }}; S_API_MESSAGE(StorageCommandCommonStat); S_API_EPILOGUE; @@ -373,7 +389,12 @@ FS_Error storage_common_stat(Storage* storage, const char* path, FileInfo* filei FS_Error storage_common_remove(Storage* storage, const char* path) { S_API_PROLOGUE; - S_API_DATA_PATH; + SAData data = { + .path = { + .path = path, + .thread_id = furi_thread_get_current_id(), + }}; + S_API_MESSAGE(StorageCommandCommonRemove); S_API_EPILOGUE; return S_RETURN_ERROR; @@ -423,7 +444,7 @@ static FS_Error furi_string_right(path, strlen(old_path)); furi_string_printf(tmp_new_path, "%s%s", new_path, furi_string_get_cstr(path)); - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { error = storage_common_mkdir(storage, furi_string_get_cstr(tmp_new_path)); } else { error = storage_common_copy( @@ -452,7 +473,7 @@ FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* error = storage_common_stat(storage, old_path, &fileinfo); if(error == FSE_OK) { - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { error = storage_copy_recursive(storage, old_path, new_path); } else { Stream* stream_from = file_stream_alloc(storage); @@ -479,7 +500,7 @@ FS_Error storage_common_copy(Storage* storage, const char* old_path, const char* static FS_Error storage_merge_recursive(Storage* storage, const char* old_path, const char* new_path) { - FS_Error error = storage_common_mkdir(storage, new_path); + FS_Error error = FSE_OK; DirWalk* dir_walk = dir_walk_alloc(storage); FuriString *path, *file_basename, *tmp_new_path; FileInfo fileinfo; @@ -488,7 +509,7 @@ static FS_Error tmp_new_path = furi_string_alloc(); do { - if((error != FSE_OK) && (error != FSE_EXIST)) break; + if(!storage_simply_mkdir(storage, new_path)) break; dir_walk_set_recursive(dir_walk, false); if(!dir_walk_open(dir_walk, old_path)) { @@ -508,13 +529,13 @@ static FS_Error path_extract_basename(furi_string_get_cstr(path), file_basename); path_concat(new_path, furi_string_get_cstr(file_basename), tmp_new_path); - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { if(storage_common_stat( storage, furi_string_get_cstr(tmp_new_path), &fileinfo) == FSE_OK) { - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { error = storage_common_mkdir(storage, furi_string_get_cstr(tmp_new_path)); - if(error != FSE_OK) { + if(error != FSE_OK && error != FSE_EXIST) { break; } } @@ -548,7 +569,7 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char error = storage_common_stat(storage, old_path, &fileinfo); if(error == FSE_OK) { - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { error = storage_merge_recursive(storage, old_path, new_path); } else { error = storage_common_stat(storage, new_path, &fileinfo); @@ -556,7 +577,7 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char furi_string_set(new_path_next, new_path); FuriString* dir_path; FuriString* filename; - char extension[MAX_EXT_LEN]; + char extension[MAX_EXT_LEN] = {0}; dir_path = furi_string_alloc(); filename = furi_string_alloc(); @@ -608,7 +629,12 @@ FS_Error storage_common_merge(Storage* storage, const char* old_path, const char FS_Error storage_common_mkdir(Storage* storage, const char* path) { S_API_PROLOGUE; - S_API_DATA_PATH; + SAData data = { + .path = { + .path = path, + .thread_id = furi_thread_get_current_id(), + }}; + S_API_MESSAGE(StorageCommandCommonMkDir); S_API_EPILOGUE; return S_RETURN_ERROR; @@ -626,6 +652,7 @@ FS_Error storage_common_fs_info( .fs_path = fs_path, .total_space = total_space, .free_space = free_space, + .thread_id = furi_thread_get_current_id(), }}; S_API_MESSAGE(StorageCommandCommonFSInfo); @@ -633,6 +660,38 @@ FS_Error storage_common_fs_info( return S_RETURN_ERROR; } +void storage_common_resolve_path_and_ensure_app_directory(Storage* storage, FuriString* path) { + S_API_PROLOGUE; + + SAData data = { + .cresolvepath = { + .path = path, + .thread_id = furi_thread_get_current_id(), + }}; + + S_API_MESSAGE(StorageCommandCommonResolvePath); + S_API_EPILOGUE; +} + +FS_Error storage_common_migrate(Storage* storage, const char* source, const char* dest) { + if(!storage_common_exists(storage, source)) { + return FSE_OK; + } + + FS_Error error = storage_common_merge(storage, source, dest); + + if(error == FSE_OK) { + storage_simply_remove_recursive(storage, source); + } + + return error; +} + +bool storage_common_exists(Storage* storage, const char* path) { + FileInfo file_info; + return storage_common_stat(storage, path, &file_info) == FSE_OK; +} + /****************** ERROR ******************/ const char* storage_error_get_desc(FS_Error error_id) { @@ -750,7 +809,7 @@ bool storage_simply_remove_recursive(Storage* storage, const char* path) { } while(storage_dir_read(dir, &fileinfo, name, MAX_NAME_LENGTH)) { - if(fileinfo.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&fileinfo)) { furi_string_cat_printf(cur_dir, "/%s", name); go_deeper = true; break; diff --git a/applications/services/storage/storage_glue.c b/applications/services/storage/storage_glue.c index cccf4046a..5dabfa386 100644 --- a/applications/services/storage/storage_glue.c +++ b/applications/services/storage/storage_glue.c @@ -5,21 +5,18 @@ void storage_file_init(StorageFile* obj) { obj->file = NULL; - obj->type = ST_ERROR; obj->file_data = NULL; obj->path = furi_string_alloc(); } void storage_file_init_set(StorageFile* obj, const StorageFile* src) { obj->file = src->file; - obj->type = src->type; obj->file_data = src->file_data; obj->path = furi_string_alloc_set(src->path); } void storage_file_set(StorageFile* obj, const StorageFile* src) { //-V524 obj->file = src->file; - obj->type = src->type; obj->file_data = src->file_data; furi_string_set(obj->path, src->path); } @@ -150,16 +147,10 @@ void* storage_get_storage_file_data(const File* file, StorageData* storage) { return founded_file->file_data; } -void storage_push_storage_file( - File* file, - FuriString* path, - StorageType type, - StorageData* storage) { +void storage_push_storage_file(File* file, FuriString* path, StorageData* storage) { StorageFile* storage_file = StorageFileList_push_new(storage->files); - file->file_id = (uint32_t)storage_file; storage_file->file = file; - storage_file->type = type; furi_string_set(storage_file->path, path); } diff --git a/applications/services/storage/storage_glue.h b/applications/services/storage/storage_glue.h index 501c26abc..bf0a1c69e 100644 --- a/applications/services/storage/storage_glue.h +++ b/applications/services/storage/storage_glue.h @@ -18,7 +18,6 @@ typedef struct { typedef struct { File* file; - StorageType type; void* file_data; FuriString* path; } StorageFile; @@ -66,11 +65,7 @@ bool storage_path_already_open(FuriString* path, StorageFileList_t files); void storage_set_storage_file_data(const File* file, void* file_data, StorageData* storage); void* storage_get_storage_file_data(const File* file, StorageData* storage); -void storage_push_storage_file( - File* file, - FuriString* path, - StorageType type, - StorageData* storage); +void storage_push_storage_file(File* file, FuriString* path, StorageData* storage); bool storage_pop_storage_file(File* file, StorageData* storage); #ifdef __cplusplus diff --git a/applications/services/storage/storage_i.h b/applications/services/storage/storage_i.h index 406fc921e..85df5d926 100644 --- a/applications/services/storage/storage_i.h +++ b/applications/services/storage/storage_i.h @@ -12,6 +12,8 @@ extern "C" { #define STORAGE_COUNT (ST_INT + 1) +#define APPS_DATA_PATH EXT_PATH("apps_data") + typedef struct { ViewPort* view_port; bool enabled; diff --git a/applications/services/storage/storage_message.h b/applications/services/storage/storage_message.h index 3edb1018e..9e13bf83d 100644 --- a/applications/services/storage/storage_message.h +++ b/applications/services/storage/storage_message.h @@ -11,6 +11,7 @@ typedef struct { const char* path; FS_AccessMode access_mode; FS_OpenMode open_mode; + FuriThreadId thread_id; } SADataFOpen; typedef struct { @@ -34,6 +35,7 @@ typedef struct { typedef struct { File* file; const char* path; + FuriThreadId thread_id; } SADataDOpen; typedef struct { @@ -46,25 +48,34 @@ typedef struct { typedef struct { const char* path; uint32_t* timestamp; + FuriThreadId thread_id; } SADataCTimestamp; typedef struct { const char* path; FileInfo* fileinfo; + FuriThreadId thread_id; } SADataCStat; typedef struct { const char* fs_path; uint64_t* total_space; uint64_t* free_space; + FuriThreadId thread_id; } SADataCFSInfo; +typedef struct { + FuriString* path; + FuriThreadId thread_id; +} SADataCResolvePath; + typedef struct { uint32_t id; } SADataError; typedef struct { const char* path; + FuriThreadId thread_id; } SADataPath; typedef struct { @@ -87,6 +98,7 @@ typedef union { SADataCTimestamp ctimestamp; SADataCStat cstat; SADataCFSInfo cfsinfo; + SADataCResolvePath cresolvepath; SADataError error; @@ -128,6 +140,7 @@ typedef enum { StorageCommandSDUnmount, StorageCommandSDInfo, StorageCommandSDStatus, + StorageCommandCommonResolvePath, } StorageCommand; typedef struct { diff --git a/applications/services/storage/storage_processing.c b/applications/services/storage/storage_processing.c index b1ea5d29b..cab1edff5 100644 --- a/applications/services/storage/storage_processing.c +++ b/applications/services/storage/storage_processing.c @@ -4,17 +4,11 @@ #define FS_CALL(_storage, _fn) ret = _storage->fs_api->_fn; -static StorageData* storage_get_storage_by_type(Storage* app, StorageType type) { - furi_check(type == ST_EXT || type == ST_INT); - StorageData* storage = &app->storage[type]; - return storage; -} - -static bool storage_type_is_not_valid(StorageType type) { +static bool storage_type_is_valid(StorageType type) { #ifdef FURI_RAM_EXEC - return type != ST_EXT; + return type == ST_EXT; #else - return type >= ST_ERROR; + return type < ST_ERROR; #endif } @@ -30,25 +24,21 @@ static StorageData* get_storage_by_file(File* file, StorageData* storages) { return storage_data; } -static const char* remove_vfs(const char* path) { - return path + MIN(4u, strlen(path)); +static const char* cstr_path_without_vfs_prefix(FuriString* path) { + const char* path_cstr = furi_string_get_cstr(path); + return path_cstr + MIN(4u, strlen(path_cstr)); } -static StorageType storage_get_type_by_path(Storage* app, const char* path) { +static StorageType storage_get_type_by_path(FuriString* path) { StorageType type = ST_ERROR; - if(memcmp(path, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) { - type = ST_EXT; - } else if(memcmp(path, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) { - type = ST_INT; - } else if(memcmp(path, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) { - type = ST_ANY; - } + const char* path_cstr = furi_string_get_cstr(path); - if(type == ST_ANY) { + if(memcmp(path_cstr, STORAGE_EXT_PATH_PREFIX, strlen(STORAGE_EXT_PATH_PREFIX)) == 0) { + type = ST_EXT; + } else if(memcmp(path_cstr, STORAGE_INT_PATH_PREFIX, strlen(STORAGE_INT_PATH_PREFIX)) == 0) { type = ST_INT; - if(storage_data_status(&app->storage[ST_EXT]) == StorageStatusOK) { - type = ST_EXT; - } + } else if(memcmp(path_cstr, STORAGE_ANY_PATH_PREFIX, strlen(STORAGE_ANY_PATH_PREFIX)) == 0) { + type = ST_ANY; } return type; @@ -71,38 +61,51 @@ static void storage_path_change_to_real_storage(FuriString* path, StorageType re } } +FS_Error storage_get_data(Storage* app, FuriString* path, StorageData** storage) { + StorageType type = storage_get_type_by_path(path); + + if(storage_type_is_valid(type)) { + if(type == ST_ANY) { + type = ST_INT; + if(storage_data_status(&app->storage[ST_EXT]) == StorageStatusOK) { + type = ST_EXT; + } + storage_path_change_to_real_storage(path, type); + } + + furi_assert(type == ST_EXT || type == ST_INT); + *storage = &app->storage[type]; + + return FSE_OK; + } else { + return FSE_INVALID_NAME; + } +} + /******************* File Functions *******************/ bool storage_process_file_open( Storage* app, File* file, - const char* path, + FuriString* path, FS_AccessMode access_mode, FS_OpenMode open_mode) { bool ret = false; - StorageType type = storage_get_type_by_path(app, path); StorageData* storage; - file->error_id = FSE_OK; + file->error_id = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - file->error_id = FSE_INVALID_NAME; - } else { - storage = storage_get_storage_by_type(app, type); - FuriString* real_path; - real_path = furi_string_alloc_set(path); - storage_path_change_to_real_storage(real_path, type); - - if(storage_path_already_open(real_path, storage->files)) { + if(file->error_id == FSE_OK) { + if(storage_path_already_open(path, storage->files)) { file->error_id = FSE_ALREADY_OPEN; } else { if(access_mode & FSAM_WRITE) { storage_data_timestamp(storage); } - storage_push_storage_file(file, real_path, type, storage); - FS_CALL(storage, file.open(storage, file, remove_vfs(path), access_mode, open_mode)); - } + storage_push_storage_file(file, path, storage); - furi_string_free(real_path); + const char* path_cstr_no_vfs = cstr_path_without_vfs_prefix(path); + FS_CALL(storage, file.open(storage, file, path_cstr_no_vfs, access_mode, open_mode)); + } } return ret; @@ -243,27 +246,18 @@ static bool storage_process_file_eof(Storage* app, File* file) { /******************* Dir Functions *******************/ -bool storage_process_dir_open(Storage* app, File* file, const char* path) { +bool storage_process_dir_open(Storage* app, File* file, FuriString* path) { bool ret = false; - StorageType type = storage_get_type_by_path(app, path); StorageData* storage; - file->error_id = FSE_OK; + file->error_id = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - file->error_id = FSE_INVALID_NAME; - } else { - storage = storage_get_storage_by_type(app, type); - FuriString* real_path; - real_path = furi_string_alloc_set(path); - storage_path_change_to_real_storage(real_path, type); - - if(storage_path_already_open(real_path, storage->files)) { + if(file->error_id == FSE_OK) { + if(storage_path_already_open(path, storage->files)) { file->error_id = FSE_ALREADY_OPEN; } else { - storage_push_storage_file(file, real_path, type, storage); - FS_CALL(storage, dir.open(storage, file, remove_vfs(path))); + storage_push_storage_file(file, path, storage); + FS_CALL(storage, dir.open(storage, file, cstr_path_without_vfs_prefix(path))); } - furi_string_free(real_path); } return ret; @@ -320,73 +314,52 @@ bool storage_process_dir_rewind(Storage* app, File* file) { /******************* Common FS Functions *******************/ static FS_Error - storage_process_common_timestamp(Storage* app, const char* path, uint32_t* timestamp) { - FS_Error ret = FSE_OK; - StorageType type = storage_get_type_by_path(app, path); + storage_process_common_timestamp(Storage* app, FuriString* path, uint32_t* timestamp) { + StorageData* storage; + FS_Error ret = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - ret = FSE_INVALID_NAME; - } else { - StorageData* storage = storage_get_storage_by_type(app, type); + if(ret == FSE_OK) { *timestamp = storage_data_get_timestamp(storage); } return ret; } -static FS_Error storage_process_common_stat(Storage* app, const char* path, FileInfo* fileinfo) { - FS_Error ret = FSE_OK; - StorageType type = storage_get_type_by_path(app, path); +static FS_Error storage_process_common_stat(Storage* app, FuriString* path, FileInfo* fileinfo) { + StorageData* storage; + FS_Error ret = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - ret = FSE_INVALID_NAME; - } else { - StorageData* storage = storage_get_storage_by_type(app, type); - FS_CALL(storage, common.stat(storage, remove_vfs(path), fileinfo)); + if(ret == FSE_OK) { + FS_CALL(storage, common.stat(storage, cstr_path_without_vfs_prefix(path), fileinfo)); } return ret; } -static FS_Error storage_process_common_remove(Storage* app, const char* path) { - FS_Error ret = FSE_OK; - StorageType type = storage_get_type_by_path(app, path); - - FuriString* real_path; - real_path = furi_string_alloc_set(path); - storage_path_change_to_real_storage(real_path, type); +static FS_Error storage_process_common_remove(Storage* app, FuriString* path) { + StorageData* storage; + FS_Error ret = storage_get_data(app, path, &storage); do { - if(storage_type_is_not_valid(type)) { - ret = FSE_INVALID_NAME; - break; - } - - StorageData* storage = storage_get_storage_by_type(app, type); - if(storage_path_already_open(real_path, storage->files)) { + if(storage_path_already_open(path, storage->files)) { ret = FSE_ALREADY_OPEN; break; } storage_data_timestamp(storage); - FS_CALL(storage, common.remove(storage, remove_vfs(path))); + FS_CALL(storage, common.remove(storage, cstr_path_without_vfs_prefix(path))); } while(false); - furi_string_free(real_path); - return ret; } -static FS_Error storage_process_common_mkdir(Storage* app, const char* path) { - FS_Error ret = FSE_OK; - StorageType type = storage_get_type_by_path(app, path); +static FS_Error storage_process_common_mkdir(Storage* app, FuriString* path) { + StorageData* storage; + FS_Error ret = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - ret = FSE_INVALID_NAME; - } else { - StorageData* storage = storage_get_storage_by_type(app, type); + if(ret == FSE_OK) { storage_data_timestamp(storage); - FS_CALL(storage, common.mkdir(storage, remove_vfs(path))); + FS_CALL(storage, common.mkdir(storage, cstr_path_without_vfs_prefix(path))); } return ret; @@ -394,17 +367,16 @@ static FS_Error storage_process_common_mkdir(Storage* app, const char* path) { static FS_Error storage_process_common_fs_info( Storage* app, - const char* fs_path, + FuriString* path, uint64_t* total_space, uint64_t* free_space) { - FS_Error ret = FSE_OK; - StorageType type = storage_get_type_by_path(app, fs_path); + StorageData* storage; + FS_Error ret = storage_get_data(app, path, &storage); - if(storage_type_is_not_valid(type)) { - ret = FSE_INVALID_NAME; - } else { - StorageData* storage = storage_get_storage_by_type(app, type); - FS_CALL(storage, common.fs_info(storage, remove_vfs(fs_path), total_space, free_space)); + if(ret == FSE_OK) { + FS_CALL( + storage, + common.fs_info(storage, cstr_path_without_vfs_prefix(path), total_space, free_space)); } return ret; @@ -471,14 +443,52 @@ static FS_Error storage_process_sd_status(Storage* app) { return ret; } +/******************** Aliases processing *******************/ + +void storage_process_alias( + Storage* app, + FuriString* path, + FuriThreadId thread_id, + bool create_folders) { + if(furi_string_start_with(path, STORAGE_APP_DATA_PATH_PREFIX)) { + FuriString* apps_data_path_with_appsid = furi_string_alloc_set(APPS_DATA_PATH "/"); + furi_string_cat(apps_data_path_with_appsid, furi_thread_get_appid(thread_id)); + + // "/app" -> "/ext/apps_data/appsid" + furi_string_replace_at( + path, + 0, + strlen(STORAGE_APP_DATA_PATH_PREFIX), + furi_string_get_cstr(apps_data_path_with_appsid)); + + // Create app data folder if not exists + if(create_folders && + storage_process_common_stat(app, apps_data_path_with_appsid, NULL) != FSE_OK) { + furi_string_set(apps_data_path_with_appsid, APPS_DATA_PATH); + storage_process_common_mkdir(app, apps_data_path_with_appsid); + furi_string_cat(apps_data_path_with_appsid, "/"); + furi_string_cat(apps_data_path_with_appsid, furi_thread_get_appid(thread_id)); + storage_process_common_mkdir(app, apps_data_path_with_appsid); + } + + furi_string_free(apps_data_path_with_appsid); + } +} + /****************** API calls processing ******************/ + void storage_process_message_internal(Storage* app, StorageMessage* message) { + FuriString* path = NULL; + switch(message->command) { + // File operations case StorageCommandFileOpen: + path = furi_string_alloc_set(message->data->fopen.path); + storage_process_alias(app, path, message->data->fopen.thread_id, true); message->return_data->bool_value = storage_process_file_open( app, message->data->fopen.file, - message->data->fopen.path, + path, message->data->fopen.access_mode, message->data->fopen.open_mode); break; @@ -527,9 +537,12 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) { message->return_data->bool_value = storage_process_file_eof(app, message->data->file.file); break; + // Dir operations case StorageCommandDirOpen: + path = furi_string_alloc_set(message->data->dopen.path); + storage_process_alias(app, path, message->data->dopen.thread_id, true); message->return_data->bool_value = - storage_process_dir_open(app, message->data->dopen.file, message->data->dopen.path); + storage_process_dir_open(app, message->data->dopen.file, path); break; case StorageCommandDirClose: message->return_data->bool_value = @@ -547,29 +560,42 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) { message->return_data->bool_value = storage_process_dir_rewind(app, message->data->file.file); break; + + // Common operations case StorageCommandCommonTimestamp: - message->return_data->error_value = storage_process_common_timestamp( - app, message->data->ctimestamp.path, message->data->ctimestamp.timestamp); + path = furi_string_alloc_set(message->data->ctimestamp.path); + storage_process_alias(app, path, message->data->ctimestamp.thread_id, false); + message->return_data->error_value = + storage_process_common_timestamp(app, path, message->data->ctimestamp.timestamp); break; case StorageCommandCommonStat: - message->return_data->error_value = storage_process_common_stat( - app, message->data->cstat.path, message->data->cstat.fileinfo); + path = furi_string_alloc_set(message->data->cstat.path); + storage_process_alias(app, path, message->data->cstat.thread_id, false); + message->return_data->error_value = + storage_process_common_stat(app, path, message->data->cstat.fileinfo); break; case StorageCommandCommonRemove: - message->return_data->error_value = - storage_process_common_remove(app, message->data->path.path); + path = furi_string_alloc_set(message->data->path.path); + storage_process_alias(app, path, message->data->path.thread_id, false); + message->return_data->error_value = storage_process_common_remove(app, path); break; case StorageCommandCommonMkDir: - message->return_data->error_value = - storage_process_common_mkdir(app, message->data->path.path); + path = furi_string_alloc_set(message->data->path.path); + storage_process_alias(app, path, message->data->path.thread_id, true); + message->return_data->error_value = storage_process_common_mkdir(app, path); break; case StorageCommandCommonFSInfo: + path = furi_string_alloc_set(message->data->cfsinfo.fs_path); + storage_process_alias(app, path, message->data->cfsinfo.thread_id, false); message->return_data->error_value = storage_process_common_fs_info( - app, - message->data->cfsinfo.fs_path, - message->data->cfsinfo.total_space, - message->data->cfsinfo.free_space); + app, path, message->data->cfsinfo.total_space, message->data->cfsinfo.free_space); break; + case StorageCommandCommonResolvePath: + storage_process_alias( + app, message->data->cresolvepath.path, message->data->cresolvepath.thread_id, true); + break; + + // SD operations case StorageCommandSDFormat: message->return_data->error_value = storage_process_sd_format(app); break; @@ -585,6 +611,10 @@ void storage_process_message_internal(Storage* app, StorageMessage* message) { break; } + if(path != NULL) { //-V547 + furi_string_free(path); + } + api_lock_unlock(message->lock); } diff --git a/applications/services/storage/storage_test_app.c b/applications/services/storage/storage_test_app.c deleted file mode 100644 index 852953e99..000000000 --- a/applications/services/storage/storage_test_app.c +++ /dev/null @@ -1,341 +0,0 @@ -#include -#include -#include - -#define TAG "StorageTest" -#define BYTES_COUNT 16 -#define TEST_STRING "TestDataStringProvidedByDiceRoll" -#define SEEK_OFFSET_FROM_START 10 -#define SEEK_OFFSET_INCREASE 12 -#define SEEK_OFFSET_SUM (SEEK_OFFSET_FROM_START + SEEK_OFFSET_INCREASE) - -static void do_file_test(Storage* api, const char* path) { - File* file = storage_file_alloc(api); - bool result; - uint8_t bytes[BYTES_COUNT + 1]; - uint8_t bytes_count; - uint64_t position; - uint64_t size; - - FURI_LOG_I(TAG, "--------- FILE \"%s\" ---------", path); - - // open - result = storage_file_open(file, path, FSAM_WRITE, FSOM_CREATE_ALWAYS); - if(result) { - FURI_LOG_I(TAG, "open"); - } else { - FURI_LOG_E(TAG, "open, %s", storage_file_get_error_desc(file)); - } - - // write - bytes_count = storage_file_write(file, TEST_STRING, strlen(TEST_STRING)); - if(bytes_count == 0) { - FURI_LOG_E(TAG, "write, %s", storage_file_get_error_desc(file)); - } else { - FURI_LOG_I(TAG, "write"); - } - - // sync - result = storage_file_sync(file); - if(result) { - FURI_LOG_I(TAG, "sync"); - } else { - FURI_LOG_E(TAG, "sync, %s", storage_file_get_error_desc(file)); - } - - // eof #1 - result = storage_file_eof(file); - if(result) { - FURI_LOG_I(TAG, "eof #1"); - } else { - FURI_LOG_E(TAG, "eof #1, %s", storage_file_get_error_desc(file)); - } - - // seek from start and tell - result = storage_file_seek(file, SEEK_OFFSET_FROM_START, true); - if(result) { - FURI_LOG_I(TAG, "seek #1"); - } else { - FURI_LOG_E(TAG, "seek #1, %s", storage_file_get_error_desc(file)); - } - position = storage_file_tell(file); - if(position != SEEK_OFFSET_FROM_START) { - FURI_LOG_E(TAG, "tell #1, %s", storage_file_get_error_desc(file)); - } else { - FURI_LOG_I(TAG, "tell #1"); - } - - // size - size = storage_file_size(file); - if(size != strlen(TEST_STRING)) { - FURI_LOG_E(TAG, "size #1, %s", storage_file_get_error_desc(file)); - } else { - FURI_LOG_I(TAG, "size #1"); - } - - // seek and tell - result = storage_file_seek(file, SEEK_OFFSET_INCREASE, false); - if(result) { - FURI_LOG_I(TAG, "seek #2"); - } else { - FURI_LOG_E(TAG, "seek #2, %s", storage_file_get_error_desc(file)); - } - position = storage_file_tell(file); - if(position != SEEK_OFFSET_SUM) { - FURI_LOG_E(TAG, "tell #2, %s", storage_file_get_error_desc(file)); - } else { - FURI_LOG_I(TAG, "tell #2"); - } - - // eof #2 - result = storage_file_eof(file); - if(!result) { - FURI_LOG_I(TAG, "eof #2"); - } else { - FURI_LOG_E(TAG, "eof #2, %s", storage_file_get_error_desc(file)); - } - - // truncate - result = storage_file_truncate(file); - if(result) { - FURI_LOG_I(TAG, "truncate"); - } else { - FURI_LOG_E(TAG, "truncate, %s", storage_file_get_error_desc(file)); - } - size = storage_file_size(file); - if(size != SEEK_OFFSET_SUM) { - FURI_LOG_E(TAG, "size #2, %s", storage_file_get_error_desc(file)); - } else { - FURI_LOG_I(TAG, "size #2"); - } - - // close - result = storage_file_close(file); - if(result) { - FURI_LOG_I(TAG, "close"); - } else { - FURI_LOG_E(TAG, "close, error"); - } - - // open - result = storage_file_open(file, path, FSAM_READ, FSOM_OPEN_EXISTING); - if(result) { - FURI_LOG_I(TAG, "open"); - } else { - FURI_LOG_E(TAG, "open, %s", storage_file_get_error_desc(file)); - } - - // read - memset(bytes, 0, BYTES_COUNT + 1); - bytes_count = storage_file_read(file, bytes, BYTES_COUNT); - if(bytes_count == 0) { - FURI_LOG_E(TAG, "read, %s", storage_file_get_error_desc(file)); - } else { - if(memcmp(TEST_STRING, bytes, bytes_count) == 0) { - FURI_LOG_I(TAG, "read"); - } else { - FURI_LOG_E(TAG, "read, garbage"); - } - } - - // close - result = storage_file_close(file); - if(result) { - FURI_LOG_I(TAG, "close"); - } else { - FURI_LOG_E(TAG, "close, error"); - } - - storage_file_free(file); -} - -static void do_dir_test(Storage* api, const char* path) { - File* file = storage_file_alloc(api); - bool result; - - FURI_LOG_I(TAG, "--------- DIR \"%s\" ---------", path); - - // open - result = storage_dir_open(file, path); - if(result) { - FURI_LOG_I(TAG, "open"); - } else { - FURI_LOG_E(TAG, "open, %s", storage_file_get_error_desc(file)); - } - - // read - const uint8_t filename_size = 100; - char* filename = malloc(filename_size); - FileInfo fileinfo; - - do { - result = storage_dir_read(file, &fileinfo, filename, filename_size); - if(result) { - if(strlen(filename)) { - FURI_LOG_I( - TAG, - "read #1, [%s]%s", - ((fileinfo.flags & FSF_DIRECTORY) ? "D" : "F"), - filename); - } - } else if(storage_file_get_error(file) != FSE_NOT_EXIST) { - FURI_LOG_E(TAG, "read #1, %s", storage_file_get_error_desc(file)); - break; - } - - } while(result); - - // rewind - result = storage_dir_rewind(file); - if(result) { - FURI_LOG_I(TAG, "rewind"); - } else { - FURI_LOG_E(TAG, "rewind, %s", storage_file_get_error_desc(file)); - } - - // read - do { - result = storage_dir_read(file, &fileinfo, filename, filename_size); - if(result) { - if(strlen(filename)) { - FURI_LOG_I( - TAG, - "read #2, [%s]%s", - ((fileinfo.flags & FSF_DIRECTORY) ? "D" : "F"), - filename); - } - } else if(storage_file_get_error(file) != FSE_NOT_EXIST) { - FURI_LOG_E(TAG, "read #2, %s", storage_file_get_error_desc(file)); - break; - } - - } while((strlen(filename))); - - // close - result = storage_dir_close(file); - if(result) { - FURI_LOG_I(TAG, "close"); - } else { - FURI_LOG_E(TAG, "close, error"); - } - - storage_file_free(file); - free(filename); -} - -static void do_test_start(Storage* api, const char* path) { - FuriString* str_path = furi_string_alloc_printf("%s/test-folder", path); - - FURI_LOG_I(TAG, "--------- START \"%s\" ---------", path); - - // mkdir - FS_Error result = storage_common_mkdir(api, furi_string_get_cstr(str_path)); - - if(result == FSE_OK) { - FURI_LOG_I(TAG, "mkdir ok"); - } else { - FURI_LOG_E(TAG, "mkdir, %s", storage_error_get_desc(result)); - } - - // stat - FileInfo fileinfo; - result = storage_common_stat(api, furi_string_get_cstr(str_path), &fileinfo); - - if(result == FSE_OK) { - if(fileinfo.flags & FSF_DIRECTORY) { - FURI_LOG_I(TAG, "stat #1 ok"); - } else { - FURI_LOG_E(TAG, "stat #1, %s", storage_error_get_desc(result)); - } - } else { - FURI_LOG_E(TAG, "stat #1, %s", storage_error_get_desc(result)); - } - - furi_string_free(str_path); -} - -static void do_test_end(Storage* api, const char* path) { - uint64_t total_space; - uint64_t free_space; - FuriString* str_path_1 = furi_string_alloc_printf("%s/test-folder", path); - FuriString* str_path_2 = furi_string_alloc_printf("%s/test-folder2", path); - - FURI_LOG_I(TAG, "--------- END \"%s\" ---------", path); - - // fs stat - FS_Error result = storage_common_fs_info(api, path, &total_space, &free_space); - - if(result == FSE_OK) { - uint32_t total_kb = total_space / 1024; - uint32_t free_kb = free_space / 1024; - FURI_LOG_I(TAG, "fs_info: total %luk, free %luk", total_kb, free_kb); - } else { - FURI_LOG_E(TAG, "fs_info, %s", storage_error_get_desc(result)); - } - - // rename #1 - result = storage_common_rename( - api, furi_string_get_cstr(str_path_1), furi_string_get_cstr(str_path_2)); - if(result == FSE_OK) { - FURI_LOG_I(TAG, "rename #1 ok"); - } else { - FURI_LOG_E(TAG, "rename #1, %s", storage_error_get_desc(result)); - } - - // remove #1 - result = storage_common_remove(api, furi_string_get_cstr(str_path_2)); - if(result == FSE_OK) { - FURI_LOG_I(TAG, "remove #1 ok"); - } else { - FURI_LOG_E(TAG, "remove #1, %s", storage_error_get_desc(result)); - } - - // rename #2 - furi_string_printf(str_path_1, "%s/test.txt", path); - furi_string_printf(str_path_2, "%s/test2.txt", path); - - result = storage_common_rename( - api, furi_string_get_cstr(str_path_1), furi_string_get_cstr(str_path_2)); - if(result == FSE_OK) { - FURI_LOG_I(TAG, "rename #2 ok"); - } else { - FURI_LOG_E(TAG, "rename #2, %s", storage_error_get_desc(result)); - } - - // remove #2 - result = storage_common_remove(api, furi_string_get_cstr(str_path_2)); - if(result == FSE_OK) { - FURI_LOG_I(TAG, "remove #2 ok"); - } else { - FURI_LOG_E(TAG, "remove #2, %s", storage_error_get_desc(result)); - } - - furi_string_free(str_path_1); - furi_string_free(str_path_2); -} - -int32_t storage_test_app(void* p) { - UNUSED(p); - Storage* api = furi_record_open(RECORD_STORAGE); - do_test_start(api, STORAGE_INT_PATH_PREFIX); - do_test_start(api, STORAGE_ANY_PATH_PREFIX); - do_test_start(api, STORAGE_EXT_PATH_PREFIX); - - do_file_test(api, INT_PATH("test.txt")); - do_file_test(api, ANY_PATH("test.txt")); - do_file_test(api, EXT_PATH("test.txt")); - - do_dir_test(api, STORAGE_INT_PATH_PREFIX); - do_dir_test(api, STORAGE_ANY_PATH_PREFIX); - do_dir_test(api, STORAGE_EXT_PATH_PREFIX); - - do_test_end(api, STORAGE_INT_PATH_PREFIX); - do_test_end(api, STORAGE_ANY_PATH_PREFIX); - do_test_end(api, STORAGE_EXT_PATH_PREFIX); - - while(true) { - furi_delay_ms(1000); - } - - return 0; -} diff --git a/applications/system/storage_move_to_sd/storage_move_to_sd.c b/applications/system/storage_move_to_sd/storage_move_to_sd.c index 2027bd237..9c91b9266 100644 --- a/applications/system/storage_move_to_sd/storage_move_to_sd.c +++ b/applications/system/storage_move_to_sd/storage_move_to_sd.c @@ -13,7 +13,7 @@ static bool storage_move_to_sd_check_entry(const char* name, FileInfo* fileinfo, void* ctx) { UNUSED(ctx); - if((fileinfo->flags & FSF_DIRECTORY) != 0) { + if(file_info_is_dir(fileinfo)) { return true; } diff --git a/assets/icons/ErasePin/Erase_pin_128x64.png b/assets/icons/ErasePin/Erase_pin_128x64.png new file mode 100644 index 000000000..92ca5f91c Binary files /dev/null and b/assets/icons/ErasePin/Erase_pin_128x64.png differ diff --git a/assets/resources/picopass/assets/iclass_elite_dict.txt b/assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt similarity index 100% rename from assets/resources/picopass/assets/iclass_elite_dict.txt rename to assets/resources/apps_data/picopass/assets/iclass_elite_dict.txt diff --git a/firmware/targets/f18/api_symbols.csv b/firmware/targets/f18/api_symbols.csv index 88da0db60..902b433cf 100644 --- a/firmware/targets/f18/api_symbols.csv +++ b/firmware/targets/f18/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,15.0,, +Version,+,17.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 99448036e..502a64542 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1,5 +1,5 @@ entry,status,name,type,params -Version,+,15.0,, +Version,+,17.0,, Header,+,applications/services/bt/bt_service/bt.h,, Header,+,applications/services/cli/cli.h,, Header,+,applications/services/cli/cli_vcp.h,, @@ -165,9 +165,10 @@ Header,+,lib/mlib/m-rbtree.h,, Header,+,lib/mlib/m-tuple.h,, Header,+,lib/mlib/m-variant.h,, Header,+,lib/nfc/nfc_device.h,, +Header,+,lib/one_wire/ibutton/ibutton_key.h,, +Header,+,lib/one_wire/ibutton/ibutton_protocols.h,, Header,+,lib/one_wire/ibutton/ibutton_worker.h,, Header,+,lib/one_wire/maxim_crc.h,, -Header,+,lib/one_wire/one_wire_device.h,, Header,+,lib/one_wire/one_wire_host.h,, Header,+,lib/one_wire/one_wire_host_timing.h,, Header,+,lib/one_wire/one_wire_slave.h,, @@ -195,6 +196,7 @@ Header,+,lib/toolbox/manchester_decoder.h,, Header,+,lib/toolbox/manchester_encoder.h,, Header,+,lib/toolbox/md5.h,, Header,+,lib/toolbox/path.h,, +Header,+,lib/toolbox/pretty_format.h,, Header,+,lib/toolbox/protocols/protocol_dict.h,, Header,+,lib/toolbox/random_name.h,, Header,+,lib/toolbox/saved_struct.h,, @@ -885,6 +887,7 @@ Function,+,file_browser_worker_set_folder_callback,void,"BrowserWorker*, Browser Function,+,file_browser_worker_set_item_callback,void,"BrowserWorker*, BrowserWorkerListItemCallback" Function,+,file_browser_worker_set_list_callback,void,"BrowserWorker*, BrowserWorkerListLoadCallback" Function,+,file_browser_worker_set_long_load_callback,void,"BrowserWorker*, BrowserWorkerLongLoadCallback" +Function,+,file_info_is_dir,_Bool,const FileInfo* Function,+,file_stream_alloc,Stream*,Storage* Function,+,file_stream_close,_Bool,Stream* Function,+,file_stream_get_error,FS_Error,Stream* @@ -911,6 +914,7 @@ Function,-,flipper_application_preload_status_to_string,const char*,FlipperAppli Function,+,flipper_application_spawn,FuriThread*,"FlipperApplication*, void*" Function,+,flipper_format_buffered_file_alloc,FlipperFormat*,Storage* Function,+,flipper_format_buffered_file_close,_Bool,FlipperFormat* +Function,+,flipper_format_buffered_file_open_always,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_buffered_file_open_existing,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_delete_key,_Bool,"FlipperFormat*, const char*" Function,+,flipper_format_file_alloc,FlipperFormat*,Storage* @@ -1584,6 +1588,7 @@ Function,+,furi_thread_flags_get,uint32_t, Function,+,furi_thread_flags_set,uint32_t,"FuriThreadId, uint32_t" Function,+,furi_thread_flags_wait,uint32_t,"uint32_t, uint32_t, uint32_t" Function,+,furi_thread_free,void,FuriThread* +Function,+,furi_thread_get_appid,const char*,FuriThreadId Function,+,furi_thread_get_current,FuriThread*, Function,+,furi_thread_get_current_id,FuriThreadId, Function,+,furi_thread_get_current_priority,FuriThreadPriority, @@ -1598,6 +1603,7 @@ Function,+,furi_thread_is_suspended,_Bool,FuriThreadId Function,+,furi_thread_join,_Bool,FuriThread* Function,+,furi_thread_mark_as_service,void,FuriThread* Function,+,furi_thread_resume,void,FuriThreadId +Function,+,furi_thread_set_appid,void,"FuriThread*, const char*" Function,+,furi_thread_set_callback,void,"FuriThread*, FuriThreadCallback" Function,+,furi_thread_set_context,void,"FuriThread*, void*" Function,+,furi_thread_set_current_priority,void,FuriThreadPriority @@ -1658,22 +1664,33 @@ Function,+,hmac_sha256_update,void,"const hmac_sha256_context*, const uint8_t*, Function,-,hypot,double,"double, double" Function,-,hypotf,float,"float, float" Function,-,hypotl,long double,"long double, long double" -Function,+,ibutton_key_alloc,iButtonKey*, -Function,+,ibutton_key_clear_data,void,iButtonKey* -Function,+,ibutton_key_dallas_crc_is_valid,_Bool,iButtonKey* -Function,+,ibutton_key_dallas_is_1990_key,_Bool,iButtonKey* +Function,+,ibutton_key_alloc,iButtonKey*,size_t Function,+,ibutton_key_free,void,iButtonKey* -Function,+,ibutton_key_get_data_p,const uint8_t*,iButtonKey* -Function,+,ibutton_key_get_data_size,uint8_t,iButtonKey* -Function,+,ibutton_key_get_max_size,uint8_t, -Function,+,ibutton_key_get_size_by_type,uint8_t,iButtonKeyType -Function,+,ibutton_key_get_string_by_type,const char*,iButtonKeyType -Function,+,ibutton_key_get_type,iButtonKeyType,iButtonKey* -Function,+,ibutton_key_get_type_by_string,_Bool,"const char*, iButtonKeyType*" -Function,+,ibutton_key_set,void,"iButtonKey*, const iButtonKey*" -Function,+,ibutton_key_set_data,void,"iButtonKey*, uint8_t*, uint8_t" -Function,+,ibutton_key_set_type,void,"iButtonKey*, iButtonKeyType" -Function,+,ibutton_worker_alloc,iButtonWorker*, +Function,+,ibutton_key_get_protocol_id,iButtonProtocolId,const iButtonKey* +Function,+,ibutton_key_reset,void,iButtonKey* +Function,+,ibutton_key_set_protocol_id,void,"iButtonKey*, iButtonProtocolId" +Function,+,ibutton_protocols_alloc,iButtonProtocols*, +Function,+,ibutton_protocols_apply_edits,void,"iButtonProtocols*, const iButtonKey*" +Function,+,ibutton_protocols_emulate_start,void,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_protocols_emulate_stop,void,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_protocols_free,void,iButtonProtocols* +Function,+,ibutton_protocols_get_editable_data,void,"iButtonProtocols*, const iButtonKey*, iButtonEditableData*" +Function,+,ibutton_protocols_get_features,uint32_t,"iButtonProtocols*, iButtonProtocolId" +Function,+,ibutton_protocols_get_id_by_name,iButtonProtocolId,"iButtonProtocols*, const char*" +Function,+,ibutton_protocols_get_manufacturer,const char*,"iButtonProtocols*, iButtonProtocolId" +Function,+,ibutton_protocols_get_max_data_size,size_t,iButtonProtocols* +Function,+,ibutton_protocols_get_name,const char*,"iButtonProtocols*, iButtonProtocolId" +Function,+,ibutton_protocols_get_protocol_count,uint32_t, +Function,+,ibutton_protocols_is_valid,_Bool,"iButtonProtocols*, const iButtonKey*" +Function,+,ibutton_protocols_load,_Bool,"iButtonProtocols*, iButtonKey*, const char*" +Function,+,ibutton_protocols_read,_Bool,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_protocols_render_brief_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*" +Function,+,ibutton_protocols_render_data,void,"iButtonProtocols*, const iButtonKey*, FuriString*" +Function,+,ibutton_protocols_render_error,void,"iButtonProtocols*, const iButtonKey*, FuriString*" +Function,+,ibutton_protocols_save,_Bool,"iButtonProtocols*, const iButtonKey*, const char*" +Function,+,ibutton_protocols_write_blank,_Bool,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_protocols_write_copy,_Bool,"iButtonProtocols*, iButtonKey*" +Function,+,ibutton_worker_alloc,iButtonWorker*,iButtonProtocols* Function,+,ibutton_worker_emulate_set_callback,void,"iButtonWorker*, iButtonWorkerEmulateCallback, void*" Function,+,ibutton_worker_emulate_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_free,void,iButtonWorker* @@ -1682,8 +1699,9 @@ Function,+,ibutton_worker_read_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_start_thread,void,iButtonWorker* Function,+,ibutton_worker_stop,void,iButtonWorker* Function,+,ibutton_worker_stop_thread,void,iButtonWorker* +Function,+,ibutton_worker_write_blank_start,void,"iButtonWorker*, iButtonKey*" +Function,+,ibutton_worker_write_copy_start,void,"iButtonWorker*, iButtonKey*" Function,+,ibutton_worker_write_set_callback,void,"iButtonWorker*, iButtonWorkerWriteCallback, void*" -Function,+,ibutton_worker_write_start,void,"iButtonWorker*, iButtonKey*" Function,+,icon_animation_alloc,IconAnimation*,const Icon* Function,+,icon_animation_free,void,IconAnimation* Function,+,icon_animation_get_height,uint8_t,const IconAnimation* @@ -2147,12 +2165,6 @@ Function,+,notification_message,void,"NotificationApp*, const NotificationSequen Function,+,notification_message_block,void,"NotificationApp*, const NotificationSequence*" Function,-,nrand48,long,unsigned short[3] Function,-,on_exit,int,"void (*)(int, void*), void*" -Function,+,onewire_device_alloc,OneWireDevice*,"uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t" -Function,+,onewire_device_attach,void,"OneWireDevice*, OneWireSlave*" -Function,+,onewire_device_detach,void,OneWireDevice* -Function,+,onewire_device_free,void,OneWireDevice* -Function,+,onewire_device_get_id_p,uint8_t*,OneWireDevice* -Function,+,onewire_device_send_id,void,OneWireDevice* Function,+,onewire_host_alloc,OneWireHost*,const GpioPin* Function,+,onewire_host_free,void,OneWireHost* Function,+,onewire_host_read,uint8_t,OneWireHost* @@ -2167,10 +2179,15 @@ Function,+,onewire_host_stop,void,OneWireHost* Function,+,onewire_host_target_search,void,"OneWireHost*, uint8_t" Function,+,onewire_host_write,void,"OneWireHost*, uint8_t" Function,+,onewire_host_write_bit,void,"OneWireHost*, _Bool" +Function,+,onewire_host_write_bytes,void,"OneWireHost*, const uint8_t*, uint16_t" Function,+,onewire_slave_alloc,OneWireSlave*,const GpioPin* -Function,+,onewire_slave_attach,void,"OneWireSlave*, OneWireDevice*" -Function,+,onewire_slave_detach,void,OneWireSlave* Function,+,onewire_slave_free,void,OneWireSlave* +Function,+,onewire_slave_receive,_Bool,"OneWireSlave*, uint8_t*, size_t" +Function,+,onewire_slave_receive_bit,_Bool,OneWireSlave* +Function,+,onewire_slave_send,_Bool,"OneWireSlave*, const uint8_t*, size_t" +Function,+,onewire_slave_send_bit,_Bool,"OneWireSlave*, _Bool" +Function,+,onewire_slave_set_command_callback,void,"OneWireSlave*, OneWireSlaveCommandCallback, void*" +Function,+,onewire_slave_set_reset_callback,void,"OneWireSlave*, OneWireSlaveResetCallback, void*" Function,+,onewire_slave_set_result_callback,void,"OneWireSlave*, OneWireSlaveResultCallback, void*" Function,+,onewire_slave_start,void,OneWireSlave* Function,+,onewire_slave_stop,void,OneWireSlave* @@ -2219,6 +2236,7 @@ Function,+,power_off,void,Power* Function,+,power_reboot,void,PowerBootMode Function,+,powf,float,"float, float" Function,-,powl,long double,"long double, long double" +Function,+,pretty_format_bytes_hex_canonical,void,"FuriString*, size_t, const char*, const uint8_t*, size_t" Function,-,printf,int,"const char*, ..." Function,-,prng_successor,uint32_t,"uint32_t, uint32_t" Function,+,property_value_out,void,"PropertyValueContext*, const char*, unsigned int, ..." @@ -2560,14 +2578,18 @@ Function,+,sscanf,int,"const char*, const char*, ..." Function,-,star_line_reset_kl_type,void, Function,-,star_line_reset_mfname,void, Function,+,storage_common_copy,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_exists,_Bool,"Storage*, const char*" Function,+,storage_common_fs_info,FS_Error,"Storage*, const char*, uint64_t*, uint64_t*" Function,+,storage_common_merge,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_migrate,FS_Error,"Storage*, const char*, const char*" Function,+,storage_common_mkdir,FS_Error,"Storage*, const char*" Function,+,storage_common_remove,FS_Error,"Storage*, const char*" Function,+,storage_common_rename,FS_Error,"Storage*, const char*, const char*" +Function,+,storage_common_resolve_path_and_ensure_app_directory,void,"Storage*, FuriString*" Function,+,storage_common_stat,FS_Error,"Storage*, const char*, FileInfo*" Function,+,storage_common_timestamp,FS_Error,"Storage*, const char*, uint32_t*" Function,+,storage_dir_close,_Bool,File* +Function,+,storage_dir_exists,_Bool,"Storage*, const char*" Function,+,storage_dir_open,_Bool,"File*, const char*" Function,+,storage_dir_read,_Bool,"File*, FileInfo*, char*, uint16_t" Function,-,storage_dir_rewind,_Bool,File* @@ -2696,9 +2718,10 @@ Function,-,strupr,char*,char* Function,-,strverscmp,int,"const char*, const char*" Function,-,strxfrm,size_t,"char*, const char*, size_t" Function,-,strxfrm_l,size_t,"char*, const char*, size_t, locale_t" -Function,+,subghz_block_generic_deserialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*" +Function,+,subghz_block_generic_deserialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*" +Function,+,subghz_block_generic_deserialize_check_count_bit,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, uint16_t" Function,+,subghz_block_generic_get_preset_name,void,"const char*, FuriString*" -Function,+,subghz_block_generic_serialize,_Bool,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_block_generic_serialize,SubGhzProtocolStatus,"SubGhzBlockGeneric*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_environment_alloc,SubGhzEnvironment*, Function,+,subghz_environment_free,void,SubGhzEnvironment* Function,+,subghz_environment_get_alutech_at_4n_rainbow_table_file_name,const char*,SubGhzEnvironment* @@ -2742,537 +2765,537 @@ Function,+,subghz_protocol_blocks_reverse_key,uint64_t,"uint64_t, uint8_t" Function,+,subghz_protocol_blocks_set_bit_array,void,"_Bool, uint8_t[], size_t, size_t" Function,+,subghz_protocol_blocks_xor_bytes,uint8_t,"const uint8_t[], size_t" Function,-,subghz_protocol_decoder_alutech_at_4n_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_alutech_at_4n_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_alutech_at_4n_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_alutech_at_4n_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_alutech_at_4n_free,void,void* Function,-,subghz_protocol_decoder_alutech_at_4n_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_alutech_at_4n_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_alutech_at_4n_reset,void,void* -Function,-,subghz_protocol_decoder_alutech_at_4n_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_alutech_at_4n_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_ansonic_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_ansonic_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_ansonic_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_ansonic_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_ansonic_free,void,void* Function,-,subghz_protocol_decoder_ansonic_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_ansonic_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_ansonic_reset,void,void* -Function,-,subghz_protocol_decoder_ansonic_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_base_deserialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*" +Function,-,subghz_protocol_decoder_ansonic_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_protocol_decoder_base_deserialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*" Function,+,subghz_protocol_decoder_base_get_hash_data,uint8_t,SubGhzProtocolDecoderBase* Function,+,subghz_protocol_decoder_base_get_string,_Bool,"SubGhzProtocolDecoderBase*, FuriString*" -Function,+,subghz_protocol_decoder_base_serialize,_Bool,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*" +Function,+,subghz_protocol_decoder_base_serialize,SubGhzProtocolStatus,"SubGhzProtocolDecoderBase*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_base_set_decoder_callback,void,"SubGhzProtocolDecoderBase*, SubGhzProtocolDecoderBaseRxCallback, void*" Function,-,subghz_protocol_decoder_bett_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_bett_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_bett_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_bett_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_bett_free,void,void* Function,-,subghz_protocol_decoder_bett_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_bett_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_bett_reset,void,void* -Function,-,subghz_protocol_decoder_bett_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_bett_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_bin_raw_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_bin_raw_data_input_rssi,void,"SubGhzProtocolDecoderBinRAW*, float" -Function,-,subghz_protocol_decoder_bin_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_bin_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_bin_raw_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_bin_raw_free,void,void* Function,-,subghz_protocol_decoder_bin_raw_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_bin_raw_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_bin_raw_reset,void,void* -Function,-,subghz_protocol_decoder_bin_raw_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_bin_raw_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_came_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_came_atomo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_came_atomo_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_came_atomo_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_came_atomo_free,void,void* Function,-,subghz_protocol_decoder_came_atomo_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_came_atomo_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_came_atomo_reset,void,void* -Function,-,subghz_protocol_decoder_came_atomo_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_came_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_came_atomo_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_came_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_came_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_came_free,void,void* Function,-,subghz_protocol_decoder_came_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_came_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_came_reset,void,void* -Function,-,subghz_protocol_decoder_came_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_came_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_came_twee_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_came_twee_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_came_twee_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_came_twee_free,void,void* Function,-,subghz_protocol_decoder_came_twee_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_came_twee_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_came_twee_reset,void,void* -Function,-,subghz_protocol_decoder_came_twee_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_came_twee_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_chamb_code_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_chamb_code_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_chamb_code_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_chamb_code_free,void,void* Function,-,subghz_protocol_decoder_chamb_code_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_chamb_code_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_chamb_code_reset,void,void* -Function,-,subghz_protocol_decoder_chamb_code_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_chamb_code_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_clemsa_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_clemsa_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_clemsa_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_clemsa_free,void,void* Function,-,subghz_protocol_decoder_clemsa_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_clemsa_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_clemsa_reset,void,void* -Function,-,subghz_protocol_decoder_clemsa_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_clemsa_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_doitrand_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_doitrand_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_doitrand_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_doitrand_free,void,void* Function,-,subghz_protocol_decoder_doitrand_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_doitrand_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_doitrand_reset,void,void* -Function,-,subghz_protocol_decoder_doitrand_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_doitrand_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_dooya_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_dooya_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_dooya_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_dooya_free,void,void* Function,-,subghz_protocol_decoder_dooya_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_dooya_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_dooya_reset,void,void* -Function,-,subghz_protocol_decoder_dooya_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_dooya_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_faac_slh_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_faac_slh_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_faac_slh_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_faac_slh_free,void,void* Function,-,subghz_protocol_decoder_faac_slh_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_faac_slh_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_faac_slh_reset,void,void* -Function,-,subghz_protocol_decoder_faac_slh_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_faac_slh_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_gate_tx_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_gate_tx_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_gate_tx_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_gate_tx_free,void,void* Function,-,subghz_protocol_decoder_gate_tx_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_gate_tx_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_gate_tx_reset,void,void* -Function,-,subghz_protocol_decoder_gate_tx_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_gate_tx_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_holtek_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_holtek_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_holtek_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_holtek_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_holtek_free,void,void* Function,-,subghz_protocol_decoder_holtek_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_holtek_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_holtek_reset,void,void* -Function,-,subghz_protocol_decoder_holtek_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_holtek_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_holtek_th12x_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_holtek_th12x_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_holtek_th12x_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_holtek_th12x_free,void,void* Function,-,subghz_protocol_decoder_holtek_th12x_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_holtek_th12x_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_holtek_th12x_reset,void,void* -Function,-,subghz_protocol_decoder_holtek_th12x_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_holtek_th12x_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_honeywell_wdb_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_honeywell_wdb_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_honeywell_wdb_free,void,void* Function,-,subghz_protocol_decoder_honeywell_wdb_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_honeywell_wdb_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_honeywell_wdb_reset,void,void* -Function,-,subghz_protocol_decoder_honeywell_wdb_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_honeywell_wdb_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_hormann_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_hormann_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_hormann_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_hormann_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_hormann_free,void,void* Function,-,subghz_protocol_decoder_hormann_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_hormann_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_hormann_reset,void,void* -Function,-,subghz_protocol_decoder_hormann_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_hormann_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_ido_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_ido_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_ido_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_ido_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_ido_free,void,void* Function,-,subghz_protocol_decoder_ido_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_ido_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_ido_reset,void,void* -Function,-,subghz_protocol_decoder_ido_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_ido_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_intertechno_v3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_intertechno_v3_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_intertechno_v3_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_intertechno_v3_free,void,void* Function,-,subghz_protocol_decoder_intertechno_v3_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_intertechno_v3_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_intertechno_v3_reset,void,void* -Function,-,subghz_protocol_decoder_intertechno_v3_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_intertechno_v3_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_keeloq_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_keeloq_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_keeloq_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_keeloq_free,void,void* Function,-,subghz_protocol_decoder_keeloq_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_keeloq_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_keeloq_reset,void,void* -Function,-,subghz_protocol_decoder_keeloq_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_keeloq_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_kia_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_kia_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_kia_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_kia_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_kia_free,void,void* Function,-,subghz_protocol_decoder_kia_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_kia_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_kia_reset,void,void* -Function,-,subghz_protocol_decoder_kia_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_kia_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_kinggates_stylo_4k_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_kinggates_stylo_4k_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_kinggates_stylo_4k_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_kinggates_stylo_4k_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_kinggates_stylo_4k_free,void,void* Function,-,subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_kinggates_stylo_4k_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_kinggates_stylo_4k_reset,void,void* -Function,-,subghz_protocol_decoder_kinggates_stylo_4k_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_kinggates_stylo_4k_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_linear_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_decoder_linear_delta3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_linear_delta3_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_linear_delta3_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_linear_delta3_free,void,void* Function,-,subghz_protocol_decoder_linear_delta3_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_linear_delta3_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_linear_delta3_reset,void,void* -Function,-,subghz_protocol_decoder_linear_delta3_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" -Function,-,subghz_protocol_decoder_linear_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_linear_delta3_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_linear_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_linear_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_linear_free,void,void* Function,-,subghz_protocol_decoder_linear_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_linear_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_linear_reset,void,void* -Function,-,subghz_protocol_decoder_linear_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_linear_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_magellan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_magellan_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_magellan_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_magellan_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_magellan_free,void,void* Function,-,subghz_protocol_decoder_magellan_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_magellan_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_magellan_reset,void,void* -Function,-,subghz_protocol_decoder_magellan_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_magellan_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_marantec_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_marantec_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_marantec_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_marantec_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_marantec_free,void,void* Function,-,subghz_protocol_decoder_marantec_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_marantec_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_marantec_reset,void,void* -Function,-,subghz_protocol_decoder_marantec_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_marantec_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_megacode_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_megacode_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_megacode_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_megacode_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_megacode_free,void,void* Function,-,subghz_protocol_decoder_megacode_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_megacode_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_megacode_reset,void,void* -Function,-,subghz_protocol_decoder_megacode_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_megacode_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_nero_radio_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_nero_radio_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_nero_radio_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_nero_radio_free,void,void* Function,-,subghz_protocol_decoder_nero_radio_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_nero_radio_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_nero_radio_reset,void,void* -Function,-,subghz_protocol_decoder_nero_radio_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_nero_radio_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_nero_sketch_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_nero_sketch_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_nero_sketch_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_nero_sketch_free,void,void* Function,-,subghz_protocol_decoder_nero_sketch_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_nero_sketch_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_nero_sketch_reset,void,void* -Function,-,subghz_protocol_decoder_nero_sketch_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_nero_sketch_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_nice_flo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_nice_flo_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_nice_flo_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_nice_flo_free,void,void* Function,-,subghz_protocol_decoder_nice_flo_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_nice_flo_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_nice_flo_reset,void,void* -Function,-,subghz_protocol_decoder_nice_flo_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_nice_flo_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_nice_flor_s_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_nice_flor_s_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_nice_flor_s_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_nice_flor_s_free,void,void* Function,-,subghz_protocol_decoder_nice_flor_s_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_nice_flor_s_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_nice_flor_s_reset,void,void* -Function,-,subghz_protocol_decoder_nice_flor_s_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_nice_flor_s_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_phoenix_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_phoenix_v2_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_phoenix_v2_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_phoenix_v2_free,void,void* Function,-,subghz_protocol_decoder_phoenix_v2_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_phoenix_v2_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_phoenix_v2_reset,void,void* -Function,-,subghz_protocol_decoder_phoenix_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_phoenix_v2_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_power_smart_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_power_smart_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_power_smart_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_power_smart_free,void,void* Function,-,subghz_protocol_decoder_power_smart_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_power_smart_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_power_smart_reset,void,void* -Function,-,subghz_protocol_decoder_power_smart_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_power_smart_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_protocol_decoder_princeton_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_princeton_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_princeton_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,+,subghz_protocol_decoder_princeton_feed,void,"void*, _Bool, uint32_t" Function,+,subghz_protocol_decoder_princeton_free,void,void* Function,+,subghz_protocol_decoder_princeton_get_hash_data,uint8_t,void* Function,+,subghz_protocol_decoder_princeton_get_string,void,"void*, FuriString*" Function,+,subghz_protocol_decoder_princeton_reset,void,void* -Function,+,subghz_protocol_decoder_princeton_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_princeton_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,+,subghz_protocol_decoder_raw_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_decoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_decoder_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,+,subghz_protocol_decoder_raw_feed,void,"void*, _Bool, uint32_t" Function,+,subghz_protocol_decoder_raw_free,void,void* Function,+,subghz_protocol_decoder_raw_get_string,void,"void*, FuriString*" Function,+,subghz_protocol_decoder_raw_reset,void,void* Function,-,subghz_protocol_decoder_scher_khan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_scher_khan_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_scher_khan_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_scher_khan_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_scher_khan_free,void,void* Function,-,subghz_protocol_decoder_scher_khan_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_scher_khan_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_scher_khan_reset,void,void* -Function,-,subghz_protocol_decoder_scher_khan_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_scher_khan_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_secplus_v1_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_secplus_v1_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_secplus_v1_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_secplus_v1_free,void,void* Function,-,subghz_protocol_decoder_secplus_v1_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_secplus_v1_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_secplus_v1_reset,void,void* -Function,-,subghz_protocol_decoder_secplus_v1_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_secplus_v1_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_secplus_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_secplus_v2_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_secplus_v2_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_secplus_v2_free,void,void* Function,-,subghz_protocol_decoder_secplus_v2_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_secplus_v2_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_secplus_v2_reset,void,void* -Function,-,subghz_protocol_decoder_secplus_v2_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_secplus_v2_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_smc5326_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_smc5326_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_smc5326_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_smc5326_free,void,void* Function,-,subghz_protocol_decoder_smc5326_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_smc5326_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_smc5326_reset,void,void* -Function,-,subghz_protocol_decoder_smc5326_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_smc5326_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_somfy_keytis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_somfy_keytis_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_somfy_keytis_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_somfy_keytis_free,void,void* Function,-,subghz_protocol_decoder_somfy_keytis_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_somfy_keytis_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_somfy_keytis_reset,void,void* -Function,-,subghz_protocol_decoder_somfy_keytis_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_somfy_keytis_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_somfy_telis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_somfy_telis_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_somfy_telis_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_somfy_telis_free,void,void* Function,-,subghz_protocol_decoder_somfy_telis_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_somfy_telis_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_somfy_telis_reset,void,void* -Function,-,subghz_protocol_decoder_somfy_telis_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_somfy_telis_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_decoder_star_line_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_decoder_star_line_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_decoder_star_line_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_decoder_star_line_feed,void,"void*, _Bool, uint32_t" Function,-,subghz_protocol_decoder_star_line_free,void,void* Function,-,subghz_protocol_decoder_star_line_get_hash_data,uint8_t,void* Function,-,subghz_protocol_decoder_star_line_get_string,void,"void*, FuriString*" Function,-,subghz_protocol_decoder_star_line_reset,void,void* -Function,-,subghz_protocol_decoder_star_line_serialize,_Bool,"void*, FlipperFormat*, SubGhzRadioPreset*" +Function,-,subghz_protocol_decoder_star_line_serialize,SubGhzProtocolStatus,"void*, FlipperFormat*, SubGhzRadioPreset*" Function,-,subghz_protocol_encoder_alutech_at_4n_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_alutech_at_4n_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_alutech_at_4n_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_alutech_at_4n_free,void,void* Function,-,subghz_protocol_encoder_alutech_at_4n_stop,void,void* Function,-,subghz_protocol_encoder_alutech_at_4n_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_ansonic_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_ansonic_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_ansonic_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_ansonic_free,void,void* Function,-,subghz_protocol_encoder_ansonic_stop,void,void* Function,-,subghz_protocol_encoder_ansonic_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_bett_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_bett_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_bett_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_bett_free,void,void* Function,-,subghz_protocol_encoder_bett_stop,void,void* Function,-,subghz_protocol_encoder_bett_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_bin_raw_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_bin_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_bin_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_bin_raw_free,void,void* Function,-,subghz_protocol_encoder_bin_raw_stop,void,void* Function,-,subghz_protocol_encoder_bin_raw_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_came_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_came_atomo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_came_atomo_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_came_atomo_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_came_atomo_free,void,void* Function,-,subghz_protocol_encoder_came_atomo_stop,void,void* Function,-,subghz_protocol_encoder_came_atomo_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_came_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_came_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_came_free,void,void* Function,-,subghz_protocol_encoder_came_stop,void,void* Function,-,subghz_protocol_encoder_came_twee_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_came_twee_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_came_twee_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_came_twee_free,void,void* Function,-,subghz_protocol_encoder_came_twee_stop,void,void* Function,-,subghz_protocol_encoder_came_twee_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_came_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_chamb_code_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_chamb_code_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_chamb_code_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_chamb_code_free,void,void* Function,-,subghz_protocol_encoder_chamb_code_stop,void,void* Function,-,subghz_protocol_encoder_chamb_code_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_clemsa_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_clemsa_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_clemsa_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_clemsa_free,void,void* Function,-,subghz_protocol_encoder_clemsa_stop,void,void* Function,-,subghz_protocol_encoder_clemsa_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_doitrand_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_doitrand_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_doitrand_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_doitrand_free,void,void* Function,-,subghz_protocol_encoder_doitrand_stop,void,void* Function,-,subghz_protocol_encoder_doitrand_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_dooya_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_dooya_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_dooya_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_dooya_free,void,void* Function,-,subghz_protocol_encoder_dooya_stop,void,void* Function,-,subghz_protocol_encoder_dooya_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_faac_slh_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_faac_slh_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_faac_slh_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_faac_slh_free,void,void* Function,-,subghz_protocol_encoder_faac_slh_stop,void,void* Function,-,subghz_protocol_encoder_faac_slh_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_gate_tx_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_gate_tx_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_gate_tx_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_gate_tx_free,void,void* Function,-,subghz_protocol_encoder_gate_tx_stop,void,void* Function,-,subghz_protocol_encoder_gate_tx_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_holtek_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_holtek_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_holtek_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_holtek_free,void,void* Function,-,subghz_protocol_encoder_holtek_stop,void,void* Function,-,subghz_protocol_encoder_holtek_th12x_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_holtek_th12x_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_holtek_th12x_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_holtek_th12x_free,void,void* Function,-,subghz_protocol_encoder_holtek_th12x_stop,void,void* Function,-,subghz_protocol_encoder_holtek_th12x_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_holtek_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_honeywell_wdb_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_honeywell_wdb_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_honeywell_wdb_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_honeywell_wdb_free,void,void* Function,-,subghz_protocol_encoder_honeywell_wdb_stop,void,void* Function,-,subghz_protocol_encoder_honeywell_wdb_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_hormann_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_hormann_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_hormann_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_hormann_free,void,void* Function,-,subghz_protocol_encoder_hormann_stop,void,void* Function,-,subghz_protocol_encoder_hormann_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_intertechno_v3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_intertechno_v3_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_intertechno_v3_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_intertechno_v3_free,void,void* Function,-,subghz_protocol_encoder_intertechno_v3_stop,void,void* Function,-,subghz_protocol_encoder_intertechno_v3_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_keeloq_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_keeloq_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_keeloq_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_keeloq_free,void,void* Function,-,subghz_protocol_encoder_keeloq_stop,void,void* Function,-,subghz_protocol_encoder_keeloq_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_kinggates_stylo_4k_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_kinggates_stylo_4k_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_kinggates_stylo_4k_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_kinggates_stylo_4k_free,void,void* Function,-,subghz_protocol_encoder_kinggates_stylo_4k_stop,void,void* Function,-,subghz_protocol_encoder_kinggates_stylo_4k_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_linear_alloc,void*,SubGhzEnvironment* Function,-,subghz_protocol_encoder_linear_delta3_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_linear_delta3_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_linear_delta3_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_linear_delta3_free,void,void* Function,-,subghz_protocol_encoder_linear_delta3_stop,void,void* Function,-,subghz_protocol_encoder_linear_delta3_yield,LevelDuration,void* -Function,-,subghz_protocol_encoder_linear_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_linear_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_linear_free,void,void* Function,-,subghz_protocol_encoder_linear_stop,void,void* Function,-,subghz_protocol_encoder_linear_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_magellan_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_magellan_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_magellan_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_magellan_free,void,void* Function,-,subghz_protocol_encoder_magellan_stop,void,void* Function,-,subghz_protocol_encoder_magellan_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_marantec_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_marantec_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_marantec_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_marantec_free,void,void* Function,-,subghz_protocol_encoder_marantec_stop,void,void* Function,-,subghz_protocol_encoder_marantec_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_megacode_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_megacode_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_megacode_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_megacode_free,void,void* Function,-,subghz_protocol_encoder_megacode_stop,void,void* Function,-,subghz_protocol_encoder_megacode_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_nero_radio_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nero_radio_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_nero_radio_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_nero_radio_free,void,void* Function,-,subghz_protocol_encoder_nero_radio_stop,void,void* Function,-,subghz_protocol_encoder_nero_radio_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_nero_sketch_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nero_sketch_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_nero_sketch_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_nero_sketch_free,void,void* Function,-,subghz_protocol_encoder_nero_sketch_stop,void,void* Function,-,subghz_protocol_encoder_nero_sketch_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_nice_flo_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nice_flo_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_nice_flo_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_nice_flo_free,void,void* Function,-,subghz_protocol_encoder_nice_flo_stop,void,void* Function,-,subghz_protocol_encoder_nice_flo_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_nice_flor_s_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_nice_flor_s_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_nice_flor_s_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_nice_flor_s_free,void,void* Function,-,subghz_protocol_encoder_nice_flor_s_stop,void,void* Function,-,subghz_protocol_encoder_nice_flor_s_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_phoenix_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_phoenix_v2_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_phoenix_v2_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_phoenix_v2_free,void,void* Function,-,subghz_protocol_encoder_phoenix_v2_stop,void,void* Function,-,subghz_protocol_encoder_phoenix_v2_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_power_smart_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_power_smart_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_power_smart_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_power_smart_free,void,void* Function,-,subghz_protocol_encoder_power_smart_stop,void,void* Function,-,subghz_protocol_encoder_power_smart_yield,LevelDuration,void* Function,+,subghz_protocol_encoder_princeton_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_princeton_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_princeton_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,+,subghz_protocol_encoder_princeton_free,void,void* Function,+,subghz_protocol_encoder_princeton_stop,void,void* Function,+,subghz_protocol_encoder_princeton_yield,LevelDuration,void* Function,+,subghz_protocol_encoder_raw_alloc,void*,SubGhzEnvironment* -Function,+,subghz_protocol_encoder_raw_deserialize,_Bool,"void*, FlipperFormat*" +Function,+,subghz_protocol_encoder_raw_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,+,subghz_protocol_encoder_raw_free,void,void* Function,+,subghz_protocol_encoder_raw_stop,void,void* Function,+,subghz_protocol_encoder_raw_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_secplus_v1_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_secplus_v1_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_secplus_v1_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_secplus_v1_free,void,void* Function,-,subghz_protocol_encoder_secplus_v1_stop,void,void* Function,-,subghz_protocol_encoder_secplus_v1_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_secplus_v2_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_secplus_v2_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_secplus_v2_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_secplus_v2_free,void,void* Function,-,subghz_protocol_encoder_secplus_v2_stop,void,void* Function,-,subghz_protocol_encoder_secplus_v2_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_smc5326_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_smc5326_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_smc5326_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_smc5326_free,void,void* Function,-,subghz_protocol_encoder_smc5326_stop,void,void* Function,-,subghz_protocol_encoder_smc5326_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_somfy_keytis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_somfy_keytis_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_somfy_keytis_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_somfy_keytis_free,void,void* Function,-,subghz_protocol_encoder_somfy_keytis_stop,void,void* Function,-,subghz_protocol_encoder_somfy_keytis_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_somfy_telis_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_somfy_telis_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_somfy_telis_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_somfy_telis_free,void,void* Function,-,subghz_protocol_encoder_somfy_telis_stop,void,void* Function,-,subghz_protocol_encoder_somfy_telis_yield,LevelDuration,void* Function,-,subghz_protocol_encoder_star_line_alloc,void*,SubGhzEnvironment* -Function,-,subghz_protocol_encoder_star_line_deserialize,_Bool,"void*, FlipperFormat*" +Function,-,subghz_protocol_encoder_star_line_deserialize,SubGhzProtocolStatus,"void*, FlipperFormat*" Function,-,subghz_protocol_encoder_star_line_free,void,void* Function,-,subghz_protocol_encoder_star_line_stop,void,void* Function,-,subghz_protocol_encoder_star_line_yield,LevelDuration,void* @@ -3321,7 +3344,7 @@ Function,+,subghz_setting_load,void,"SubGhzSetting*, const char*" Function,+,subghz_setting_load_custom_preset,_Bool,"SubGhzSetting*, const char*, FlipperFormat*" Function,+,subghz_setting_set_default_frequency,void,"SubGhzSetting*, uint32_t" Function,+,subghz_transmitter_alloc_init,SubGhzTransmitter*,"SubGhzEnvironment*, const char*" -Function,+,subghz_transmitter_deserialize,_Bool,"SubGhzTransmitter*, FlipperFormat*" +Function,+,subghz_transmitter_deserialize,SubGhzProtocolStatus,"SubGhzTransmitter*, FlipperFormat*" Function,+,subghz_transmitter_free,void,SubGhzTransmitter* Function,+,subghz_transmitter_get_protocol_instance,SubGhzProtocolEncoderBase*,SubGhzTransmitter* Function,+,subghz_transmitter_stop,_Bool,SubGhzTransmitter* diff --git a/firmware/targets/f7/src/recovery.c b/firmware/targets/f7/src/recovery.c index d56be4fe0..db538b0d5 100644 --- a/firmware/targets/f7/src/recovery.c +++ b/firmware/targets/f7/src/recovery.c @@ -5,24 +5,20 @@ #include #include -#define COUNTER_VALUE (100U) +#define COUNTER_VALUE (136U) static void flipper_boot_recovery_draw_splash(u8g2_t* fb, size_t progress) { - u8g2_ClearBuffer(fb); - u8g2_SetDrawColor(fb, 0x01); - - u8g2_SetFont(fb, u8g2_font_helvB08_tr); - u8g2_DrawStr(fb, 2, 8, "PIN and Factory Reset"); - u8g2_SetFont(fb, u8g2_font_haxrcorp4089_tr); - u8g2_DrawStr(fb, 2, 21, "Hold Right to confirm"); - u8g2_DrawStr(fb, 2, 31, "Press Down to cancel"); - if(progress < COUNTER_VALUE) { - size_t width = progress / (COUNTER_VALUE / 100); - u8g2_DrawBox(fb, 14 + (50 - width / 2), 54, width, 3); + // Fill the progress bar while the progress is going down + u8g2_SetDrawColor(fb, 0x01); + u8g2_DrawRFrame(fb, 59, 41, 69, 8, 2); + size_t width = (COUNTER_VALUE - progress) * 68 / COUNTER_VALUE; + u8g2_DrawBox(fb, 60, 42, width, 6); + } else { + u8g2_SetDrawColor(fb, 0x00); + u8g2_DrawRBox(fb, 59, 41, 69, 8, 2); } - u8g2_SetPowerSave(fb, 0); u8g2_SendBuffer(fb); } @@ -31,6 +27,18 @@ void flipper_boot_recovery_exec() { u8g2_Setup_st756x_flipper(fb, U8G2_R0, u8x8_hw_spi_stm32, u8g2_gpio_and_delay_stm32); u8g2_InitDisplay(fb); + furi_hal_compress_icon_init(); + uint8_t* splash_data = NULL; + furi_hal_compress_icon_decode(icon_get_data(&I_Erase_pin_128x64), &splash_data); + + u8g2_ClearBuffer(fb); + u8g2_SetDrawColor(fb, 0x01); + + // Draw the recovery picture + u8g2_DrawXBM(fb, 0, 0, 128, 64, splash_data); + u8g2_SendBuffer(fb); + u8g2_SetPowerSave(fb, 0); + size_t counter = COUNTER_VALUE; while(counter) { if(!furi_hal_gpio_read(&gpio_button_down)) { diff --git a/furi/core/thread.c b/furi/core/thread.c index ea9f45e84..b45651c29 100644 --- a/furi/core/thread.c +++ b/furi/core/thread.c @@ -35,6 +35,8 @@ struct FuriThread { void* state_context; char* name; + char* appid; + configSTACK_DEPTH_TYPE stack_size; FuriThreadPriority priority; @@ -122,11 +124,25 @@ FuriThread* furi_thread_alloc() { thread->output.buffer = furi_string_alloc(); thread->is_service = false; + FuriThread* parent = NULL; + if(xTaskGetSchedulerState() != taskSCHEDULER_NOT_STARTED) { + // TLS is not available, if we called not from thread context + parent = pvTaskGetThreadLocalStoragePointer(NULL, 0); + + if(parent && parent->appid) { + furi_thread_set_appid(thread, parent->appid); + } else { + furi_thread_set_appid(thread, "unknown"); + } + } else { + // if scheduler is not started, we are starting driver thread + furi_thread_set_appid(thread, "driver"); + } + FuriHalRtcHeapTrackMode mode = furi_hal_rtc_get_heap_track_mode(); if(mode == FuriHalRtcHeapTrackModeAll) { thread->heap_trace_enabled = true; } else if(mode == FuriHalRtcHeapTrackModeTree && furi_thread_get_current_id()) { - FuriThread* parent = pvTaskGetThreadLocalStoragePointer(NULL, 0); if(parent) thread->heap_trace_enabled = parent->heap_trace_enabled; } else { thread->heap_trace_enabled = false; @@ -153,6 +169,7 @@ void furi_thread_free(FuriThread* thread) { furi_assert(thread->state == FuriThreadStateStopped); if(thread->name) free((void*)thread->name); + if(thread->appid) free((void*)thread->appid); furi_string_free(thread->output.buffer); free(thread); @@ -165,6 +182,13 @@ void furi_thread_set_name(FuriThread* thread, const char* name) { thread->name = name ? strdup(name) : NULL; } +void furi_thread_set_appid(FuriThread* thread, const char* appid) { + furi_assert(thread); + furi_assert(thread->state == FuriThreadStateStopped); + if(thread->appid) free((void*)thread->appid); + thread->appid = appid ? strdup(appid) : NULL; +} + void furi_thread_mark_as_service(FuriThread* thread) { thread->is_service = true; } @@ -498,6 +522,20 @@ const char* furi_thread_get_name(FuriThreadId thread_id) { return (name); } +const char* furi_thread_get_appid(FuriThreadId thread_id) { + TaskHandle_t hTask = (TaskHandle_t)thread_id; + const char* appid = "system"; + + if(!FURI_IS_IRQ_MODE() && (hTask != NULL)) { + FuriThread* thread = (FuriThread*)pvTaskGetThreadLocalStoragePointer(hTask, 0); + if(thread) { + appid = thread->appid; + } + } + + return (appid); +} + uint32_t furi_thread_get_stack_space(FuriThreadId thread_id) { TaskHandle_t hTask = (TaskHandle_t)thread_id; uint32_t sz; diff --git a/furi/core/thread.h b/furi/core/thread.h index 2675f7cee..8f4398419 100644 --- a/furi/core/thread.h +++ b/furi/core/thread.h @@ -87,6 +87,16 @@ void furi_thread_free(FuriThread* thread); */ void furi_thread_set_name(FuriThread* thread, const char* name); +/** + * @brief Set FuriThread appid + * Technically, it is like a "process id", but it is not a system-wide unique identifier. + * All threads spawned by the same app will have the same appid. + * + * @param thread + * @param appid + */ +void furi_thread_set_appid(FuriThread* thread, const char* appid); + /** Mark thread as service * The service cannot be stopped or removed, and cannot exit from the thread body * @@ -233,10 +243,37 @@ uint32_t furi_thread_flags_get(void); uint32_t furi_thread_flags_wait(uint32_t flags, uint32_t options, uint32_t timeout); +/** + * @brief Enumerate threads + * + * @param thread_array array of FuriThreadId, where thread ids will be stored + * @param array_items array size + * @return uint32_t threads count + */ uint32_t furi_thread_enumerate(FuriThreadId* thread_array, uint32_t array_items); +/** + * @brief Get thread name + * + * @param thread_id + * @return const char* name or NULL + */ const char* furi_thread_get_name(FuriThreadId thread_id); +/** + * @brief Get thread appid + * + * @param thread_id + * @return const char* appid + */ +const char* furi_thread_get_appid(FuriThreadId thread_id); + +/** + * @brief Get thread stack watermark + * + * @param thread_id + * @return uint32_t + */ uint32_t furi_thread_get_stack_space(FuriThreadId thread_id); /** Get STDOUT callback for thead diff --git a/furi/flipper.c b/furi/flipper.c index d16a84a10..f0147c060 100644 --- a/furi/flipper.c +++ b/furi/flipper.c @@ -41,6 +41,7 @@ void flipper_init() { FLIPPER_SERVICES[i].app, NULL); furi_thread_mark_as_service(thread); + furi_thread_set_appid(thread, FLIPPER_SERVICES[i].appid); furi_thread_start(thread); } diff --git a/lib/flipper_format/flipper_format.c b/lib/flipper_format/flipper_format.c index 292dab5f1..bb1aa59f5 100644 --- a/lib/flipper_format/flipper_format.c +++ b/lib/flipper_format/flipper_format.c @@ -91,6 +91,12 @@ bool flipper_format_file_open_always(FlipperFormat* flipper_format, const char* return file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS); } +bool flipper_format_buffered_file_open_always(FlipperFormat* flipper_format, const char* path) { + furi_assert(flipper_format); + return buffered_file_stream_open( + flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_ALWAYS); +} + bool flipper_format_file_open_new(FlipperFormat* flipper_format, const char* path) { furi_assert(flipper_format); return file_stream_open(flipper_format->stream, path, FSAM_READ_WRITE, FSOM_CREATE_NEW); diff --git a/lib/flipper_format/flipper_format.h b/lib/flipper_format/flipper_format.h index 743918e3b..671ff6fa0 100644 --- a/lib/flipper_format/flipper_format.h +++ b/lib/flipper_format/flipper_format.h @@ -131,7 +131,7 @@ bool flipper_format_file_open_existing(FlipperFormat* flipper_format, const char /** * Open existing file, buffered mode. - * Use only if FlipperFormat allocated as a file. + * Use only if FlipperFormat allocated as a buffered file. * @param flipper_format Pointer to a FlipperFormat instance * @param path File path * @return True on success @@ -156,6 +156,15 @@ bool flipper_format_file_open_append(FlipperFormat* flipper_format, const char* */ bool flipper_format_file_open_always(FlipperFormat* flipper_format, const char* path); +/** + * Open file. Creates a new file, or deletes the contents of the file if it already exists, buffered mode. + * Use only if FlipperFormat allocated as a buffered file. + * @param flipper_format Pointer to a FlipperFormat instance + * @param path File path + * @return True on success + */ +bool flipper_format_buffered_file_open_always(FlipperFormat* flipper_format, const char* path); + /** * Open file. Creates a new file, fails if file already exists. * Use only if FlipperFormat allocated as a file. diff --git a/lib/one_wire/SConscript b/lib/one_wire/SConscript index 5e06d21e3..56d4759eb 100644 --- a/lib/one_wire/SConscript +++ b/lib/one_wire/SConscript @@ -11,8 +11,9 @@ env.Append( File("one_wire_host_timing.h"), File("one_wire_host.h"), File("one_wire_slave.h"), - File("one_wire_device.h"), + File("ibutton/ibutton_key.h"), File("ibutton/ibutton_worker.h"), + File("ibutton/ibutton_protocols.h"), File("maxim_crc.h"), ], ) diff --git a/lib/one_wire/ibutton/ibutton_key.c b/lib/one_wire/ibutton/ibutton_key.c index 7b7571a29..926a826a2 100644 --- a/lib/one_wire/ibutton/ibutton_key.c +++ b/lib/one_wire/ibutton/ibutton_key.c @@ -1,110 +1,43 @@ -#include -#include -#include "ibutton_key.h" +#include "ibutton_key_i.h" struct iButtonKey { - uint8_t data[IBUTTON_KEY_DATA_SIZE]; - iButtonKeyType type; + iButtonProtocolId protocol_id; + iButtonProtocolData* protocol_data; + size_t protocol_data_size; }; -iButtonKey* ibutton_key_alloc() { +iButtonKey* ibutton_key_alloc(size_t data_size) { iButtonKey* key = malloc(sizeof(iButtonKey)); - memset(key, 0, sizeof(iButtonKey)); + + key->protocol_id = iButtonProtocolIdInvalid; + key->protocol_data = malloc(data_size); + key->protocol_data_size = data_size; + return key; } void ibutton_key_free(iButtonKey* key) { + free(key->protocol_data); free(key); } -void ibutton_key_set(iButtonKey* to, const iButtonKey* from) { - memcpy(to, from, sizeof(iButtonKey)); +void ibutton_key_reset(iButtonKey* key) { + key->protocol_id = iButtonProtocolIdInvalid; + memset(key->protocol_data, 0, key->protocol_data_size); } -void ibutton_key_set_data(iButtonKey* key, uint8_t* data, uint8_t data_count) { - furi_check(data_count > 0); - furi_check(data_count <= IBUTTON_KEY_DATA_SIZE); - - memset(key->data, 0, IBUTTON_KEY_DATA_SIZE); - memcpy(key->data, data, data_count); +iButtonProtocolId ibutton_key_get_protocol_id(const iButtonKey* key) { + return key->protocol_id; } -void ibutton_key_clear_data(iButtonKey* key) { - memset(key->data, 0, IBUTTON_KEY_DATA_SIZE); +void ibutton_key_set_protocol_id(iButtonKey* key, iButtonProtocolId protocol_id) { + key->protocol_id = protocol_id; } -const uint8_t* ibutton_key_get_data_p(iButtonKey* key) { - return key->data; +iButtonProtocolData* ibutton_key_get_protocol_data(const iButtonKey* key) { + return key->protocol_data; } -uint8_t ibutton_key_get_data_size(iButtonKey* key) { - return ibutton_key_get_size_by_type(key->type); -} - -void ibutton_key_set_type(iButtonKey* key, iButtonKeyType key_type) { - key->type = key_type; -} - -iButtonKeyType ibutton_key_get_type(iButtonKey* key) { - return key->type; -} - -const char* ibutton_key_get_string_by_type(iButtonKeyType key_type) { - switch(key_type) { - case iButtonKeyCyfral: - return "Cyfral"; - break; - case iButtonKeyMetakom: - return "Metakom"; - break; - case iButtonKeyDS1990: - return "Dallas"; - break; - default: - furi_crash("Invalid iButton type"); - } -} - -bool ibutton_key_get_type_by_string(const char* type_string, iButtonKeyType* key_type) { - if(strcmp(type_string, ibutton_key_get_string_by_type(iButtonKeyCyfral)) == 0) { - *key_type = iButtonKeyCyfral; - } else if(strcmp(type_string, ibutton_key_get_string_by_type(iButtonKeyMetakom)) == 0) { - *key_type = iButtonKeyMetakom; - } else if(strcmp(type_string, ibutton_key_get_string_by_type(iButtonKeyDS1990)) == 0) { - *key_type = iButtonKeyDS1990; - } else { - return false; - } - - return true; -} - -uint8_t ibutton_key_get_size_by_type(iButtonKeyType key_type) { - uint8_t size = 0; - - switch(key_type) { - case iButtonKeyCyfral: - size = 2; - break; - case iButtonKeyMetakom: - size = 4; - break; - case iButtonKeyDS1990: - size = 8; - break; - } - - return size; -} - -uint8_t ibutton_key_get_max_size() { - return IBUTTON_KEY_DATA_SIZE; -} - -bool ibutton_key_dallas_crc_is_valid(iButtonKey* key) { - return (maxim_crc8(key->data, 8, MAXIM_CRC8_INIT) == 0); -} - -bool ibutton_key_dallas_is_1990_key(iButtonKey* key) { - return (key->data[0] == 0x01); +size_t ibutton_key_get_protocol_data_size(const iButtonKey* key) { + return key->protocol_data_size; } diff --git a/lib/one_wire/ibutton/ibutton_key.h b/lib/one_wire/ibutton/ibutton_key.h index d682555a8..1848cd672 100644 --- a/lib/one_wire/ibutton/ibutton_key.h +++ b/lib/one_wire/ibutton/ibutton_key.h @@ -5,127 +5,49 @@ */ #pragma once -#include + +#include + +#include "protocols/protocol_common.h" #ifdef __cplusplus extern "C" { #endif -#define IBUTTON_KEY_DATA_SIZE 8 -#define IBUTTON_KEY_NAME_SIZE 22 - -typedef enum { - iButtonKeyDS1990, - iButtonKeyCyfral, - iButtonKeyMetakom, -} iButtonKeyType; - typedef struct iButtonKey iButtonKey; /** - * Allocate key - * @return iButtonKey* + * Allocate a key object + * @param [in] data_size maximum data size held by the key + * @return pointer to the key object */ -iButtonKey* ibutton_key_alloc(); +iButtonKey* ibutton_key_alloc(size_t data_size); /** - * Free key - * @param key + * Destroy the key object, free resources + * @param [in] key pointer to the key object */ void ibutton_key_free(iButtonKey* key); /** - * Copy key - * @param to - * @param from + * Get the protocol id held by the key + * @param [in] key pointer to the key object + * @return protocol id held by the key */ -void ibutton_key_set(iButtonKey* to, const iButtonKey* from); +iButtonProtocolId ibutton_key_get_protocol_id(const iButtonKey* key); /** - * Set key data - * @param key - * @param data - * @param data_count + * Set the protocol id held by the key + * @param [in] key pointer to the key object + * @param [in] protocol_id new protocol id */ -void ibutton_key_set_data(iButtonKey* key, uint8_t* data, uint8_t data_count); +void ibutton_key_set_protocol_id(iButtonKey* key, iButtonProtocolId protocol_id); /** - * Clear key data - * @param key + * Reset the protocol id and data held by the key + * @param [in] key pointer to the key object */ -void ibutton_key_clear_data(iButtonKey* key); - -/** - * Get pointer to key data - * @param key - * @return const uint8_t* - */ -const uint8_t* ibutton_key_get_data_p(iButtonKey* key); - -/** - * Get key data size - * @param key - * @return uint8_t - */ -uint8_t ibutton_key_get_data_size(iButtonKey* key); - -/** - * Set key type - * @param key - * @param key_type - */ -void ibutton_key_set_type(iButtonKey* key, iButtonKeyType key_type); - -/** - * Get key type - * @param key - * @return iButtonKeyType - */ -iButtonKeyType ibutton_key_get_type(iButtonKey* key); - -/** - * Get type string from key type - * @param key_type - * @return const char* - */ -const char* ibutton_key_get_string_by_type(iButtonKeyType key_type); - -/** - * Get key type from string - * @param type_string - * @param key_type - * @return bool - */ -bool ibutton_key_get_type_by_string(const char* type_string, iButtonKeyType* key_type); - -/** - * Get key data size from type - * @param key_type - * @return uint8_t - */ -uint8_t ibutton_key_get_size_by_type(iButtonKeyType key_type); - -/** - * Get max key size - * @return uint8_t - */ -uint8_t ibutton_key_get_max_size(); - -/** - * Check if CRC for onewire key is valid - * @param key - * @return true - * @return false - */ -bool ibutton_key_dallas_crc_is_valid(iButtonKey* key); - -/** - * Check if onewire key is a DS1990 key - * @param key - * @return true - * @return false - */ -bool ibutton_key_dallas_is_1990_key(iButtonKey* key); +void ibutton_key_reset(iButtonKey* key); #ifdef __cplusplus } diff --git a/lib/one_wire/ibutton/ibutton_key_command.h b/lib/one_wire/ibutton/ibutton_key_command.h deleted file mode 100644 index 88049d064..000000000 --- a/lib/one_wire/ibutton/ibutton_key_command.h +++ /dev/null @@ -1,28 +0,0 @@ -/** - * @file ibutton_key_command.h - * - * List of misc commands for Dallas and blanks - */ - -#pragma once - -#define RW1990_1_CMD_WRITE_RECORD_FLAG 0xD1 -#define RW1990_1_CMD_READ_RECORD_FLAG 0xB5 -#define RW1990_1_CMD_WRITE_ROM 0xD5 - -#define RW1990_2_CMD_WRITE_RECORD_FLAG 0x1D -#define RW1990_2_CMD_READ_RECORD_FLAG 0x1E -#define RW1990_2_CMD_WRITE_ROM 0xD5 - -#define TM2004_CMD_READ_STATUS 0xAA -#define TM2004_CMD_READ_MEMORY 0xF0 -#define TM2004_CMD_WRITE_ROM 0x3C -#define TM2004_CMD_FINALIZATION 0x35 -#define TM2004_ANSWER_READ_MEMORY 0xF5 - -#define TM01_CMD_WRITE_RECORD_FLAG 0xC1 -#define TM01_CMD_WRITE_ROM 0xC5 -#define TM01_CMD_SWITCH_TO_CYFRAL 0xCA -#define TM01_CMD_SWITCH_TO_METAKOM 0xCB - -#define DS1990_CMD_READ_ROM 0x33 diff --git a/lib/one_wire/ibutton/ibutton_key_i.h b/lib/one_wire/ibutton/ibutton_key_i.h new file mode 100644 index 000000000..b527c65b4 --- /dev/null +++ b/lib/one_wire/ibutton/ibutton_key_i.h @@ -0,0 +1,9 @@ +#pragma once + +#include "ibutton_key.h" + +#include "protocols/protocol_common_i.h" + +iButtonProtocolData* ibutton_key_get_protocol_data(const iButtonKey* key); + +size_t ibutton_key_get_protocol_data_size(const iButtonKey* key); diff --git a/lib/one_wire/ibutton/ibutton_protocols.c b/lib/one_wire/ibutton/ibutton_protocols.c new file mode 100644 index 000000000..75aa225ef --- /dev/null +++ b/lib/one_wire/ibutton/ibutton_protocols.c @@ -0,0 +1,309 @@ +#include "ibutton_protocols.h" + +#include + +#include "ibutton_key_i.h" + +#include "protocols/protocol_group_defs.h" + +#define IBUTTON_FILE_TYPE "Flipper iButton key" + +#define IBUTTON_PROTOCOL_KEY_V1 "Key type" +#define IBUTTON_PROTOCOL_KEY_V2 "Protocol" + +#define IBUTTON_CURRENT_FORMAT_VERSION 2U + +#define GET_PROTOCOL_GROUP(id) \ + iButtonProtocolGroupInfo info; \ + ibutton_protocols_get_group_by_id(protocols, (id), &info); + +#define GROUP_BASE (info.base) +#define GROUP_DATA (info.group) +#define PROTOCOL_ID (info.id) + +struct iButtonProtocols { + iButtonProtocolGroupData** group_datas; +}; + +typedef struct { + const iButtonProtocolGroupBase* base; + iButtonProtocolGroupData* group; + iButtonProtocolLocalId id; +} iButtonProtocolGroupInfo; + +static void ibutton_protocols_get_group_by_id( + iButtonProtocols* protocols, + iButtonProtocolId id, + iButtonProtocolGroupInfo* info) { + iButtonProtocolLocalId local_id = id; + + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + if(local_id < (signed)ibutton_protocol_groups[i]->protocol_count) { + info->base = ibutton_protocol_groups[i]; + info->group = protocols->group_datas[i]; + info->id = local_id; + return; + + } else { + local_id -= ibutton_protocol_groups[i]->protocol_count; + } + } + furi_crash(NULL); +} + +iButtonProtocols* ibutton_protocols_alloc() { + iButtonProtocols* protocols = malloc(sizeof(iButtonProtocols*)); + + protocols->group_datas = malloc(sizeof(iButtonProtocolGroupData*) * iButtonProtocolGroupMax); + + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + protocols->group_datas[i] = ibutton_protocol_groups[i]->alloc(); + } + + return protocols; +} + +void ibutton_protocols_free(iButtonProtocols* protocols) { + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + ibutton_protocol_groups[i]->free(protocols->group_datas[i]); + } + + free(protocols->group_datas); + free(protocols); +} + +uint32_t ibutton_protocols_get_protocol_count() { + uint32_t count = 0; + + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + count += ibutton_protocol_groups[i]->protocol_count; + } + + return count; +} + +iButtonProtocolId ibutton_protocols_get_id_by_name(iButtonProtocols* protocols, const char* name) { + iButtonProtocolLocalId offset = 0; + + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + iButtonProtocolLocalId local_id; + if(ibutton_protocol_groups[i]->get_id_by_name(protocols->group_datas[i], &local_id, name)) { + return local_id + offset; + } + offset += ibutton_protocol_groups[i]->protocol_count; + } + return iButtonProtocolIdInvalid; +} + +uint32_t ibutton_protocols_get_features(iButtonProtocols* protocols, iButtonProtocolId id) { + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->get_features(GROUP_DATA, PROTOCOL_ID); +} + +size_t ibutton_protocols_get_max_data_size(iButtonProtocols* protocols) { + size_t max_size = 0; + + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + const size_t current_max_size = + ibutton_protocol_groups[i]->get_max_data_size(protocols->group_datas[i]); + if(current_max_size > max_size) { + max_size = current_max_size; + } + } + + return max_size; +} + +const char* ibutton_protocols_get_manufacturer(iButtonProtocols* protocols, iButtonProtocolId id) { + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->get_manufacturer(GROUP_DATA, PROTOCOL_ID); +} + +const char* ibutton_protocols_get_name(iButtonProtocols* protocols, iButtonProtocolId id) { + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->get_name(GROUP_DATA, PROTOCOL_ID); +} + +bool ibutton_protocols_read(iButtonProtocols* protocols, iButtonKey* key) { + iButtonProtocolLocalId id = iButtonProtocolIdInvalid; + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + iButtonProtocolLocalId offset = 0; + for(iButtonProtocolGroupId i = 0; i < iButtonProtocolGroupMax; ++i) { + if(ibutton_protocol_groups[i]->read(protocols->group_datas[i], data, &id)) { + id += offset; + break; + } + offset += ibutton_protocol_groups[i]->protocol_count; + } + + ibutton_key_set_protocol_id(key, id); + return id != iButtonProtocolIdInvalid; +} + +bool ibutton_protocols_write_blank(iButtonProtocols* protocols, iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->write_blank(GROUP_DATA, data, PROTOCOL_ID); +} + +bool ibutton_protocols_write_copy(iButtonProtocols* protocols, iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->write_copy(GROUP_DATA, data, PROTOCOL_ID); +} + +void ibutton_protocols_emulate_start(iButtonProtocols* protocols, iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->emulate_start(GROUP_DATA, data, PROTOCOL_ID); +} + +void ibutton_protocols_emulate_stop(iButtonProtocols* protocols, iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->emulate_stop(GROUP_DATA, data, PROTOCOL_ID); +} + +bool ibutton_protocols_save( + iButtonProtocols* protocols, + const iButtonKey* key, + const char* file_name) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + const iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + bool success = false; + Storage* storage = furi_record_open(RECORD_STORAGE); + + FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); + + do { + const char* protocol_name = ibutton_protocols_get_name(protocols, id); + + if(!flipper_format_buffered_file_open_always(ff, file_name)) break; + + if(!flipper_format_write_header_cstr(ff, IBUTTON_FILE_TYPE, IBUTTON_CURRENT_FORMAT_VERSION)) + break; + if(!flipper_format_write_string_cstr(ff, IBUTTON_PROTOCOL_KEY_V2, protocol_name)) break; + + GET_PROTOCOL_GROUP(id); + if(!GROUP_BASE->save(GROUP_DATA, data, PROTOCOL_ID, ff)) break; + + success = true; + } while(false); + + flipper_format_free(ff); + furi_record_close(RECORD_STORAGE); + + return success; +} + +bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name) { + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + bool success = false; + Storage* storage = furi_record_open(RECORD_STORAGE); + + FlipperFormat* ff = flipper_format_buffered_file_alloc(storage); + FuriString* tmp = furi_string_alloc(); + + do { + if(!flipper_format_buffered_file_open_existing(ff, file_name)) break; + + uint32_t version; + + if(!flipper_format_read_header(ff, tmp, &version)) break; + if(!furi_string_equal(tmp, IBUTTON_FILE_TYPE)) break; + + if(version == 1) { + if(!flipper_format_read_string(ff, IBUTTON_PROTOCOL_KEY_V1, tmp)) break; + } else if(version == 2) { + if(!flipper_format_read_string(ff, IBUTTON_PROTOCOL_KEY_V2, tmp)) break; + } else { + break; + } + + const iButtonProtocolId id = + ibutton_protocols_get_id_by_name(protocols, furi_string_get_cstr(tmp)); + ibutton_key_set_protocol_id(key, id); + + GET_PROTOCOL_GROUP(id); + if(!GROUP_BASE->load(GROUP_DATA, data, PROTOCOL_ID, version, ff)) break; + + success = true; + } while(false); + + flipper_format_free(ff); + furi_string_free(tmp); + furi_record_close(RECORD_STORAGE); + + return success; +} + +void ibutton_protocols_render_data( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + const iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->render_data(GROUP_DATA, data, PROTOCOL_ID, result); +} + +void ibutton_protocols_render_brief_data( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + const iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->render_brief_data(GROUP_DATA, data, PROTOCOL_ID, result); +} + +void ibutton_protocols_render_error( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + const iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->render_error(GROUP_DATA, data, PROTOCOL_ID, result); +} + +bool ibutton_protocols_is_valid(iButtonProtocols* protocols, const iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + const iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + return GROUP_BASE->is_valid(GROUP_DATA, data, PROTOCOL_ID); +} + +void ibutton_protocols_get_editable_data( + iButtonProtocols* protocols, + const iButtonKey* key, + iButtonEditableData* editable) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->get_editable_data(GROUP_DATA, data, PROTOCOL_ID, editable); +} + +void ibutton_protocols_apply_edits(iButtonProtocols* protocols, const iButtonKey* key) { + const iButtonProtocolId id = ibutton_key_get_protocol_id(key); + iButtonProtocolData* data = ibutton_key_get_protocol_data(key); + + GET_PROTOCOL_GROUP(id); + GROUP_BASE->apply_edits(GROUP_DATA, data, PROTOCOL_ID); +} diff --git a/lib/one_wire/ibutton/ibutton_protocols.h b/lib/one_wire/ibutton/ibutton_protocols.h new file mode 100644 index 000000000..0e7ed0a80 --- /dev/null +++ b/lib/one_wire/ibutton/ibutton_protocols.h @@ -0,0 +1,197 @@ +/** + * @file ibutton_protocols.h + * + * Common interface for accessing various iButton protocols + */ + +#pragma once + +#include +#include + +#include "protocols/protocol_common.h" + +#include "ibutton_key.h" + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct iButtonProtocols iButtonProtocols; + +/** + * Allocate an iButtonProtocols object + * @return pointer to an iButtonProtocols object + */ +iButtonProtocols* ibutton_protocols_alloc(); + +/** + * Destroy an iButtonProtocols object, free resources + * @param [in] protocols pointer to an iButtonProtocols object + */ +void ibutton_protocols_free(iButtonProtocols* protocols); + +/** + * Get the total number of available protocols + */ +uint32_t ibutton_protocols_get_protocol_count(); + +/** + * Get maximum data size out of all protocols available + * @param [in] protocols pointer to an iButtonProtocols object + * @return maximum data size in bytes + */ +size_t ibutton_protocols_get_max_data_size(iButtonProtocols* protocols); + +/** + * Get the protocol id based on its name + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] name pointer to a string containing the name + * @return protocol id on success on iButtonProtocolIdInvalid on failure + */ +iButtonProtocolId ibutton_protocols_get_id_by_name(iButtonProtocols* protocols, const char* name); + +/** + * Get the manufacturer name based on the protocol id + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] id id of the protocol in question + * @return pointer to a statically allocated string with manufacturer name + */ +const char* ibutton_protocols_get_manufacturer(iButtonProtocols* protocols, iButtonProtocolId id); + +/** + * Get the protocol name based on the protocol id + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] id id of the protocol in question + * @return pointer to a statically allocated string with protocol name + */ +const char* ibutton_protocols_get_name(iButtonProtocols* protocols, iButtonProtocolId id); + +/** + * Get protocol features bitmask by protocol id + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] id id of the protocol in question + */ +uint32_t ibutton_protocols_get_features(iButtonProtocols* protocols, iButtonProtocolId id); + +/** + * Read a physical device (a key or an emulator) + * @param [in] protocols pointer to an iButtonProtocols object + * @param [out] key pointer to the key to read into (must be allocated before) + * @return true on success, false on failure + */ +bool ibutton_protocols_read(iButtonProtocols* protocols, iButtonKey* key); + +/** + * Write the key to a blank + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be written + * @return true on success, false on failure + */ +bool ibutton_protocols_write_blank(iButtonProtocols* protocols, iButtonKey* key); + +/** + * Write the key to another one of the same type + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be written + * @return true on success, false on failure + */ +bool ibutton_protocols_write_copy(iButtonProtocols* protocols, iButtonKey* key); + +/** + * Start emulating the key + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be emulated + */ +void ibutton_protocols_emulate_start(iButtonProtocols* protocols, iButtonKey* key); + +/** + * Stop emulating the key + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be emulated + */ +void ibutton_protocols_emulate_stop(iButtonProtocols* protocols, iButtonKey* key); + +/** + * Save the key data to a file. + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be saved + * @param [in] file_name full absolute path to the file name + * @return true on success, false on failure + */ +bool ibutton_protocols_save( + iButtonProtocols* protocols, + const iButtonKey* key, + const char* file_name); + +/** + * Load the key from a file. + * @param [in] protocols pointer to an iButtonProtocols object + * @param [out] key pointer to the key to load into (must be allocated before) + * @param [in] file_name full absolute path to the file name + * @return true on success, false on failure + */ +bool ibutton_protocols_load(iButtonProtocols* protocols, iButtonKey* key, const char* file_name); + +/** + * Format a string containing device full data + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be rendered + * @param [out] result pointer to the FuriString instance (must be initialized) + */ +void ibutton_protocols_render_data( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result); + +/** + * Format a string containing device brief data + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be rendered + * @param [out] result pointer to the FuriString instance (must be initialized) + */ +void ibutton_protocols_render_brief_data( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result); + +/** + * Format a string containing error message (for invalid keys) + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be rendered + * @param [out] result pointer to the FuriString instance (must be initialized) + */ +void ibutton_protocols_render_error( + iButtonProtocols* protocols, + const iButtonKey* key, + FuriString* result); + +/** + * Check whether the key data is valid + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be checked + * @return true if data is valid, false otherwise + */ +bool ibutton_protocols_is_valid(iButtonProtocols* protocols, const iButtonKey* key); + +/** + * Get a pointer to the key's editable data (for in-place editing) + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in] key pointer to the key to be checked + * @param [out] editable pointer to a structure to contain the editable data + */ +void ibutton_protocols_get_editable_data( + iButtonProtocols* protocols, + const iButtonKey* key, + iButtonEditableData* editable); + +/** + * Make all necessary internal adjustments after editing the key + * @param [in] protocols pointer to an iButtonProtocols object + * @param [in,out] key pointer to the key to be adjusted + */ +void ibutton_protocols_apply_edits(iButtonProtocols* protocols, const iButtonKey* key); + +#ifdef __cplusplus +} +#endif diff --git a/lib/one_wire/ibutton/ibutton_worker.c b/lib/one_wire/ibutton/ibutton_worker.c index 1fe39b5e5..d40dba71a 100644 --- a/lib/one_wire/ibutton/ibutton_worker.c +++ b/lib/one_wire/ibutton/ibutton_worker.c @@ -1,13 +1,14 @@ -#include -#include -#include #include "ibutton_worker_i.h" +#include "ibutton_protocols.h" + +#include typedef enum { iButtonMessageEnd, iButtonMessageStop, iButtonMessageRead, - iButtonMessageWrite, + iButtonMessageWriteBlank, + iButtonMessageWriteCopy, iButtonMessageEmulate, iButtonMessageNotifyEmulate, } iButtonMessageType; @@ -21,26 +22,15 @@ typedef struct { static int32_t ibutton_worker_thread(void* thread_context); -iButtonWorker* ibutton_worker_alloc() { +iButtonWorker* ibutton_worker_alloc(iButtonProtocols* protocols) { iButtonWorker* worker = malloc(sizeof(iButtonWorker)); - worker->key_p = NULL; - worker->key_data = malloc(ibutton_key_get_max_size()); - worker->host = onewire_host_alloc(&ibutton_gpio); - worker->slave = onewire_slave_alloc(&ibutton_gpio); - worker->writer = ibutton_writer_alloc(worker->host); - worker->device = onewire_device_alloc(0, 0, 0, 0, 0, 0, 0, 0); + + worker->protocols = protocols; worker->messages = furi_message_queue_alloc(1, sizeof(iButtonMessage)); - worker->mode_index = iButtonWorkerIdle; - worker->read_cb = NULL; - worker->write_cb = NULL; - worker->emulate_cb = NULL; - worker->cb_ctx = NULL; - + worker->mode_index = iButtonWorkerModeIdle; worker->thread = furi_thread_alloc_ex("iButtonWorker", 2048, ibutton_worker_thread, worker); - worker->protocols = protocol_dict_alloc(ibutton_protocols, iButtonProtocolMax); - return worker; } @@ -48,7 +38,7 @@ void ibutton_worker_read_set_callback( iButtonWorker* worker, iButtonWorkerReadCallback callback, void* context) { - furi_check(worker->mode_index == iButtonWorkerIdle); + furi_check(worker->mode_index == iButtonWorkerModeIdle); worker->read_cb = callback; worker->cb_ctx = context; } @@ -57,7 +47,7 @@ void ibutton_worker_write_set_callback( iButtonWorker* worker, iButtonWorkerWriteCallback callback, void* context) { - furi_check(worker->mode_index == iButtonWorkerIdle); + furi_check(worker->mode_index == iButtonWorkerModeIdle); worker->write_cb = callback; worker->cb_ctx = context; } @@ -66,7 +56,7 @@ void ibutton_worker_emulate_set_callback( iButtonWorker* worker, iButtonWorkerEmulateCallback callback, void* context) { - furi_check(worker->mode_index == iButtonWorkerIdle); + furi_check(worker->mode_index == iButtonWorkerModeIdle); worker->emulate_cb = callback; worker->cb_ctx = context; } @@ -77,8 +67,14 @@ void ibutton_worker_read_start(iButtonWorker* worker, iButtonKey* key) { furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk); } -void ibutton_worker_write_start(iButtonWorker* worker, iButtonKey* key) { - iButtonMessage message = {.type = iButtonMessageWrite, .data.key = key}; +void ibutton_worker_write_blank_start(iButtonWorker* worker, iButtonKey* key) { + iButtonMessage message = {.type = iButtonMessageWriteBlank, .data.key = key}; + furi_check( + furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk); +} + +void ibutton_worker_write_copy_start(iButtonWorker* worker, iButtonKey* key) { + iButtonMessage message = {.type = iButtonMessageWriteCopy, .data.key = key}; furi_check( furi_message_queue_put(worker->messages, &message, FuriWaitForever) == FuriStatusOk); } @@ -96,19 +92,8 @@ void ibutton_worker_stop(iButtonWorker* worker) { } void ibutton_worker_free(iButtonWorker* worker) { - ibutton_writer_free(worker->writer); - - onewire_slave_free(worker->slave); - - onewire_host_free(worker->host); - onewire_device_free(worker->device); - - protocol_dict_free(worker->protocols); - furi_message_queue_free(worker->messages); - furi_thread_free(worker->thread); - free(worker->key_data); free(worker); } @@ -137,7 +122,7 @@ void ibutton_worker_notify_emulate(iButtonWorker* worker) { } void ibutton_worker_set_key_p(iButtonWorker* worker, iButtonKey* key) { - worker->key_p = key; + worker->key = key; } static int32_t ibutton_worker_thread(void* thread_context) { @@ -154,25 +139,29 @@ static int32_t ibutton_worker_thread(void* thread_context) { if(status == FuriStatusOk) { switch(message.type) { case iButtonMessageEnd: - ibutton_worker_switch_mode(worker, iButtonWorkerIdle); + ibutton_worker_switch_mode(worker, iButtonWorkerModeIdle); ibutton_worker_set_key_p(worker, NULL); running = false; break; case iButtonMessageStop: - ibutton_worker_switch_mode(worker, iButtonWorkerIdle); + ibutton_worker_switch_mode(worker, iButtonWorkerModeIdle); ibutton_worker_set_key_p(worker, NULL); break; case iButtonMessageRead: ibutton_worker_set_key_p(worker, message.data.key); - ibutton_worker_switch_mode(worker, iButtonWorkerRead); + ibutton_worker_switch_mode(worker, iButtonWorkerModeRead); break; - case iButtonMessageWrite: + case iButtonMessageWriteBlank: ibutton_worker_set_key_p(worker, message.data.key); - ibutton_worker_switch_mode(worker, iButtonWorkerWrite); + ibutton_worker_switch_mode(worker, iButtonWorkerModeWriteBlank); + break; + case iButtonMessageWriteCopy: + ibutton_worker_set_key_p(worker, message.data.key); + ibutton_worker_switch_mode(worker, iButtonWorkerModeWriteCopy); break; case iButtonMessageEmulate: ibutton_worker_set_key_p(worker, message.data.key); - ibutton_worker_switch_mode(worker, iButtonWorkerEmulate); + ibutton_worker_switch_mode(worker, iButtonWorkerModeEmulate); break; case iButtonMessageNotifyEmulate: if(worker->emulate_cb) { diff --git a/lib/one_wire/ibutton/ibutton_worker.h b/lib/one_wire/ibutton/ibutton_worker.h index 5c8b1fc39..2a12a3194 100644 --- a/lib/one_wire/ibutton/ibutton_worker.h +++ b/lib/one_wire/ibutton/ibutton_worker.h @@ -5,7 +5,9 @@ */ #pragma once + #include "ibutton_key.h" +#include "ibutton_protocols.h" #ifdef __cplusplus extern "C" { @@ -28,7 +30,7 @@ typedef struct iButtonWorker iButtonWorker; * Allocate ibutton worker * @return iButtonWorker* */ -iButtonWorker* ibutton_worker_alloc(); +iButtonWorker* ibutton_worker_alloc(iButtonProtocols* protocols); /** * Free ibutton worker @@ -78,11 +80,18 @@ void ibutton_worker_write_set_callback( void* context); /** - * Start write mode + * Start write blank mode * @param worker * @param key */ -void ibutton_worker_write_start(iButtonWorker* worker, iButtonKey* key); +void ibutton_worker_write_blank_start(iButtonWorker* worker, iButtonKey* key); + +/** + * Start write copy mode + * @param worker + * @param key + */ +void ibutton_worker_write_copy_start(iButtonWorker* worker, iButtonKey* key); /** * Set "emulate success" callback diff --git a/lib/one_wire/ibutton/ibutton_worker_i.h b/lib/one_wire/ibutton/ibutton_worker_i.h index 2396fbd61..5f259a38a 100644 --- a/lib/one_wire/ibutton/ibutton_worker_i.h +++ b/lib/one_wire/ibutton/ibutton_worker_i.h @@ -5,13 +5,11 @@ */ #pragma once + +#include +#include + #include "ibutton_worker.h" -#include "ibutton_writer.h" -#include "../one_wire_host.h" -#include "../one_wire_slave.h" -#include "../one_wire_device.h" -#include -#include "protocols/ibutton_protocols.h" #ifdef __cplusplus extern "C" { @@ -25,19 +23,16 @@ typedef struct { } iButtonWorkerModeType; typedef enum { - iButtonWorkerIdle = 0, - iButtonWorkerRead = 1, - iButtonWorkerWrite = 2, - iButtonWorkerEmulate = 3, + iButtonWorkerModeIdle, + iButtonWorkerModeRead, + iButtonWorkerModeWriteBlank, + iButtonWorkerModeWriteCopy, + iButtonWorkerModeEmulate, } iButtonWorkerMode; struct iButtonWorker { - iButtonKey* key_p; - uint8_t* key_data; - OneWireHost* host; - OneWireSlave* slave; - OneWireDevice* device; - iButtonWriter* writer; + iButtonKey* key; + iButtonProtocols* protocols; iButtonWorkerMode mode_index; FuriMessageQueue* messages; FuriThread* thread; @@ -45,10 +40,8 @@ struct iButtonWorker { iButtonWorkerReadCallback read_cb; iButtonWorkerWriteCallback write_cb; iButtonWorkerEmulateCallback emulate_cb; - void* cb_ctx; - ProtocolDict* protocols; - iButtonProtocol protocol_to_encode; + void* cb_ctx; }; extern const iButtonWorkerModeType ibutton_worker_modes[]; diff --git a/lib/one_wire/ibutton/ibutton_worker_modes.c b/lib/one_wire/ibutton/ibutton_worker_modes.c index 4f7f0855a..1b8e0a3b8 100644 --- a/lib/one_wire/ibutton/ibutton_worker_modes.c +++ b/lib/one_wire/ibutton/ibutton_worker_modes.c @@ -1,23 +1,28 @@ -#include -#include #include "ibutton_worker_i.h" -#include "ibutton_key_command.h" -void ibutton_worker_mode_idle_start(iButtonWorker* worker); -void ibutton_worker_mode_idle_tick(iButtonWorker* worker); -void ibutton_worker_mode_idle_stop(iButtonWorker* worker); +#include -void ibutton_worker_mode_emulate_start(iButtonWorker* worker); -void ibutton_worker_mode_emulate_tick(iButtonWorker* worker); -void ibutton_worker_mode_emulate_stop(iButtonWorker* worker); +#include +#include -void ibutton_worker_mode_read_start(iButtonWorker* worker); -void ibutton_worker_mode_read_tick(iButtonWorker* worker); -void ibutton_worker_mode_read_stop(iButtonWorker* worker); +#include "ibutton_protocols.h" -void ibutton_worker_mode_write_start(iButtonWorker* worker); -void ibutton_worker_mode_write_tick(iButtonWorker* worker); -void ibutton_worker_mode_write_stop(iButtonWorker* worker); +static void ibutton_worker_mode_idle_start(iButtonWorker* worker); +static void ibutton_worker_mode_idle_tick(iButtonWorker* worker); +static void ibutton_worker_mode_idle_stop(iButtonWorker* worker); + +static void ibutton_worker_mode_emulate_start(iButtonWorker* worker); +static void ibutton_worker_mode_emulate_tick(iButtonWorker* worker); +static void ibutton_worker_mode_emulate_stop(iButtonWorker* worker); + +static void ibutton_worker_mode_read_start(iButtonWorker* worker); +static void ibutton_worker_mode_read_tick(iButtonWorker* worker); +static void ibutton_worker_mode_read_stop(iButtonWorker* worker); + +static void ibutton_worker_mode_write_common_start(iButtonWorker* worker); +static void ibutton_worker_mode_write_blank_tick(iButtonWorker* worker); +static void ibutton_worker_mode_write_copy_tick(iButtonWorker* worker); +static void ibutton_worker_mode_write_common_stop(iButtonWorker* worker); const iButtonWorkerModeType ibutton_worker_modes[] = { { @@ -34,9 +39,15 @@ const iButtonWorkerModeType ibutton_worker_modes[] = { }, { .quant = 1000, - .start = ibutton_worker_mode_write_start, - .tick = ibutton_worker_mode_write_tick, - .stop = ibutton_worker_mode_write_stop, + .start = ibutton_worker_mode_write_common_start, + .tick = ibutton_worker_mode_write_blank_tick, + .stop = ibutton_worker_mode_write_common_stop, + }, + { + .quant = 1000, + .start = ibutton_worker_mode_write_common_start, + .tick = ibutton_worker_mode_write_copy_tick, + .stop = ibutton_worker_mode_write_common_stop, }, { .quant = 1000, @@ -62,143 +73,18 @@ void ibutton_worker_mode_idle_stop(iButtonWorker* worker) { /*********************** READ ***********************/ -typedef struct { - uint32_t last_dwt_value; - FuriStreamBuffer* stream; -} iButtonReadContext; - -void ibutton_worker_comparator_callback(bool level, void* context) { - iButtonReadContext* read_context = context; - - uint32_t current_dwt_value = DWT->CYCCNT; - - LevelDuration data = - level_duration_make(level, current_dwt_value - read_context->last_dwt_value); - furi_stream_buffer_send(read_context->stream, &data, sizeof(LevelDuration), 0); - - read_context->last_dwt_value = current_dwt_value; -} - -bool ibutton_worker_read_comparator(iButtonWorker* worker) { - bool result = false; - - protocol_dict_decoders_start(worker->protocols); - - furi_hal_rfid_pins_reset(); - // pulldown pull pin, we sense the signal through the analog part of the RFID schematic - furi_hal_rfid_pin_pull_pulldown(); - - iButtonReadContext read_context = { - .last_dwt_value = DWT->CYCCNT, - .stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 512, 1), - }; - - furi_hal_rfid_comp_set_callback(ibutton_worker_comparator_callback, &read_context); - furi_hal_rfid_comp_start(); - - uint32_t tick_start = furi_get_tick(); - while(true) { - LevelDuration level; - size_t ret = - furi_stream_buffer_receive(read_context.stream, &level, sizeof(LevelDuration), 100); - - if((furi_get_tick() - tick_start) > 100) { - break; - } - - if(ret > 0) { - ProtocolId decoded_index = protocol_dict_decoders_feed( - worker->protocols, - level_duration_get_level(level), - level_duration_get_duration(level)); - - if(decoded_index == PROTOCOL_NO) continue; - - protocol_dict_get_data( - worker->protocols, decoded_index, worker->key_data, ibutton_key_get_max_size()); - - switch(decoded_index) { - case iButtonProtocolCyfral: - furi_check(worker->key_p != NULL); - ibutton_key_set_type(worker->key_p, iButtonKeyCyfral); - ibutton_key_set_data(worker->key_p, worker->key_data, ibutton_key_get_max_size()); - result = true; - break; - case iButtonProtocolMetakom: - furi_check(worker->key_p != NULL); - ibutton_key_set_type(worker->key_p, iButtonKeyMetakom); - ibutton_key_set_data(worker->key_p, worker->key_data, ibutton_key_get_max_size()); - result = true; - break; - default: - break; - } - } - } - - furi_hal_rfid_comp_stop(); - furi_hal_rfid_comp_set_callback(NULL, NULL); - furi_hal_rfid_pins_reset(); - - furi_stream_buffer_free(read_context.stream); - - return result; -} - -bool ibutton_worker_read_dallas(iButtonWorker* worker) { - bool result = false; - onewire_host_start(worker->host); - furi_delay_ms(100); - FURI_CRITICAL_ENTER(); - if(onewire_host_search(worker->host, worker->key_data, NORMAL_SEARCH)) { - onewire_host_reset_search(worker->host); - - // key found, verify - if(onewire_host_reset(worker->host)) { - onewire_host_write(worker->host, DS1990_CMD_READ_ROM); - bool key_valid = true; - for(uint8_t i = 0; i < ibutton_key_get_max_size(); i++) { - if(onewire_host_read(worker->host) != worker->key_data[i]) { - key_valid = false; - break; - } - } - - if(key_valid) { - result = true; - - furi_check(worker->key_p != NULL); - ibutton_key_set_type(worker->key_p, iButtonKeyDS1990); - ibutton_key_set_data(worker->key_p, worker->key_data, ibutton_key_get_max_size()); - } - } - } else { - onewire_host_reset_search(worker->host); - } - onewire_host_stop(worker->host); - FURI_CRITICAL_EXIT(); - return result; -} - void ibutton_worker_mode_read_start(iButtonWorker* worker) { UNUSED(worker); furi_hal_power_enable_otg(); } void ibutton_worker_mode_read_tick(iButtonWorker* worker) { - bool valid = false; - if(ibutton_worker_read_dallas(worker)) { - valid = true; - } else if(ibutton_worker_read_comparator(worker)) { - valid = true; - } - - if(valid) { + if(ibutton_protocols_read(worker->protocols, worker->key)) { if(worker->read_cb != NULL) { worker->read_cb(worker->cb_ctx); } - ibutton_worker_switch_mode(worker, iButtonWorkerIdle); + ibutton_worker_switch_mode(worker, iButtonWorkerModeIdle); } } @@ -208,83 +94,14 @@ void ibutton_worker_mode_read_stop(iButtonWorker* worker) { } /*********************** EMULATE ***********************/ -static void onewire_slave_callback(void* context) { - furi_assert(context); - iButtonWorker* worker = context; - ibutton_worker_notify_emulate(worker); -} - -void ibutton_worker_emulate_dallas_start(iButtonWorker* worker) { - uint8_t* device_id = onewire_device_get_id_p(worker->device); - const uint8_t* key_id = ibutton_key_get_data_p(worker->key_p); - const uint8_t key_size = ibutton_key_get_max_size(); - memcpy(device_id, key_id, key_size); - - onewire_slave_attach(worker->slave, worker->device); - onewire_slave_set_result_callback(worker->slave, onewire_slave_callback, worker); - onewire_slave_start(worker->slave); -} - -void ibutton_worker_emulate_dallas_stop(iButtonWorker* worker) { - onewire_slave_stop(worker->slave); - onewire_slave_detach(worker->slave); -} - -void ibutton_worker_emulate_timer_cb(void* context) { - furi_assert(context); - iButtonWorker* worker = context; - - const LevelDuration level_duration = - protocol_dict_encoder_yield(worker->protocols, worker->protocol_to_encode); - - furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level_duration)); - furi_hal_ibutton_pin_write(level_duration_get_level(level_duration)); -} - -void ibutton_worker_emulate_timer_start(iButtonWorker* worker) { - furi_assert(worker->key_p); - const uint8_t* key_id = ibutton_key_get_data_p(worker->key_p); - const uint8_t key_size = ibutton_key_get_max_size(); - - switch(ibutton_key_get_type(worker->key_p)) { - case iButtonKeyDS1990: - return; - break; - case iButtonKeyCyfral: - worker->protocol_to_encode = iButtonProtocolCyfral; - break; - case iButtonKeyMetakom: - worker->protocol_to_encode = iButtonProtocolMetakom; - break; - } - - protocol_dict_set_data(worker->protocols, worker->protocol_to_encode, key_id, key_size); - protocol_dict_encoder_start(worker->protocols, worker->protocol_to_encode); - - furi_hal_ibutton_pin_configure(); - furi_hal_ibutton_emulate_start(0, ibutton_worker_emulate_timer_cb, worker); -} - -void ibutton_worker_emulate_timer_stop(iButtonWorker* worker) { - UNUSED(worker); - furi_hal_ibutton_emulate_stop(); -} void ibutton_worker_mode_emulate_start(iButtonWorker* worker) { - furi_assert(worker->key_p); + furi_assert(worker->key); furi_hal_rfid_pins_reset(); furi_hal_rfid_pin_pull_pulldown(); - switch(ibutton_key_get_type(worker->key_p)) { - case iButtonKeyDS1990: - ibutton_worker_emulate_dallas_start(worker); - break; - case iButtonKeyCyfral: - case iButtonKeyMetakom: - ibutton_worker_emulate_timer_start(worker); - break; - } + ibutton_protocols_emulate_start(worker->protocols, worker->key); } void ibutton_worker_mode_emulate_tick(iButtonWorker* worker) { @@ -292,56 +109,45 @@ void ibutton_worker_mode_emulate_tick(iButtonWorker* worker) { } void ibutton_worker_mode_emulate_stop(iButtonWorker* worker) { - furi_assert(worker->key_p); + furi_assert(worker->key); + + ibutton_protocols_emulate_stop(worker->protocols, worker->key); furi_hal_rfid_pins_reset(); - - switch(ibutton_key_get_type(worker->key_p)) { - case iButtonKeyDS1990: - ibutton_worker_emulate_dallas_stop(worker); - break; - case iButtonKeyCyfral: - case iButtonKeyMetakom: - ibutton_worker_emulate_timer_stop(worker); - break; - } } /*********************** WRITE ***********************/ -void ibutton_worker_mode_write_start(iButtonWorker* worker) { +void ibutton_worker_mode_write_common_start(iButtonWorker* worker) { //-V524 + UNUSED(worker); furi_hal_power_enable_otg(); - onewire_host_start(worker->host); } -void ibutton_worker_mode_write_tick(iButtonWorker* worker) { - furi_check(worker->key_p != NULL); - iButtonWriterResult writer_result = ibutton_writer_write(worker->writer, worker->key_p); - iButtonWorkerWriteResult result; - switch(writer_result) { - case iButtonWriterOK: - result = iButtonWorkerWriteOK; - break; - case iButtonWriterSameKey: - result = iButtonWorkerWriteSameKey; - break; - case iButtonWriterNoDetect: - result = iButtonWorkerWriteNoDetect; - break; - case iButtonWriterCannotWrite: - result = iButtonWorkerWriteCannotWrite; - break; - default: - result = iButtonWorkerWriteNoDetect; - break; - } +void ibutton_worker_mode_write_blank_tick(iButtonWorker* worker) { + furi_assert(worker->key); + const bool success = ibutton_protocols_write_blank(worker->protocols, worker->key); + // TODO: pass a proper result to the callback + const iButtonWorkerWriteResult result = success ? iButtonWorkerWriteOK : + iButtonWorkerWriteNoDetect; if(worker->write_cb != NULL) { worker->write_cb(worker->cb_ctx, result); } } -void ibutton_worker_mode_write_stop(iButtonWorker* worker) { - furi_hal_power_disable_otg(); - onewire_host_stop(worker->host); +void ibutton_worker_mode_write_copy_tick(iButtonWorker* worker) { + furi_assert(worker->key); + + const bool success = ibutton_protocols_write_copy(worker->protocols, worker->key); + // TODO: pass a proper result to the callback + const iButtonWorkerWriteResult result = success ? iButtonWorkerWriteOK : + iButtonWorkerWriteNoDetect; + if(worker->write_cb != NULL) { + worker->write_cb(worker->cb_ctx, result); + } +} + +void ibutton_worker_mode_write_common_stop(iButtonWorker* worker) { //-V524 + UNUSED(worker); + furi_hal_power_disable_otg(); } diff --git a/lib/one_wire/ibutton/ibutton_writer.c b/lib/one_wire/ibutton/ibutton_writer.c deleted file mode 100644 index 84d122491..000000000 --- a/lib/one_wire/ibutton/ibutton_writer.c +++ /dev/null @@ -1,298 +0,0 @@ -#include -#include -#include "ibutton_writer.h" -#include "ibutton_key_command.h" - -/*********************** PRIVATE ***********************/ - -struct iButtonWriter { - OneWireHost* host; -}; - -static void writer_write_one_bit(iButtonWriter* writer, bool value, uint32_t delay) { - onewire_host_write_bit(writer->host, value); - furi_delay_us(delay); -} - -static void writer_write_byte_ds1990(iButtonWriter* writer, uint8_t data) { - for(uint8_t n_bit = 0; n_bit < 8; n_bit++) { - onewire_host_write_bit(writer->host, data & 1); - furi_delay_us(5000); - data = data >> 1; - } -} - -static bool writer_compare_key_ds1990(iButtonWriter* writer, iButtonKey* key) { - bool result = false; - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - FURI_CRITICAL_ENTER(); - bool presence = onewire_host_reset(writer->host); - - if(presence) { - onewire_host_write(writer->host, DS1990_CMD_READ_ROM); - - result = true; - for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) { - if(ibutton_key_get_data_p(key)[i] != onewire_host_read(writer->host)) { - result = false; - break; - } - } - } - - FURI_CRITICAL_EXIT(); - } - - return result; -} - -static bool writer_write_TM2004(iButtonWriter* writer, iButtonKey* key) { - uint8_t answer; - bool result = true; - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - FURI_CRITICAL_ENTER(); - - // write rom, addr is 0x0000 - onewire_host_reset(writer->host); - onewire_host_write(writer->host, TM2004_CMD_WRITE_ROM); - onewire_host_write(writer->host, 0x00); - onewire_host_write(writer->host, 0x00); - - // write key - for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) { - // write key byte - onewire_host_write(writer->host, ibutton_key_get_data_p(key)[i]); - answer = onewire_host_read(writer->host); - // TODO: check answer CRC - - // pulse indicating that data is correct - furi_delay_us(600); - writer_write_one_bit(writer, 1, 50000); - - // read written key byte - answer = onewire_host_read(writer->host); //-V519 - - // check that written and read are same - if(ibutton_key_get_data_p(key)[i] != answer) { - result = false; - break; - } - } - - if(!writer_compare_key_ds1990(writer, key)) { - result = false; - } - - onewire_host_reset(writer->host); - - FURI_CRITICAL_EXIT(); - } else { - result = false; - } - - return result; -} - -static bool writer_write_1990_1(iButtonWriter* writer, iButtonKey* key) { - bool result = false; - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - FURI_CRITICAL_ENTER(); - - // unlock - onewire_host_reset(writer->host); - onewire_host_write(writer->host, RW1990_1_CMD_WRITE_RECORD_FLAG); - furi_delay_us(10); - writer_write_one_bit(writer, 0, 5000); - - // write key - onewire_host_reset(writer->host); - onewire_host_write(writer->host, RW1990_1_CMD_WRITE_ROM); - for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) { - // inverted key for RW1990.1 - writer_write_byte_ds1990(writer, ~ibutton_key_get_data_p(key)[i]); - furi_delay_us(30000); - } - - // lock - onewire_host_write(writer->host, RW1990_1_CMD_WRITE_RECORD_FLAG); - writer_write_one_bit(writer, 1, 10000); - - FURI_CRITICAL_EXIT(); - - if(writer_compare_key_ds1990(writer, key)) { - result = true; - } - } - - return result; -} - -static bool writer_write_1990_2(iButtonWriter* writer, iButtonKey* key) { - bool result = false; - - if(ibutton_key_get_type(key) == iButtonKeyDS1990) { - FURI_CRITICAL_ENTER(); - - // unlock - onewire_host_reset(writer->host); - onewire_host_write(writer->host, RW1990_2_CMD_WRITE_RECORD_FLAG); - furi_delay_us(10); - writer_write_one_bit(writer, 1, 5000); - - // write key - onewire_host_reset(writer->host); - onewire_host_write(writer->host, RW1990_2_CMD_WRITE_ROM); - for(uint8_t i = 0; i < ibutton_key_get_data_size(key); i++) { - writer_write_byte_ds1990(writer, ibutton_key_get_data_p(key)[i]); - furi_delay_us(30000); - } - - // lock - onewire_host_write(writer->host, RW1990_2_CMD_WRITE_RECORD_FLAG); - writer_write_one_bit(writer, 0, 10000); - - FURI_CRITICAL_EXIT(); - - if(writer_compare_key_ds1990(writer, key)) { - result = true; - } - } - - return result; -} - -/* -// TODO: adapt and test -static bool writer_write_TM01( - iButtonWriter* writer, - iButtonKey type, - const uint8_t* key, - uint8_t key_length) { - bool result = true; - - { - // TODO test and encoding - FURI_CRITICAL_ENTER(); - - // unlock - onewire_host_reset(writer->host); - onewire_host_write(writer->host, TM01::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(1, 10000); - - // write key - onewire_host_reset(writer->host); - onewire_host_write(writer->host, TM01::CMD_WRITE_ROM); - - // TODO: key types - //if(type == KEY_METAKOM || type == KEY_CYFRAL) { - //} else { - for(uint8_t i = 0; i < key->get_type_data_size(); i++) { - write_byte_ds1990(key->get_data()[i]); - furi_delay_us(10000); - } - //} - - // lock - onewire_host_write(writer->host, TM01::CMD_WRITE_RECORD_FLAG); - onewire_write_one_bit(0, 10000); - - FURI_CRITICAL_EXIT(); - } - - if(!compare_key_ds1990(key)) { - result = false; - } - - { - FURI_CRITICAL_ENTER(); - - if(key->get_key_type() == iButtonKeyType::KeyMetakom || - key->get_key_type() == iButtonKeyType::KeyCyfral) { - onewire_host_reset(writer->host); - if(key->get_key_type() == iButtonKeyType::KeyCyfral) - onewire_host_write(writer->host, TM01::CMD_SWITCH_TO_CYFRAL); - else - onewire_host_write(writer->host, TM01::CMD_SWITCH_TO_METAKOM); - onewire_write_one_bit(1); - } - - FURI_CRITICAL_EXIT(); - } - - return result; -} -*/ - -static iButtonWriterResult writer_write_DS1990(iButtonWriter* writer, iButtonKey* key) { - iButtonWriterResult result = iButtonWriterNoDetect; - bool same_key = writer_compare_key_ds1990(writer, key); - - if(!same_key) { - // currently we can write: - // RW1990_1, TM08v2, TM08vi-2 by write_1990_1() - // RW1990_2 by write_1990_2() - // RW2004, RW2004, TM2004 with EEPROM by write_TM2004(); - - bool write_result = true; - do { - if(writer_write_1990_1(writer, key)) break; - if(writer_write_1990_2(writer, key)) break; - if(writer_write_TM2004(writer, key)) break; - write_result = false; - } while(false); - - if(write_result) { - result = iButtonWriterOK; - } else { - result = iButtonWriterCannotWrite; - } - } else { - result = iButtonWriterSameKey; - } - - return result; -} - -/*********************** PUBLIC ***********************/ - -iButtonWriter* ibutton_writer_alloc(OneWireHost* host) { - iButtonWriter* writer = malloc(sizeof(iButtonWriter)); - writer->host = host; - return writer; -} - -void ibutton_writer_free(iButtonWriter* writer) { - free(writer); -} - -iButtonWriterResult ibutton_writer_write(iButtonWriter* writer, iButtonKey* key) { - iButtonWriterResult result = iButtonWriterNoDetect; - - furi_kernel_lock(); - bool blank_present = onewire_host_reset(writer->host); - furi_kernel_unlock(); - - if(blank_present) { - switch(ibutton_key_get_type(key)) { - case iButtonKeyDS1990: - result = writer_write_DS1990(writer, key); - default: - break; - } - } - - return result; -} - -void ibutton_writer_start(iButtonWriter* writer) { - furi_hal_power_enable_otg(); - onewire_host_start(writer->host); -} - -void ibutton_writer_stop(iButtonWriter* writer) { - onewire_host_stop(writer->host); - furi_hal_power_disable_otg(); -} diff --git a/lib/one_wire/ibutton/ibutton_writer.h b/lib/one_wire/ibutton/ibutton_writer.h deleted file mode 100644 index 6dbdbb27a..000000000 --- a/lib/one_wire/ibutton/ibutton_writer.h +++ /dev/null @@ -1,60 +0,0 @@ -/** - * @file ibutton_writer.h - * - * iButton blanks writer - */ - -#pragma once -#include -#include "ibutton_key.h" -#include "../one_wire_host.h" - -#ifdef __cplusplus -extern "C" { -#endif - -typedef enum { - iButtonWriterOK, - iButtonWriterSameKey, - iButtonWriterNoDetect, - iButtonWriterCannotWrite, -} iButtonWriterResult; - -typedef struct iButtonWriter iButtonWriter; - -/** - * Allocate writer - * @param host - * @return iButtonWriter* - */ -iButtonWriter* ibutton_writer_alloc(OneWireHost* host); - -/** - * Deallocate writer - * @param writer - */ -void ibutton_writer_free(iButtonWriter* writer); - -/** - * Write key to blank - * @param writer - * @param key - * @return iButtonWriterResult - */ -iButtonWriterResult ibutton_writer_write(iButtonWriter* writer, iButtonKey* key); - -/** - * Start writing. Must be called before write attempt - * @param writer - */ -void ibutton_writer_start(iButtonWriter* writer); - -/** - * Stop writing - * @param writer - */ -void ibutton_writer_stop(iButtonWriter* writer); - -#ifdef __cplusplus -} -#endif diff --git a/lib/one_wire/ibutton/protocols/blanks/rw1990.c b/lib/one_wire/ibutton/protocols/blanks/rw1990.c new file mode 100644 index 000000000..d3350fcf0 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/blanks/rw1990.c @@ -0,0 +1,95 @@ +#include "rw1990.h" + +#include + +#define RW1990_1_CMD_WRITE_RECORD_FLAG 0xD1 +#define RW1990_1_CMD_READ_RECORD_FLAG 0xB5 +#define RW1990_1_CMD_WRITE_ROM 0xD5 + +#define RW1990_2_CMD_WRITE_RECORD_FLAG 0x1D +#define RW1990_2_CMD_READ_RECORD_FLAG 0x1E +#define RW1990_2_CMD_WRITE_ROM 0xD5 + +#define DS1990_CMD_READ_ROM 0x33 + +static void rw1990_write_byte(OneWireHost* host, uint8_t value) { + for(uint8_t bitMask = 0x01; bitMask; bitMask <<= 1) { + onewire_host_write_bit(host, (bool)(bitMask & value)); + furi_delay_us(5000); + } +} + +static bool rw1990_read_and_compare(OneWireHost* host, const uint8_t* data, size_t data_size) { + bool success = false; + + if(onewire_host_reset(host)) { + success = true; + onewire_host_write(host, DS1990_CMD_READ_ROM); + + for(size_t i = 0; i < data_size; ++i) { + if(data[i] != onewire_host_read(host)) { + success = false; + break; + } + } + } + + return success; +} + +bool rw1990_write_v1(OneWireHost* host, const uint8_t* data, size_t data_size) { + // Unlock sequence + onewire_host_reset(host); + onewire_host_write(host, RW1990_1_CMD_WRITE_RECORD_FLAG); + furi_delay_us(10); + + onewire_host_write_bit(host, false); + furi_delay_us(5000); + + // Write data + onewire_host_reset(host); + onewire_host_write(host, RW1990_1_CMD_WRITE_ROM); + + for(size_t i = 0; i < data_size; ++i) { + // inverted key for RW1990.1 + rw1990_write_byte(host, ~(data[i])); + furi_delay_us(30000); + } + + // Lock sequence + onewire_host_write(host, RW1990_1_CMD_WRITE_RECORD_FLAG); + + onewire_host_write_bit(host, true); + furi_delay_us(10000); + + // TODO: Better error handling + return rw1990_read_and_compare(host, data, data_size); +} + +bool rw1990_write_v2(OneWireHost* host, const uint8_t* data, size_t data_size) { + // Unlock sequence + onewire_host_reset(host); + onewire_host_write(host, RW1990_2_CMD_WRITE_RECORD_FLAG); + furi_delay_us(10); + + onewire_host_write_bit(host, true); + furi_delay_us(5000); + + // Write data + onewire_host_reset(host); + onewire_host_write(host, RW1990_2_CMD_WRITE_ROM); + + for(size_t i = 0; i < data_size; ++i) { + rw1990_write_byte(host, data[i]); + furi_delay_us(30000); + } + + // Lock sequence + onewire_host_write(host, RW1990_2_CMD_WRITE_RECORD_FLAG); + + onewire_host_write_bit(host, false); + furi_delay_us(10000); + + // TODO: Better error handling + return rw1990_read_and_compare(host, data, data_size); +} diff --git a/lib/one_wire/ibutton/protocols/blanks/rw1990.h b/lib/one_wire/ibutton/protocols/blanks/rw1990.h new file mode 100644 index 000000000..bdd27f6bf --- /dev/null +++ b/lib/one_wire/ibutton/protocols/blanks/rw1990.h @@ -0,0 +1,9 @@ +#pragma once + +#include + +#include + +bool rw1990_write_v1(OneWireHost* host, const uint8_t* data, size_t data_size); + +bool rw1990_write_v2(OneWireHost* host, const uint8_t* data, size_t data_size); diff --git a/lib/one_wire/ibutton/protocols/blanks/tm2004.c b/lib/one_wire/ibutton/protocols/blanks/tm2004.c new file mode 100644 index 000000000..ef6f0619e --- /dev/null +++ b/lib/one_wire/ibutton/protocols/blanks/tm2004.c @@ -0,0 +1,42 @@ +#include "tm2004.h" + +#include + +#define TM2004_CMD_READ_STATUS 0xAA +#define TM2004_CMD_READ_MEMORY 0xF0 +#define TM2004_CMD_WRITE_ROM 0x3C +#define TM2004_CMD_FINALIZATION 0x35 +#define TM2004_ANSWER_READ_MEMORY 0xF5 + +bool tm2004_write(OneWireHost* host, const uint8_t* data, size_t data_size) { + onewire_host_reset(host); + onewire_host_write(host, TM2004_CMD_WRITE_ROM); + // Starting writing from address 0x0000 + onewire_host_write(host, 0x00); + onewire_host_write(host, 0x00); + + size_t i; + for(i = 0; i < data_size; ++i) { + uint8_t answer; + + onewire_host_write(host, data[i]); + answer = onewire_host_read(host); + // TODO: check answer CRC + + // pulse indicating that data is correct + furi_delay_us(600); + onewire_host_write_bit(host, true); + furi_delay_us(50000); + + // read written key byte + answer = onewire_host_read(host); //-V519 + + // check that written and read are same + if(data[i] != answer) { + break; + } + } + + // TODO: Better error handling + return i == data_size; +} diff --git a/lib/one_wire/ibutton/protocols/blanks/tm2004.h b/lib/one_wire/ibutton/protocols/blanks/tm2004.h new file mode 100644 index 000000000..15713af56 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/blanks/tm2004.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +#include + +bool tm2004_write(OneWireHost* host, const uint8_t* data, size_t data_size); diff --git a/lib/one_wire/ibutton/protocols/dallas/dallas_common.c b/lib/one_wire/ibutton/protocols/dallas/dallas_common.c new file mode 100644 index 000000000..57a873b1d --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/dallas_common.c @@ -0,0 +1,250 @@ +#include "dallas_common.h" + +#include +#include + +#define BITS_IN_BYTE 8U + +#define DALLAS_COMMON_ROM_DATA_KEY_V1 "Data" +#define DALLAS_COMMON_ROM_DATA_KEY_V2 "Rom Data" + +#define DALLAS_COMMON_COPY_SCRATCH_MIN_TIMEOUT_US 5U +#define DALLAS_COMMON_COPY_SCRATCH_POLL_COUNT 20U + +#define DALLAS_COMMON_END_ADDRESS_MASK 0x01F +#define DALLAS_COMMON_STATUS_FLAG_PF (1U << 5) +#define DALLAS_COMMON_STATUS_FLAG_OF (1U << 6) +#define DALLAS_COMMON_STATUS_FLAG_AA (1U << 7) + +#define DALLAS_COMMON_BRIEF_HEAD_COUNT 4U +#define DALLAS_COMMON_BRIEF_TAIL_COUNT 3U + +#define BITS_IN_BYTE 8U +#define BITS_IN_KBIT 1024U + +bool dallas_common_skip_rom(OneWireHost* host) { + onewire_host_write(host, DALLAS_COMMON_CMD_SKIP_ROM); + return true; +} + +bool dallas_common_read_rom(OneWireHost* host, DallasCommonRomData* rom_data) { + onewire_host_write(host, DALLAS_COMMON_CMD_READ_ROM); + onewire_host_read_bytes(host, rom_data->bytes, sizeof(DallasCommonRomData)); + + return dallas_common_is_valid_crc(rom_data); +} + +bool dallas_common_write_scratchpad( + OneWireHost* host, + uint16_t address, + const uint8_t* data, + size_t data_size) { + onewire_host_write(host, DALLAS_COMMON_CMD_WRITE_SCRATCH); + onewire_host_write(host, (uint8_t)address); + onewire_host_write(host, (uint8_t)(address >> BITS_IN_BYTE)); + + onewire_host_write_bytes(host, data, data_size); + + return true; +} + +bool dallas_common_read_scratchpad( + OneWireHost* host, + DallasCommonAddressRegs* regs, + uint8_t* data, + size_t data_size) { + onewire_host_write(host, DALLAS_COMMON_CMD_READ_SCRATCH); + onewire_host_read_bytes(host, regs->bytes, sizeof(DallasCommonAddressRegs)); + onewire_host_read_bytes(host, data, data_size); + + return true; +} + +bool dallas_common_copy_scratchpad( + OneWireHost* host, + const DallasCommonAddressRegs* regs, + uint32_t timeout_us) { + onewire_host_write(host, DALLAS_COMMON_CMD_COPY_SCRATCH); + onewire_host_write_bytes(host, regs->bytes, sizeof(DallasCommonAddressRegs)); + + const uint32_t poll_delay = + MAX(timeout_us / DALLAS_COMMON_COPY_SCRATCH_POLL_COUNT, + DALLAS_COMMON_COPY_SCRATCH_MIN_TIMEOUT_US); + + uint32_t time_elapsed; + for(time_elapsed = 0; time_elapsed < timeout_us; time_elapsed += poll_delay) { + if(!onewire_host_read_bit(host)) break; + furi_delay_us(poll_delay); + } + + return time_elapsed < timeout_us; +} + +bool dallas_common_read_mem(OneWireHost* host, uint16_t address, uint8_t* data, size_t data_size) { + onewire_host_write(host, DALLAS_COMMON_CMD_READ_MEM); + + onewire_host_write(host, (uint8_t)address); + onewire_host_write(host, (uint8_t)(address > BITS_IN_BYTE)); + + onewire_host_read_bytes(host, data, (uint16_t)data_size); + + return true; +} + +bool dallas_common_write_mem( + OneWireHost* host, + uint32_t timeout_us, + size_t page_size, + const uint8_t* data, + size_t data_size) { + // Data size must be a multiple of page size + furi_check(data_size % page_size == 0); + + DallasCommonAddressRegs regs; + uint8_t* scratch = malloc(page_size); + + size_t i; + for(i = 0; i < data_size; i += page_size) { + const uint8_t* data_ptr = data + i; + + // Write scratchpad with the next page value + if(!onewire_host_reset(host)) break; + if(!dallas_common_skip_rom(host)) break; + if(!dallas_common_write_scratchpad(host, i, data_ptr, page_size)) break; + + // Read back the scratchpad contents and address registers + if(!onewire_host_reset(host)) break; + if(!dallas_common_skip_rom(host)) break; + if(!dallas_common_read_scratchpad(host, ®s, scratch, page_size)) break; + + // Verify scratchpad contents + if(memcmp(data_ptr, scratch, page_size) != 0) break; + + // Write scratchpad to internal memory + if(!onewire_host_reset(host)) break; + if(!dallas_common_skip_rom(host)) break; + if(!dallas_common_copy_scratchpad(host, ®s, timeout_us)) break; + + // Read back the address registers again + if(!onewire_host_reset(host)) break; + if(!dallas_common_skip_rom(host)) break; + if(!dallas_common_read_scratchpad(host, ®s, scratch, 0)) break; + + // Check if AA flag is set + if(!(regs.fields.status & DALLAS_COMMON_STATUS_FLAG_AA)) break; + } + + free(scratch); + + return i == data_size; +} + +bool dallas_common_emulate_search_rom(OneWireSlave* bus, const DallasCommonRomData* rom_data) { + for(size_t i = 0; i < sizeof(DallasCommonRomData); i++) { + for(size_t j = 0; j < BITS_IN_BYTE; j++) { + bool bit = (rom_data->bytes[i] >> j) & 0x01; + + if(!onewire_slave_send_bit(bus, bit)) return false; + if(!onewire_slave_send_bit(bus, !bit)) return false; + + onewire_slave_receive_bit(bus); + // TODO: check for errors and return if any + } + } + + return true; +} + +bool dallas_common_emulate_read_rom(OneWireSlave* bus, const DallasCommonRomData* rom_data) { + return onewire_slave_send(bus, rom_data->bytes, sizeof(DallasCommonRomData)); +} + +bool dallas_common_emulate_read_mem(OneWireSlave* bus, const uint8_t* data, size_t data_size) { + bool success = false; + + union { + uint8_t bytes[sizeof(uint16_t)]; + uint16_t word; + } address; + + do { + if(!onewire_slave_receive(bus, address.bytes, sizeof(address))) break; + if(address.word >= data_size) break; + if(!onewire_slave_send(bus, data + address.word, data_size - address.word)) break; + + success = true; + } while(false); + + return success; +} + +bool dallas_common_save_rom_data(FlipperFormat* ff, const DallasCommonRomData* rom_data) { + return flipper_format_write_hex( + ff, DALLAS_COMMON_ROM_DATA_KEY_V2, rom_data->bytes, sizeof(DallasCommonRomData)); +} + +bool dallas_common_load_rom_data( + FlipperFormat* ff, + uint32_t format_version, + DallasCommonRomData* rom_data) { + switch(format_version) { + case 1: + return flipper_format_read_hex( + ff, DALLAS_COMMON_ROM_DATA_KEY_V1, rom_data->bytes, sizeof(DallasCommonRomData)); + case 2: + return flipper_format_read_hex( + ff, DALLAS_COMMON_ROM_DATA_KEY_V2, rom_data->bytes, sizeof(DallasCommonRomData)); + default: + return false; + } +} + +bool dallas_common_is_valid_crc(const DallasCommonRomData* rom_data) { + const uint8_t crc_calculated = + maxim_crc8(rom_data->bytes, sizeof(DallasCommonRomData) - 1, MAXIM_CRC8_INIT); + const uint8_t crc_received = rom_data->fields.checksum; + + return crc_calculated == crc_received; +} + +void dallas_common_render_brief_data( + FuriString* result, + const DallasCommonRomData* rom_data, + const uint8_t* sram_data, + size_t sram_data_size) { + for(size_t i = 0; i < sizeof(rom_data->bytes); ++i) { + furi_string_cat_printf(result, "%02X ", rom_data->bytes[i]); + } + + furi_string_cat_printf( + result, + "\nInternal SRAM: %zu Kbit\n", + (size_t)(sram_data_size * BITS_IN_BYTE / BITS_IN_KBIT)); + + for(size_t i = 0; i < DALLAS_COMMON_BRIEF_HEAD_COUNT; ++i) { + furi_string_cat_printf(result, "%02X ", sram_data[i]); + } + + furi_string_cat_printf(result, "[ . . . ]"); + + for(size_t i = sram_data_size - DALLAS_COMMON_BRIEF_TAIL_COUNT; i < sram_data_size; ++i) { + furi_string_cat_printf(result, " %02X", sram_data[i]); + } +} + +void dallas_common_render_crc_error(FuriString* result, const DallasCommonRomData* rom_data) { + furi_string_set(result, "CRC Error\n"); + + const size_t data_size = sizeof(DallasCommonRomData); + + for(size_t i = 0; i < data_size; ++i) { + furi_string_cat_printf(result, (i < data_size - 1) ? "%02X " : "%02X", rom_data->bytes[i]); + } +} + +void dallas_common_apply_edits(DallasCommonRomData* rom_data, uint8_t family_code) { + rom_data->fields.family_code = family_code; + const uint8_t crc = + maxim_crc8(rom_data->bytes, sizeof(DallasCommonRomData) - 1, MAXIM_CRC8_INIT); + rom_data->fields.checksum = crc; +} diff --git a/lib/one_wire/ibutton/protocols/dallas/dallas_common.h b/lib/one_wire/ibutton/protocols/dallas/dallas_common.h new file mode 100644 index 000000000..7ad13eb2c --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/dallas_common.h @@ -0,0 +1,107 @@ +#pragma once + +#include + +#include +#include + +#define DALLAS_COMMON_MANUFACTURER_NAME "Dallas" + +#define DALLAS_COMMON_CMD_READ_ROM 0x33U +#define DALLAS_COMMON_CMD_MATCH_ROM 0x55U +#define DALLAS_COMMON_CMD_SKIP_ROM 0xCCU +#define DALLAS_COMMON_CMD_COND_SEARCH 0xECU +#define DALLAS_COMMON_CMD_SEARCH_ROM 0xF0U + +#define DALLAS_COMMON_CMD_READ_SCRATCH 0xAAU +#define DALLAS_COMMON_CMD_WRITE_SCRATCH 0x0FU +#define DALLAS_COMMON_CMD_COPY_SCRATCH 0x55U + +#define DALLAS_COMMON_CMD_READ_MEM 0xF0U + +#define DALLAS_COMMON_CMD_OVERDRIVE_SKIP_ROM 0x3CU +#define DALLAS_COMMON_CMD_OVERDRIVE_MATCH_ROM 0x69U + +typedef enum { + DallasCommonCommandStateIdle, + DallasCommonCommandStateRomCmd, + DallasCommonCommandStateMemCmd, +} DallasCommonCommandState; + +typedef union { + struct { + uint8_t family_code; + uint8_t serial_number[6]; + uint8_t checksum; + } fields; + uint8_t bytes[8]; +} DallasCommonRomData; + +typedef union { + struct { + uint8_t address_lo; + uint8_t address_hi; + uint8_t status; + } fields; + uint8_t bytes[3]; +} DallasCommonAddressRegs; + +/* Standard(ish) iButton commands */ +bool dallas_common_skip_rom(OneWireHost* host); + +bool dallas_common_read_rom(OneWireHost* host, DallasCommonRomData* rom_data); + +bool dallas_common_write_scratchpad( + OneWireHost* host, + uint16_t address, + const uint8_t* data, + size_t data_size); + +bool dallas_common_read_scratchpad( + OneWireHost* host, + DallasCommonAddressRegs* regs, + uint8_t* data, + size_t data_size); + +bool dallas_common_copy_scratchpad( + OneWireHost* host, + const DallasCommonAddressRegs* regs, + uint32_t timeout_us); + +bool dallas_common_read_mem(OneWireHost* host, uint16_t address, uint8_t* data, size_t data_size); + +/* Combined operations */ +bool dallas_common_write_mem( + OneWireHost* host, + uint32_t timeout_us, + size_t page_size, + const uint8_t* data, + size_t data_size); + +/* Emulation */ +bool dallas_common_emulate_search_rom(OneWireSlave* bus, const DallasCommonRomData* rom_data); + +bool dallas_common_emulate_read_rom(OneWireSlave* bus, const DallasCommonRomData* rom_data); + +bool dallas_common_emulate_read_mem(OneWireSlave* bus, const uint8_t* data, size_t data_size); + +/* Save & Load */ +bool dallas_common_save_rom_data(FlipperFormat* ff, const DallasCommonRomData* rom_data); + +bool dallas_common_load_rom_data( + FlipperFormat* ff, + uint32_t format_version, + DallasCommonRomData* rom_data); + +/* Miscellaneous */ +bool dallas_common_is_valid_crc(const DallasCommonRomData* rom_data); + +void dallas_common_render_brief_data( + FuriString* result, + const DallasCommonRomData* rom_data, + const uint8_t* sram_data, + size_t sram_data_size); + +void dallas_common_render_crc_error(FuriString* result, const DallasCommonRomData* rom_data); + +void dallas_common_apply_edits(DallasCommonRomData* rom_data, uint8_t family_code); diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_dallas_base.h b/lib/one_wire/ibutton/protocols/dallas/protocol_dallas_base.h new file mode 100644 index 000000000..b4edb2b20 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_dallas_base.h @@ -0,0 +1,39 @@ +#pragma once + +#include "../protocol_common_i.h" + +#include + +#include +#include + +typedef bool (*iButtonProtocolDallasReadWriteFunc)(OneWireHost*, iButtonProtocolData*); +typedef void (*iButtonProtocolDallasEmulateFunc)(OneWireSlave*, iButtonProtocolData*); +typedef bool (*iButtonProtocolDallasSaveFunc)(FlipperFormat*, const iButtonProtocolData*); +typedef bool (*iButtonProtocolDallasLoadFunc)(FlipperFormat*, uint32_t, iButtonProtocolData*); +typedef void (*iButtonProtocolDallasRenderDataFunc)(FuriString*, const iButtonProtocolData*); +typedef bool (*iButtonProtocolDallasIsValidFunc)(const iButtonProtocolData*); +typedef void ( + *iButtonProtocolDallasGetEditableDataFunc)(iButtonEditableData*, iButtonProtocolData*); +typedef void (*iButtonProtocolDallasApplyEditsFunc)(iButtonProtocolData*); + +typedef struct { + const uint8_t family_code; + const uint32_t features; + const size_t data_size; + const char* manufacturer; + const char* name; + + iButtonProtocolDallasReadWriteFunc read; + iButtonProtocolDallasReadWriteFunc write_blank; + iButtonProtocolDallasReadWriteFunc write_copy; + iButtonProtocolDallasEmulateFunc emulate; + iButtonProtocolDallasSaveFunc save; + iButtonProtocolDallasLoadFunc load; + iButtonProtocolDallasRenderDataFunc render_data; + iButtonProtocolDallasRenderDataFunc render_brief_data; + iButtonProtocolDallasRenderDataFunc render_error; + iButtonProtocolDallasIsValidFunc is_valid; + iButtonProtocolDallasGetEditableDataFunc get_editable_data; + iButtonProtocolDallasApplyEditsFunc apply_edits; +} iButtonProtocolDallasBase; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.c b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.c new file mode 100644 index 000000000..0d9c937ee --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.c @@ -0,0 +1,144 @@ +#include "protocol_ds1990.h" + +#include +#include + +#include "dallas_common.h" + +#include "../blanks/rw1990.h" +#include "../blanks/tm2004.h" + +#define DS1990_FAMILY_CODE 0x01U +#define DS1990_FAMILY_NAME "DS1990" + +#define DS1990_CMD_READ_ROM 0x0FU + +typedef struct { + OneWireSlave* bus; +} DS1990ProtocolState; + +typedef struct { + DallasCommonRomData rom_data; + DS1990ProtocolState state; +} DS1990ProtocolData; + +static bool dallas_ds1990_read(OneWireHost*, iButtonProtocolData*); +static bool dallas_ds1990_write_blank(OneWireHost*, iButtonProtocolData*); +static void dallas_ds1990_emulate(OneWireSlave*, iButtonProtocolData*); +static bool dallas_ds1990_load(FlipperFormat*, uint32_t, iButtonProtocolData*); +static bool dallas_ds1990_save(FlipperFormat*, const iButtonProtocolData*); +static void dallas_ds1990_render_brief_data(FuriString*, const iButtonProtocolData*); +static void dallas_ds1990_render_error(FuriString*, const iButtonProtocolData*); +static bool dallas_ds1990_is_data_valid(const iButtonProtocolData*); +static void dallas_ds1990_get_editable_data(iButtonEditableData*, iButtonProtocolData*); +static void dallas_ds1990_apply_edits(iButtonProtocolData*); + +const iButtonProtocolDallasBase ibutton_protocol_ds1990 = { + .family_code = DS1990_FAMILY_CODE, + .features = iButtonProtocolFeatureWriteBlank, + .data_size = sizeof(DS1990ProtocolData), + .manufacturer = DALLAS_COMMON_MANUFACTURER_NAME, + .name = DS1990_FAMILY_NAME, + + .read = dallas_ds1990_read, + .write_blank = dallas_ds1990_write_blank, + .write_copy = NULL, /* No data to write a copy */ + .emulate = dallas_ds1990_emulate, + .save = dallas_ds1990_save, + .load = dallas_ds1990_load, + .render_data = NULL, /* No data to render */ + .render_brief_data = dallas_ds1990_render_brief_data, + .render_error = dallas_ds1990_render_error, + .is_valid = dallas_ds1990_is_data_valid, + .get_editable_data = dallas_ds1990_get_editable_data, + .apply_edits = dallas_ds1990_apply_edits, +}; + +bool dallas_ds1990_read(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + return onewire_host_reset(host) && dallas_common_read_rom(host, &data->rom_data); +} + +bool dallas_ds1990_write_blank(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + + return rw1990_write_v1(host, data->rom_data.bytes, sizeof(DallasCommonRomData)) || + rw1990_write_v2(host, data->rom_data.bytes, sizeof(DallasCommonRomData)) || + tm2004_write(host, data->rom_data.bytes, sizeof(DallasCommonRomData)); +} + +static bool dallas_ds1990_command_callback(uint8_t command, void* context) { + furi_assert(context); + DS1990ProtocolData* data = context; + OneWireSlave* bus = data->state.bus; + + switch(command) { + case DALLAS_COMMON_CMD_SEARCH_ROM: + dallas_common_emulate_search_rom(bus, &data->rom_data); + break; + case DALLAS_COMMON_CMD_READ_ROM: + case DS1990_CMD_READ_ROM: + dallas_common_emulate_read_rom(bus, &data->rom_data); + break; + default: + break; + } + + // No support for multiple consecutive commands + return false; +} + +void dallas_ds1990_emulate(OneWireSlave* bus, iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + data->state.bus = bus; + + onewire_slave_set_reset_callback(bus, NULL, NULL); + onewire_slave_set_command_callback(bus, dallas_ds1990_command_callback, protocol_data); +} + +bool dallas_ds1990_save(FlipperFormat* ff, const iButtonProtocolData* protocol_data) { + const DS1990ProtocolData* data = protocol_data; + return dallas_common_save_rom_data(ff, &data->rom_data); +} + +bool dallas_ds1990_load( + FlipperFormat* ff, + uint32_t format_version, + iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + return dallas_common_load_rom_data(ff, format_version, &data->rom_data); +} + +void dallas_ds1990_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1990ProtocolData* data = protocol_data; + + for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) { + furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]); + } +} + +void dallas_ds1990_render_error(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1990ProtocolData* data = protocol_data; + + if(!dallas_common_is_valid_crc(&data->rom_data)) { + dallas_common_render_crc_error(result, &data->rom_data); + } +} + +bool dallas_ds1990_is_data_valid(const iButtonProtocolData* protocol_data) { + const DS1990ProtocolData* data = protocol_data; + return dallas_common_is_valid_crc(&data->rom_data); +} + +void dallas_ds1990_get_editable_data( + iButtonEditableData* editable_data, + iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + editable_data->ptr = data->rom_data.bytes; + editable_data->size = sizeof(DallasCommonRomData); +} + +void dallas_ds1990_apply_edits(iButtonProtocolData* protocol_data) { + DS1990ProtocolData* data = protocol_data; + dallas_common_apply_edits(&data->rom_data, DS1990_FAMILY_CODE); +} diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.h b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.h new file mode 100644 index 000000000..de3da0e4c --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1990.h @@ -0,0 +1,5 @@ +#pragma once + +#include "protocol_dallas_base.h" + +extern const iButtonProtocolDallasBase ibutton_protocol_ds1990; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.c b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.c new file mode 100644 index 000000000..131bc634a --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.c @@ -0,0 +1,218 @@ +#include "protocol_ds1992.h" + +#include +#include + +#include "dallas_common.h" + +#include "../blanks/tm2004.h" + +#define DS1992_FAMILY_CODE 0x08U +#define DS1992_FAMILY_NAME "DS1992" + +#define DS1992_SRAM_DATA_SIZE 128U +#define DS1992_SRAM_PAGE_SIZE 4U +#define DS1992_COPY_SCRATCH_TIMEOUT_US 100U + +#define DS1992_DATA_BYTE_COUNT 4U + +#define DS1992_SRAM_DATA_KEY "Sram Data" + +typedef struct { + OneWireSlave* bus; + DallasCommonCommandState command_state; +} DS1992ProtocolState; + +typedef struct { + DallasCommonRomData rom_data; + uint8_t sram_data[DS1992_SRAM_DATA_SIZE]; + DS1992ProtocolState state; +} DS1992ProtocolData; + +static bool dallas_ds1992_read(OneWireHost*, void*); +static bool dallas_ds1992_write_blank(OneWireHost*, iButtonProtocolData*); +static bool dallas_ds1992_write_copy(OneWireHost*, iButtonProtocolData*); +static void dallas_ds1992_emulate(OneWireSlave*, iButtonProtocolData*); +static bool dallas_ds1992_load(FlipperFormat*, uint32_t, iButtonProtocolData*); +static bool dallas_ds1992_save(FlipperFormat*, const iButtonProtocolData*); +static void dallas_ds1992_render_data(FuriString*, const iButtonProtocolData*); +static void dallas_ds1992_render_brief_data(FuriString*, const iButtonProtocolData*); +static void dallas_ds1992_render_error(FuriString*, const iButtonProtocolData*); +static bool dallas_ds1992_is_data_valid(const iButtonProtocolData*); +static void dallas_ds1992_get_editable_data(iButtonEditableData*, iButtonProtocolData*); +static void dallas_ds1992_apply_edits(iButtonProtocolData*); + +const iButtonProtocolDallasBase ibutton_protocol_ds1992 = { + .family_code = DS1992_FAMILY_CODE, + .features = iButtonProtocolFeatureExtData | iButtonProtocolFeatureWriteBlank | + iButtonProtocolFeatureWriteCopy, + .data_size = sizeof(DS1992ProtocolData), + .manufacturer = DALLAS_COMMON_MANUFACTURER_NAME, + .name = DS1992_FAMILY_NAME, + + .read = dallas_ds1992_read, + .write_blank = dallas_ds1992_write_blank, + .write_copy = dallas_ds1992_write_copy, + .emulate = dallas_ds1992_emulate, + .save = dallas_ds1992_save, + .load = dallas_ds1992_load, + .render_data = dallas_ds1992_render_data, + .render_brief_data = dallas_ds1992_render_brief_data, + .render_error = dallas_ds1992_render_error, + .is_valid = dallas_ds1992_is_data_valid, + .get_editable_data = dallas_ds1992_get_editable_data, + .apply_edits = dallas_ds1992_apply_edits, +}; + +bool dallas_ds1992_read(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + return onewire_host_reset(host) && dallas_common_read_rom(host, &data->rom_data) && + dallas_common_read_mem(host, 0, data->sram_data, DS1992_SRAM_DATA_SIZE); +} + +bool dallas_ds1992_write_blank(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + // TODO: Make this work, currently broken + return tm2004_write(host, (uint8_t*)data, sizeof(DallasCommonRomData) + DS1992_SRAM_DATA_SIZE); +} + +bool dallas_ds1992_write_copy(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + return dallas_common_write_mem( + host, + DS1992_COPY_SCRATCH_TIMEOUT_US, + DS1992_SRAM_PAGE_SIZE, + data->sram_data, + DS1992_SRAM_DATA_SIZE); +} + +static void dallas_ds1992_reset_callback(void* context) { + furi_assert(context); + DS1992ProtocolData* data = context; + data->state.command_state = DallasCommonCommandStateIdle; +} + +static bool dallas_ds1992_command_callback(uint8_t command, void* context) { + furi_assert(context); + DS1992ProtocolData* data = context; + OneWireSlave* bus = data->state.bus; + + switch(command) { + case DALLAS_COMMON_CMD_SEARCH_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return dallas_common_emulate_search_rom(bus, &data->rom_data); + + } else if(data->state.command_state == DallasCommonCommandStateRomCmd) { + data->state.command_state = DallasCommonCommandStateMemCmd; + dallas_common_emulate_read_mem(bus, data->sram_data, DS1992_SRAM_DATA_SIZE); + return false; + + } else { + return false; + } + + case DALLAS_COMMON_CMD_READ_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return dallas_common_emulate_read_rom(bus, &data->rom_data); + } else { + return false; + } + + case DALLAS_COMMON_CMD_SKIP_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return true; + } else { + return false; + } + + default: + return false; + } +} + +void dallas_ds1992_emulate(OneWireSlave* bus, iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + data->state.bus = bus; + + onewire_slave_set_reset_callback(bus, dallas_ds1992_reset_callback, protocol_data); + onewire_slave_set_command_callback(bus, dallas_ds1992_command_callback, protocol_data); +} + +bool dallas_ds1992_load( + FlipperFormat* ff, + uint32_t format_version, + iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + bool success = false; + + do { + if(format_version < 2) break; + if(!dallas_common_load_rom_data(ff, format_version, &data->rom_data)) break; + if(!flipper_format_read_hex( + ff, DS1992_SRAM_DATA_KEY, data->sram_data, DS1992_SRAM_DATA_SIZE)) + break; + success = true; + } while(false); + + return success; +} + +bool dallas_ds1992_save(FlipperFormat* ff, const iButtonProtocolData* protocol_data) { + const DS1992ProtocolData* data = protocol_data; + bool success = false; + + do { + if(!dallas_common_save_rom_data(ff, &data->rom_data)) break; + if(!flipper_format_write_hex( + ff, DS1992_SRAM_DATA_KEY, data->sram_data, DS1992_SRAM_DATA_SIZE)) + break; + success = true; + } while(false); + + return success; +} + +void dallas_ds1992_render_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1992ProtocolData* data = protocol_data; + pretty_format_bytes_hex_canonical( + result, + DS1992_DATA_BYTE_COUNT, + PRETTY_FORMAT_FONT_MONOSPACE, + data->sram_data, + DS1992_SRAM_DATA_SIZE); +} + +void dallas_ds1992_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1992ProtocolData* data = protocol_data; + dallas_common_render_brief_data( + result, &data->rom_data, data->sram_data, DS1992_SRAM_DATA_SIZE); +} + +void dallas_ds1992_render_error(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1992ProtocolData* data = protocol_data; + + if(!dallas_common_is_valid_crc(&data->rom_data)) { + dallas_common_render_crc_error(result, &data->rom_data); + } +} + +bool dallas_ds1992_is_data_valid(const iButtonProtocolData* protocol_data) { + const DS1992ProtocolData* data = protocol_data; + return dallas_common_is_valid_crc(&data->rom_data); +} + +void dallas_ds1992_get_editable_data( + iButtonEditableData* editable_data, + iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + editable_data->ptr = data->rom_data.bytes; + editable_data->size = sizeof(DallasCommonRomData); +} + +void dallas_ds1992_apply_edits(iButtonProtocolData* protocol_data) { + DS1992ProtocolData* data = protocol_data; + dallas_common_apply_edits(&data->rom_data, DS1992_FAMILY_CODE); +} diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.h b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.h new file mode 100644 index 000000000..5a3c45f3b --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1992.h @@ -0,0 +1,5 @@ +#pragma once + +#include "protocol_dallas_base.h" + +extern const iButtonProtocolDallasBase ibutton_protocol_ds1992; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.c b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.c new file mode 100644 index 000000000..e69145c58 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.c @@ -0,0 +1,212 @@ +#include "protocol_ds1996.h" + +#include +#include + +#include "dallas_common.h" + +#define DS1996_FAMILY_CODE 0x0CU +#define DS1996_FAMILY_NAME "DS1996" + +#define DS1996_SRAM_DATA_SIZE 8192U +#define DS1996_SRAM_PAGE_SIZE 32U +#define DS1996_COPY_SCRATCH_TIMEOUT_US 100U + +#define DS1996_DATA_BYTE_COUNT 4U + +#define DS1996_SRAM_DATA_KEY "Sram Data" + +typedef struct { + OneWireSlave* bus; + DallasCommonCommandState command_state; +} DS1996ProtocolState; + +typedef struct { + DallasCommonRomData rom_data; + uint8_t sram_data[DS1996_SRAM_DATA_SIZE]; + DS1996ProtocolState state; +} DS1996ProtocolData; + +static bool dallas_ds1996_read(OneWireHost*, void*); +static bool dallas_ds1996_write_copy(OneWireHost*, iButtonProtocolData*); +static void dallas_ds1996_emulate(OneWireSlave*, iButtonProtocolData*); +static bool dallas_ds1996_load(FlipperFormat*, uint32_t, iButtonProtocolData*); +static bool dallas_ds1996_save(FlipperFormat*, const iButtonProtocolData*); +static void dallas_ds1996_render_data(FuriString*, const iButtonProtocolData*); +static void dallas_ds1996_render_brief_data(FuriString*, const iButtonProtocolData*); +static void dallas_ds1996_render_error(FuriString*, const iButtonProtocolData*); +static bool dallas_ds1996_is_data_valid(const iButtonProtocolData*); +static void dallas_ds1996_get_editable_data(iButtonEditableData*, iButtonProtocolData*); +static void dallas_ds1996_apply_edits(iButtonProtocolData*); + +const iButtonProtocolDallasBase ibutton_protocol_ds1996 = { + .family_code = DS1996_FAMILY_CODE, + .features = iButtonProtocolFeatureExtData | iButtonProtocolFeatureWriteCopy, + .data_size = sizeof(DS1996ProtocolData), + .manufacturer = DALLAS_COMMON_MANUFACTURER_NAME, + .name = DS1996_FAMILY_NAME, + + .read = dallas_ds1996_read, + .write_blank = NULL, /* Data too big for known blanks */ + .write_copy = dallas_ds1996_write_copy, + .emulate = dallas_ds1996_emulate, + .save = dallas_ds1996_save, + .load = dallas_ds1996_load, + .render_data = dallas_ds1996_render_data, + .render_brief_data = dallas_ds1996_render_brief_data, + .render_error = dallas_ds1996_render_error, + .is_valid = dallas_ds1996_is_data_valid, + .get_editable_data = dallas_ds1996_get_editable_data, + .apply_edits = dallas_ds1996_apply_edits, +}; + +bool dallas_ds1996_read(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + return onewire_host_reset(host) && dallas_common_read_rom(host, &data->rom_data) && + dallas_common_read_mem(host, 0, data->sram_data, DS1996_SRAM_DATA_SIZE); +} + +bool dallas_ds1996_write_copy(OneWireHost* host, iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + return dallas_common_write_mem( + host, + DS1996_COPY_SCRATCH_TIMEOUT_US, + DS1996_SRAM_PAGE_SIZE, + data->sram_data, + DS1996_SRAM_DATA_SIZE); +} + +static void dallas_ds1996_reset_callback(void* context) { + furi_assert(context); + DS1996ProtocolData* data = context; + data->state.command_state = DallasCommonCommandStateIdle; +} + +static bool dallas_ds1996_command_callback(uint8_t command, void* context) { + furi_assert(context); + DS1996ProtocolData* data = context; + OneWireSlave* bus = data->state.bus; + + switch(command) { + case DALLAS_COMMON_CMD_SEARCH_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return dallas_common_emulate_search_rom(bus, &data->rom_data); + + } else if(data->state.command_state == DallasCommonCommandStateRomCmd) { + data->state.command_state = DallasCommonCommandStateMemCmd; + dallas_common_emulate_read_mem(bus, data->sram_data, DS1996_SRAM_DATA_SIZE); + return false; + + } else { + return false; + } + + case DALLAS_COMMON_CMD_READ_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return dallas_common_emulate_read_rom(bus, &data->rom_data); + } else { + return false; + } + + case DALLAS_COMMON_CMD_SKIP_ROM: + if(data->state.command_state == DallasCommonCommandStateIdle) { + data->state.command_state = DallasCommonCommandStateRomCmd; + return true; + } else { + return false; + } + + case DALLAS_COMMON_CMD_OVERDRIVE_SKIP_ROM: + case DALLAS_COMMON_CMD_OVERDRIVE_MATCH_ROM: + /* TODO: Overdrive mode support */ + default: + return false; + } +} + +void dallas_ds1996_emulate(OneWireSlave* bus, iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + data->state.bus = bus; + + onewire_slave_set_reset_callback(bus, dallas_ds1996_reset_callback, protocol_data); + onewire_slave_set_command_callback(bus, dallas_ds1996_command_callback, protocol_data); +} + +bool dallas_ds1996_load( + FlipperFormat* ff, + uint32_t format_version, + iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + bool success = false; + + do { + if(format_version < 2) break; + if(!dallas_common_load_rom_data(ff, format_version, &data->rom_data)) break; + if(!flipper_format_read_hex( + ff, DS1996_SRAM_DATA_KEY, data->sram_data, DS1996_SRAM_DATA_SIZE)) + break; + success = true; + } while(false); + + return success; +} + +bool dallas_ds1996_save(FlipperFormat* ff, const iButtonProtocolData* protocol_data) { + const DS1996ProtocolData* data = protocol_data; + bool success = false; + + do { + if(!dallas_common_save_rom_data(ff, &data->rom_data)) break; + if(!flipper_format_write_hex( + ff, DS1996_SRAM_DATA_KEY, data->sram_data, DS1996_SRAM_DATA_SIZE)) + break; + success = true; + } while(false); + + return success; +} + +void dallas_ds1996_render_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1996ProtocolData* data = protocol_data; + + pretty_format_bytes_hex_canonical( + result, + DS1996_DATA_BYTE_COUNT, + PRETTY_FORMAT_FONT_MONOSPACE, + data->sram_data, + DS1996_SRAM_DATA_SIZE); +} + +void dallas_ds1996_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1996ProtocolData* data = protocol_data; + dallas_common_render_brief_data( + result, &data->rom_data, data->sram_data, DS1996_SRAM_DATA_SIZE); +} + +void dallas_ds1996_render_error(FuriString* result, const iButtonProtocolData* protocol_data) { + const DS1996ProtocolData* data = protocol_data; + + if(!dallas_common_is_valid_crc(&data->rom_data)) { + dallas_common_render_crc_error(result, &data->rom_data); + } +} + +bool dallas_ds1996_is_data_valid(const iButtonProtocolData* protocol_data) { + const DS1996ProtocolData* data = protocol_data; + return dallas_common_is_valid_crc(&data->rom_data); +} + +void dallas_ds1996_get_editable_data( + iButtonEditableData* editable_data, + iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + editable_data->ptr = data->rom_data.bytes; + editable_data->size = sizeof(DallasCommonRomData); +} + +void dallas_ds1996_apply_edits(iButtonProtocolData* protocol_data) { + DS1996ProtocolData* data = protocol_data; + dallas_common_apply_edits(&data->rom_data, DS1996_FAMILY_CODE); +} diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.h b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.h new file mode 100644 index 000000000..34546985b --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds1996.h @@ -0,0 +1,5 @@ +#pragma once + +#include "protocol_dallas_base.h" + +extern const iButtonProtocolDallasBase ibutton_protocol_ds1996; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.c b/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.c new file mode 100644 index 000000000..50fd04511 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.c @@ -0,0 +1,133 @@ +#include "protocol_ds_generic.h" + +#include +#include + +#include "dallas_common.h" + +#include "../blanks/tm2004.h" + +#define DALLAS_GENERIC_FAMILY_CODE 0x00U +#define DALLAS_GENERIC_FAMILY_NAME "DSGeneric" + +typedef struct { + OneWireSlave* bus; +} DallasGenericProtocolState; + +typedef struct { + DallasCommonRomData rom_data; + DallasGenericProtocolState state; +} DallasGenericProtocolData; + +static bool ds_generic_read(OneWireHost*, iButtonProtocolData*); +static bool ds_generic_write_blank(OneWireHost*, iButtonProtocolData*); +static void ds_generic_emulate(OneWireSlave*, iButtonProtocolData*); +static bool ds_generic_load(FlipperFormat*, uint32_t, iButtonProtocolData*); +static bool ds_generic_save(FlipperFormat*, const iButtonProtocolData*); +static void ds_generic_render_brief_data(FuriString*, const iButtonProtocolData*); +static void ds_generic_render_error(FuriString*, const iButtonProtocolData*); +static bool ds_generic_is_data_valid(const iButtonProtocolData*); +static void ds_generic_get_editable_data(iButtonEditableData*, iButtonProtocolData*); +static void ds_generic_apply_edits(iButtonProtocolData*); + +const iButtonProtocolDallasBase ibutton_protocol_ds_generic = { + .family_code = DALLAS_GENERIC_FAMILY_CODE, + .features = iButtonProtocolFeatureWriteBlank, + .data_size = sizeof(DallasGenericProtocolData), + .manufacturer = DALLAS_COMMON_MANUFACTURER_NAME, + .name = DALLAS_GENERIC_FAMILY_NAME, + + .read = ds_generic_read, + .write_blank = ds_generic_write_blank, + .write_copy = NULL, /* No data to write a copy */ + .emulate = ds_generic_emulate, + .save = ds_generic_save, + .load = ds_generic_load, + .render_data = NULL, /* No data to render */ + .render_brief_data = ds_generic_render_brief_data, + .render_error = ds_generic_render_error, + .is_valid = ds_generic_is_data_valid, + .get_editable_data = ds_generic_get_editable_data, + .apply_edits = ds_generic_apply_edits, +}; + +bool ds_generic_read(OneWireHost* host, iButtonProtocolData* protocol_data) { + DallasGenericProtocolData* data = protocol_data; + return onewire_host_reset(host) && dallas_common_read_rom(host, &data->rom_data); +} + +bool ds_generic_write_blank(OneWireHost* host, iButtonProtocolData* protocol_data) { + DallasGenericProtocolData* data = protocol_data; + return tm2004_write(host, data->rom_data.bytes, sizeof(DallasCommonRomData)); +} + +static bool ds_generic_command_callback(uint8_t command, void* context) { + furi_assert(context); + DallasGenericProtocolData* data = context; + OneWireSlave* bus = data->state.bus; + + switch(command) { + case DALLAS_COMMON_CMD_SEARCH_ROM: + dallas_common_emulate_search_rom(bus, &data->rom_data); + break; + case DALLAS_COMMON_CMD_READ_ROM: + dallas_common_emulate_read_rom(bus, &data->rom_data); + break; + default: + break; + } + + // No support for multiple consecutive commands + return false; +} + +void ds_generic_emulate(OneWireSlave* bus, iButtonProtocolData* protocol_data) { + DallasGenericProtocolData* data = protocol_data; + data->state.bus = bus; + + onewire_slave_set_reset_callback(bus, NULL, NULL); + onewire_slave_set_command_callback(bus, ds_generic_command_callback, protocol_data); +} + +bool ds_generic_save(FlipperFormat* ff, const iButtonProtocolData* protocol_data) { + const DallasGenericProtocolData* data = protocol_data; + return dallas_common_save_rom_data(ff, &data->rom_data); +} + +bool ds_generic_load( + FlipperFormat* ff, + uint32_t format_version, + iButtonProtocolData* protocol_data) { + DallasGenericProtocolData* data = protocol_data; + return dallas_common_load_rom_data(ff, format_version, &data->rom_data); +} + +void ds_generic_render_brief_data(FuriString* result, const iButtonProtocolData* protocol_data) { + const DallasGenericProtocolData* data = protocol_data; + + for(size_t i = 0; i < sizeof(DallasCommonRomData); ++i) { + furi_string_cat_printf(result, "%02X ", data->rom_data.bytes[i]); + } +} + +void ds_generic_render_error(FuriString* result, const iButtonProtocolData* protocol_data) { + UNUSED(result); + UNUSED(protocol_data); +} + +bool ds_generic_is_data_valid(const iButtonProtocolData* protocol_data) { + UNUSED(protocol_data); + return true; +} + +void ds_generic_get_editable_data( + iButtonEditableData* editable_data, + iButtonProtocolData* protocol_data) { + DallasGenericProtocolData* data = protocol_data; + editable_data->ptr = data->rom_data.bytes; + editable_data->size = sizeof(DallasCommonRomData); +} + +void ds_generic_apply_edits(iButtonProtocolData* protocol_data) { + UNUSED(protocol_data); +} diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.h b/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.h new file mode 100644 index 000000000..008f8a67b --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_ds_generic.h @@ -0,0 +1,5 @@ +#pragma once + +#include "protocol_dallas_base.h" + +extern const iButtonProtocolDallasBase ibutton_protocol_ds_generic; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.c b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.c new file mode 100644 index 000000000..d0ffa511b --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.c @@ -0,0 +1,310 @@ +#include "protocol_group_dallas.h" + +#include + +#include "protocol_group_dallas_defs.h" + +#define IBUTTON_ONEWIRE_ROM_SIZE 8U + +typedef struct { + OneWireHost* host; + OneWireSlave* bus; +} iButtonProtocolGroupDallas; + +static iButtonProtocolGroupDallas* ibutton_protocol_group_dallas_alloc() { + iButtonProtocolGroupDallas* group = malloc(sizeof(iButtonProtocolGroupDallas)); + + group->host = onewire_host_alloc(&ibutton_gpio); + group->bus = onewire_slave_alloc(&ibutton_gpio); + + return group; +} + +static void ibutton_protocol_group_dallas_free(iButtonProtocolGroupDallas* group) { + onewire_slave_free(group->bus); + onewire_host_free(group->host); + free(group); +} + +static size_t ibutton_protocol_group_dallas_get_max_data_size(iButtonProtocolGroupDallas* group) { + UNUSED(group); + size_t max_data_size = 0; + + for(iButtonProtocolLocalId i = 0; i < iButtonProtocolDSMax; ++i) { + const size_t current_rom_size = ibutton_protocols_dallas[i]->data_size; + if(current_rom_size > max_data_size) { + max_data_size = current_rom_size; + } + } + + return max_data_size; +} + +static bool ibutton_protocol_group_dallas_get_id_by_name( + iButtonProtocolGroupDallas* group, + iButtonProtocolLocalId* id, + const char* name) { + UNUSED(group); + // Handle older key files which refer to DS1990 as just "Dallas" + if(strcmp(name, "Dallas") == 0) { + *id = iButtonProtocolDS1990; + return true; + } + + for(iButtonProtocolLocalId i = 0; i < iButtonProtocolDSMax; ++i) { + if(strcmp(ibutton_protocols_dallas[i]->name, name) == 0) { + *id = i; + return true; + } + } + return false; +} + +static uint32_t ibutton_protocol_group_dallas_get_features( + iButtonProtocolGroupDallas* group, + iButtonProtocolLocalId id) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->features; +} + +static const char* ibutton_protocol_group_dallas_get_manufacturer( + iButtonProtocolGroupDallas* group, + iButtonProtocolLocalId id) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->manufacturer; +} + +static const char* ibutton_protocol_group_dallas_get_name( + iButtonProtocolGroupDallas* group, + iButtonProtocolLocalId id) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->name; +} + +static iButtonProtocolLocalId + ibutton_protocol_group_dallas_get_id_by_family_code(uint8_t family_code) { + iButtonProtocolLocalId id; + + for(id = 0; id < iButtonProtocolDSGeneric; ++id) { + if(ibutton_protocols_dallas[id]->family_code == family_code) break; + } + + return id; +} + +static bool ibutton_protocol_group_dallas_read( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId* id) { + bool success = false; + uint8_t rom_data[IBUTTON_ONEWIRE_ROM_SIZE]; + OneWireHost* host = group->host; + + onewire_host_start(host); + furi_delay_ms(100); + + FURI_CRITICAL_ENTER(); + + if(onewire_host_search(host, rom_data, OneWireHostSearchModeNormal)) { + /* Considering any found 1-Wire device a success. + * It can be checked later with ibutton_key_is_valid(). */ + success = true; + + /* If a 1-Wire device was found, id is guaranteed to be + * one of the known keys or DSGeneric. */ + *id = ibutton_protocol_group_dallas_get_id_by_family_code(rom_data[0]); + ibutton_protocols_dallas[*id]->read(host, data); + } + + onewire_host_reset_search(host); + onewire_host_stop(host); + + FURI_CRITICAL_EXIT(); + + return success; +} + +static bool ibutton_protocol_group_dallas_write_blank( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + furi_assert(id < iButtonProtocolDSMax); + const iButtonProtocolDallasBase* protocol = ibutton_protocols_dallas[id]; + furi_assert(protocol->features & iButtonProtocolFeatureWriteBlank); + + OneWireHost* host = group->host; + + onewire_host_start(host); + furi_delay_ms(100); + + FURI_CRITICAL_ENTER(); + + const bool success = protocol->write_blank(host, data); + onewire_host_stop(host); + + FURI_CRITICAL_EXIT(); + return success; +} + +static bool ibutton_protocol_group_dallas_write_copy( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + furi_assert(id < iButtonProtocolDSMax); + + const iButtonProtocolDallasBase* protocol = ibutton_protocols_dallas[id]; + furi_assert(protocol->features & iButtonProtocolFeatureWriteCopy); + + OneWireHost* host = group->host; + + onewire_host_start(host); + furi_delay_ms(100); + + FURI_CRITICAL_ENTER(); + + const bool success = protocol->write_copy(host, data); + onewire_host_stop(host); + + FURI_CRITICAL_EXIT(); + return success; +} + +static void ibutton_protocol_group_dallas_emulate_start( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + furi_assert(id < iButtonProtocolDSMax); + OneWireSlave* bus = group->bus; + ibutton_protocols_dallas[id]->emulate(bus, data); + onewire_slave_start(bus); +} + +static void ibutton_protocol_group_dallas_emulate_stop( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + furi_assert(id < iButtonProtocolDSMax); + UNUSED(data); + onewire_slave_stop(group->bus); +} + +static bool ibutton_protocol_group_dallas_save( + iButtonProtocolGroupDallas* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FlipperFormat* ff) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->save(ff, data); +} + +static bool ibutton_protocol_group_dallas_load( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id, + uint32_t version, + FlipperFormat* ff) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->load(ff, version, data); +} + +static void ibutton_protocol_group_dallas_render_data( + iButtonProtocolGroupDallas* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + const iButtonProtocolDallasBase* protocol = ibutton_protocols_dallas[id]; + furi_assert(protocol->render_data); + protocol->render_data(result, data); +} + +static void ibutton_protocol_group_dallas_render_brief_data( + iButtonProtocolGroupDallas* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + ibutton_protocols_dallas[id]->render_brief_data(result, data); +} + +static void ibutton_protocol_group_dallas_render_error( + iButtonProtocolGroupDallas* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + ibutton_protocols_dallas[id]->render_error(result, data); +} + +static bool ibutton_protocol_group_dallas_is_valid( + iButtonProtocolGroupDallas* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + return ibutton_protocols_dallas[id]->is_valid(data); +} + +static void ibutton_protocol_group_dallas_get_editable_data( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id, + iButtonEditableData* editable) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + ibutton_protocols_dallas[id]->get_editable_data(editable, data); +} + +static void ibutton_protocol_group_dallas_apply_edits( + iButtonProtocolGroupDallas* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + UNUSED(group); + furi_assert(id < iButtonProtocolDSMax); + ibutton_protocols_dallas[id]->apply_edits(data); +} + +const iButtonProtocolGroupBase ibutton_protocol_group_dallas = { + .protocol_count = iButtonProtocolDSMax, + + .alloc = (iButtonProtocolGroupAllocFunc)ibutton_protocol_group_dallas_alloc, + .free = (iButtonProtocolGroupFreeFunc)ibutton_protocol_group_dallas_free, + + .get_max_data_size = + (iButtonProtocolGropuGetSizeFunc)ibutton_protocol_group_dallas_get_max_data_size, + .get_id_by_name = (iButtonProtocolGroupGetIdFunc)ibutton_protocol_group_dallas_get_id_by_name, + .get_features = + (iButtonProtocolGroupGetFeaturesFunc)ibutton_protocol_group_dallas_get_features, + + .get_manufacturer = + (iButtonProtocolGroupGetStringFunc)ibutton_protocol_group_dallas_get_manufacturer, + .get_name = (iButtonProtocolGroupGetStringFunc)ibutton_protocol_group_dallas_get_name, + + .read = (iButtonProtocolGroupReadFunc)ibutton_protocol_group_dallas_read, + .write_blank = (iButtonProtocolGroupWriteFunc)ibutton_protocol_group_dallas_write_blank, + .write_copy = (iButtonProtocolGroupWriteFunc)ibutton_protocol_group_dallas_write_copy, + + .emulate_start = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_dallas_emulate_start, + .emulate_stop = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_dallas_emulate_stop, + + .save = (iButtonProtocolGroupSaveFunc)ibutton_protocol_group_dallas_save, + .load = (iButtonProtocolGroupLoadFunc)ibutton_protocol_group_dallas_load, + + .render_data = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_data, + .render_brief_data = + (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_brief_data, + .render_error = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_dallas_render_error, + + .is_valid = (iButtonProtocolGroupIsValidFunc)ibutton_protocol_group_dallas_is_valid, + .get_editable_data = + (iButtonProtocolGroupGetDataFunc)ibutton_protocol_group_dallas_get_editable_data, + .apply_edits = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_dallas_apply_edits, +}; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.h b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.h new file mode 100644 index 000000000..d1293c71b --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas.h @@ -0,0 +1,5 @@ +#pragma once + +#include "../protocol_group_base.h" + +extern const iButtonProtocolGroupBase ibutton_protocol_group_dallas; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.c b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.c new file mode 100644 index 000000000..e54c3125d --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.c @@ -0,0 +1,16 @@ +#include "protocol_group_dallas_defs.h" + +#include "protocol_ds1990.h" +#include "protocol_ds1992.h" +#include "protocol_ds1996.h" +#include "protocol_ds_generic.h" + +const iButtonProtocolDallasBase* ibutton_protocols_dallas[] = { + [iButtonProtocolDS1990] = &ibutton_protocol_ds1990, + [iButtonProtocolDS1992] = &ibutton_protocol_ds1992, + [iButtonProtocolDS1996] = &ibutton_protocol_ds1996, + /* Add new 1-Wire protocols here */ + + /* Default catch-all 1-Wire protocol */ + [iButtonProtocolDSGeneric] = &ibutton_protocol_ds_generic, +}; diff --git a/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.h b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.h new file mode 100644 index 000000000..ba74c0c23 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/dallas/protocol_group_dallas_defs.h @@ -0,0 +1,16 @@ +#pragma once + +#include "protocol_dallas_base.h" + +typedef enum { + iButtonProtocolDS1990, + iButtonProtocolDS1992, + iButtonProtocolDS1996, + /* Add new 1-Wire protocols here */ + + /* Default catch-all 1-Wire protocol */ + iButtonProtocolDSGeneric, + iButtonProtocolDSMax, +} iButtonProtocolDallas; + +extern const iButtonProtocolDallasBase* ibutton_protocols_dallas[]; diff --git a/lib/one_wire/ibutton/protocols/ibutton_protocols.c b/lib/one_wire/ibutton/protocols/ibutton_protocols.c deleted file mode 100644 index b07d68b33..000000000 --- a/lib/one_wire/ibutton/protocols/ibutton_protocols.c +++ /dev/null @@ -1,8 +0,0 @@ -#include "ibutton_protocols.h" -#include "protocol_cyfral.h" -#include "protocol_metakom.h" - -const ProtocolBase* ibutton_protocols[] = { - [iButtonProtocolCyfral] = &protocol_cyfral, - [iButtonProtocolMetakom] = &protocol_metakom, -}; \ No newline at end of file diff --git a/lib/one_wire/ibutton/protocols/ibutton_protocols.h b/lib/one_wire/ibutton/protocols/ibutton_protocols.h deleted file mode 100644 index cdaa3ab6f..000000000 --- a/lib/one_wire/ibutton/protocols/ibutton_protocols.h +++ /dev/null @@ -1,11 +0,0 @@ -#pragma once -#include "toolbox/protocols/protocol.h" - -typedef enum { - iButtonProtocolCyfral, - iButtonProtocolMetakom, - - iButtonProtocolMax, -} iButtonProtocol; - -extern const ProtocolBase* ibutton_protocols[]; \ No newline at end of file diff --git a/lib/one_wire/ibutton/protocols/protocol_cyfral.c b/lib/one_wire/ibutton/protocols/misc/protocol_cyfral.c similarity index 96% rename from lib/one_wire/ibutton/protocols/protocol_cyfral.c rename to lib/one_wire/ibutton/protocols/misc/protocol_cyfral.c index a5f459bc0..0cdb8766b 100644 --- a/lib/one_wire/ibutton/protocols/protocol_cyfral.c +++ b/lib/one_wire/ibutton/protocols/misc/protocol_cyfral.c @@ -1,5 +1,6 @@ #include #include + #include "protocol_cyfral.h" #define CYFRAL_DATA_SIZE sizeof(uint16_t) @@ -324,7 +325,13 @@ static LevelDuration protocol_cyfral_encoder_yield(ProtocolCyfral* proto) { return result; } -const ProtocolBase protocol_cyfral = { +static void protocol_cyfral_render_brief_data(ProtocolCyfral* proto, FuriString* result) { + for(size_t i = 0; i < CYFRAL_DATA_SIZE; ++i) { + furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]); + } +} + +const ProtocolBase ibutton_protocol_misc_cyfral = { .name = "Cyfral", .manufacturer = "Cyfral", .data_size = CYFRAL_DATA_SIZE, @@ -341,4 +348,5 @@ const ProtocolBase protocol_cyfral = { .start = (ProtocolEncoderStart)protocol_cyfral_encoder_start, .yield = (ProtocolEncoderYield)protocol_cyfral_encoder_yield, }, + .render_brief_data = (ProtocolRenderData)protocol_cyfral_render_brief_data, }; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_cyfral.h b/lib/one_wire/ibutton/protocols/misc/protocol_cyfral.h new file mode 100644 index 000000000..08b8eef81 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_cyfral.h @@ -0,0 +1,4 @@ +#pragma once +#include "toolbox/protocols/protocol.h" + +extern const ProtocolBase ibutton_protocol_misc_cyfral; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.c b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.c new file mode 100644 index 000000000..dad1ef3cf --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.c @@ -0,0 +1,295 @@ +#include "protocol_group_misc.h" + +#include +#include + +#include + +#include "protocol_group_misc_defs.h" + +#define IBUTTON_MISC_READ_TIMEOUT 100 + +#define IBUTTON_MISC_DATA_KEY_KEY_COMMON "Data" + +typedef struct { + ProtocolDict* dict; + ProtocolId emulate_id; +} iButtonProtocolGroupMisc; + +static iButtonProtocolGroupMisc* ibutton_protocol_group_misc_alloc() { + iButtonProtocolGroupMisc* group = malloc(sizeof(iButtonProtocolGroupMisc)); + + group->dict = protocol_dict_alloc(ibutton_protocols_misc, iButtonProtocolMiscMax); + group->emulate_id = PROTOCOL_NO; + + return group; +} + +static void ibutton_protocol_group_misc_free(iButtonProtocolGroupMisc* group) { + protocol_dict_free(group->dict); + free(group); +} + +static size_t ibutton_protocol_group_misc_get_max_data_size(iButtonProtocolGroupMisc* group) { + return protocol_dict_get_max_data_size(group->dict); +} + +static bool ibutton_protocol_group_misc_get_id_by_name( + iButtonProtocolGroupMisc* group, + iButtonProtocolLocalId* id, + const char* name) { + const ProtocolId found_id = protocol_dict_get_protocol_by_name(group->dict, name); + + if(found_id != PROTOCOL_NO) { + *id = found_id; + return true; + } + return false; +} + +static uint32_t ibutton_protocol_group_misc_get_features( + iButtonProtocolGroupMisc* group, + iButtonProtocolLocalId id) { + UNUSED(group); + UNUSED(id); + return 0; +} + +static const char* ibutton_protocol_group_misc_get_manufacturer( + iButtonProtocolGroupMisc* group, + iButtonProtocolLocalId id) { + return protocol_dict_get_manufacturer(group->dict, id); +} + +static const char* ibutton_protocol_group_misc_get_name( + iButtonProtocolGroupMisc* group, + iButtonProtocolLocalId id) { + return protocol_dict_get_name(group->dict, id); +} + +typedef struct { + uint32_t last_dwt_value; + FuriStreamBuffer* stream; +} iButtonReadContext; + +static void ibutton_protocols_comparator_callback(bool level, void* context) { + iButtonReadContext* read_context = context; + + uint32_t current_dwt_value = DWT->CYCCNT; + + LevelDuration data = + level_duration_make(level, current_dwt_value - read_context->last_dwt_value); + furi_stream_buffer_send(read_context->stream, &data, sizeof(LevelDuration), 0); + + read_context->last_dwt_value = current_dwt_value; +} + +static bool ibutton_protocol_group_misc_read( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId* id) { + bool result = false; + + protocol_dict_decoders_start(group->dict); + + furi_hal_rfid_pins_reset(); + // pulldown pull pin, we sense the signal through the analog part of the RFID schematic + furi_hal_rfid_pin_pull_pulldown(); + + iButtonReadContext read_context = { + .last_dwt_value = DWT->CYCCNT, + .stream = furi_stream_buffer_alloc(sizeof(LevelDuration) * 512, 1), + }; + + furi_hal_rfid_comp_set_callback(ibutton_protocols_comparator_callback, &read_context); + furi_hal_rfid_comp_start(); + + const uint32_t tick_start = furi_get_tick(); + + for(;;) { + LevelDuration level; + size_t ret = furi_stream_buffer_receive( + read_context.stream, &level, sizeof(LevelDuration), IBUTTON_MISC_READ_TIMEOUT); + + if((furi_get_tick() - tick_start) > IBUTTON_MISC_READ_TIMEOUT) { + break; + } + + if(ret > 0) { + ProtocolId decoded_index = protocol_dict_decoders_feed( + group->dict, level_duration_get_level(level), level_duration_get_duration(level)); + + if(decoded_index == PROTOCOL_NO) continue; + + *id = decoded_index; + + protocol_dict_get_data( + group->dict, + decoded_index, + data, + protocol_dict_get_data_size(group->dict, decoded_index)); + + result = true; + } + } + + furi_hal_rfid_comp_stop(); + furi_hal_rfid_comp_set_callback(NULL, NULL); + furi_hal_rfid_pins_reset(); + + furi_stream_buffer_free(read_context.stream); + + return result; +} + +static void ibutton_protocol_group_misc_emulate_callback(void* context) { + iButtonProtocolGroupMisc* group = context; + + const LevelDuration level_duration = + protocol_dict_encoder_yield(group->dict, group->emulate_id); + + furi_hal_ibutton_emulate_set_next(level_duration_get_duration(level_duration)); + furi_hal_ibutton_pin_write(level_duration_get_level(level_duration)); +} + +static void ibutton_protocol_group_misc_emulate_start( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + group->emulate_id = id; + protocol_dict_set_data(group->dict, id, data, protocol_dict_get_data_size(group->dict, id)); + protocol_dict_encoder_start(group->dict, group->emulate_id); + + furi_hal_ibutton_pin_configure(); + furi_hal_ibutton_emulate_start(0, ibutton_protocol_group_misc_emulate_callback, group); +} + +static void ibutton_protocol_group_misc_emulate_stop( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + UNUSED(group); + UNUSED(data); + UNUSED(id); + furi_hal_ibutton_emulate_stop(); + furi_hal_ibutton_pin_reset(); +} + +static bool ibutton_protocol_group_misc_save( + iButtonProtocolGroupMisc* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FlipperFormat* ff) { + const size_t data_size = protocol_dict_get_data_size(group->dict, id); + return flipper_format_write_hex(ff, IBUTTON_MISC_DATA_KEY_KEY_COMMON, data, data_size); +} + +static bool ibutton_protocol_group_misc_load( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id, + uint32_t version, + FlipperFormat* ff) { + const size_t data_size = protocol_dict_get_data_size(group->dict, id); + switch(version) { + case 1: + case 2: + return flipper_format_read_hex(ff, IBUTTON_MISC_DATA_KEY_KEY_COMMON, data, data_size); + default: + return false; + } +} + +static void ibutton_protocol_group_misc_render_data( + iButtonProtocolGroupMisc* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + const size_t data_size = protocol_dict_get_data_size(group->dict, id); + protocol_dict_set_data(group->dict, id, data, data_size); + protocol_dict_render_data(group->dict, result, id); +} + +static void ibutton_protocol_group_misc_render_brief_data( + iButtonProtocolGroupMisc* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + const size_t data_size = protocol_dict_get_data_size(group->dict, id); + protocol_dict_set_data(group->dict, id, data, data_size); + protocol_dict_render_brief_data(group->dict, result, id); +} + +static void ibutton_protocol_group_misc_render_error( + iButtonProtocolGroupMisc* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id, + FuriString* result) { + UNUSED(group); + UNUSED(data); + UNUSED(id); + UNUSED(result); +} + +static bool ibutton_protocol_group_misc_is_valid( + iButtonProtocolGroupMisc* group, + const iButtonProtocolData* data, + iButtonProtocolLocalId id) { + UNUSED(group); + UNUSED(data); + UNUSED(id); + return true; +} + +static void ibutton_protocol_group_misc_get_editable_data( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id, + iButtonEditableData* editable) { + editable->ptr = data; + editable->size = protocol_dict_get_data_size(group->dict, id); +} + +static void ibutton_protocol_group_misc_apply_edits( + iButtonProtocolGroupMisc* group, + iButtonProtocolData* data, + iButtonProtocolLocalId id) { + const size_t data_size = protocol_dict_get_data_size(group->dict, id); + protocol_dict_set_data(group->dict, id, data, data_size); +} + +const iButtonProtocolGroupBase ibutton_protocol_group_misc = { + .protocol_count = iButtonProtocolMiscMax, + + .alloc = (iButtonProtocolGroupAllocFunc)ibutton_protocol_group_misc_alloc, + .free = (iButtonProtocolGroupFreeFunc)ibutton_protocol_group_misc_free, + + .get_max_data_size = + (iButtonProtocolGropuGetSizeFunc)ibutton_protocol_group_misc_get_max_data_size, + .get_id_by_name = (iButtonProtocolGroupGetIdFunc)ibutton_protocol_group_misc_get_id_by_name, + .get_features = (iButtonProtocolGroupGetFeaturesFunc)ibutton_protocol_group_misc_get_features, + + .get_manufacturer = + (iButtonProtocolGroupGetStringFunc)ibutton_protocol_group_misc_get_manufacturer, + .get_name = (iButtonProtocolGroupGetStringFunc)ibutton_protocol_group_misc_get_name, + + .read = (iButtonProtocolGroupReadFunc)ibutton_protocol_group_misc_read, + .write_blank = NULL, + .write_copy = NULL, + + .emulate_start = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_misc_emulate_start, + .emulate_stop = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_misc_emulate_stop, + + .save = (iButtonProtocolGroupSaveFunc)ibutton_protocol_group_misc_save, + .load = (iButtonProtocolGroupLoadFunc)ibutton_protocol_group_misc_load, + + .render_data = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_misc_render_data, + .render_brief_data = + (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_misc_render_brief_data, + .render_error = (iButtonProtocolGroupRenderFunc)ibutton_protocol_group_misc_render_error, + + .is_valid = (iButtonProtocolGroupIsValidFunc)ibutton_protocol_group_misc_is_valid, + .get_editable_data = + (iButtonProtocolGroupGetDataFunc)ibutton_protocol_group_misc_get_editable_data, + .apply_edits = (iButtonProtocolGroupApplyFunc)ibutton_protocol_group_misc_apply_edits, +}; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.h b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.h new file mode 100644 index 000000000..7fde6e737 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc.h @@ -0,0 +1,5 @@ +#pragma once + +#include "../protocol_group_base.h" + +extern const iButtonProtocolGroupBase ibutton_protocol_group_misc; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.c b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.c new file mode 100644 index 000000000..09ae0bdc7 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.c @@ -0,0 +1,10 @@ +#include "protocol_group_misc_defs.h" + +#include "protocol_cyfral.h" +#include "protocol_metakom.h" + +const ProtocolBase* ibutton_protocols_misc[] = { + [iButtonProtocolMiscCyfral] = &ibutton_protocol_misc_cyfral, + [iButtonProtocolMiscMetakom] = &ibutton_protocol_misc_metakom, + /* Add new misc protocols here */ +}; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.h b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.h new file mode 100644 index 000000000..0a7f92847 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_group_misc_defs.h @@ -0,0 +1,11 @@ +#pragma once + +#include + +typedef enum { + iButtonProtocolMiscCyfral, + iButtonProtocolMiscMetakom, + iButtonProtocolMiscMax, +} iButtonProtocolMisc; + +extern const ProtocolBase* ibutton_protocols_misc[]; diff --git a/lib/one_wire/ibutton/protocols/protocol_metakom.c b/lib/one_wire/ibutton/protocols/misc/protocol_metakom.c similarity index 96% rename from lib/one_wire/ibutton/protocols/protocol_metakom.c rename to lib/one_wire/ibutton/protocols/misc/protocol_metakom.c index ff65c6678..a2bd2cf7c 100644 --- a/lib/one_wire/ibutton/protocols/protocol_metakom.c +++ b/lib/one_wire/ibutton/protocols/misc/protocol_metakom.c @@ -1,5 +1,6 @@ #include #include + #include "protocol_metakom.h" #define METAKOM_DATA_SIZE sizeof(uint32_t) @@ -300,7 +301,13 @@ static LevelDuration protocol_metakom_encoder_yield(ProtocolMetakom* proto) { return result; } -const ProtocolBase protocol_metakom = { +static void protocol_metakom_render_brief_data(ProtocolMetakom* proto, FuriString* result) { + for(size_t i = 0; i < METAKOM_DATA_SIZE; ++i) { + furi_string_cat_printf(result, "%02X ", ((uint8_t*)&proto->data)[i]); + } +} + +const ProtocolBase ibutton_protocol_misc_metakom = { .name = "Metakom", .manufacturer = "Metakom", .data_size = METAKOM_DATA_SIZE, @@ -317,4 +324,5 @@ const ProtocolBase protocol_metakom = { .start = (ProtocolEncoderStart)protocol_metakom_encoder_start, .yield = (ProtocolEncoderYield)protocol_metakom_encoder_yield, }, + .render_brief_data = (ProtocolRenderData)protocol_metakom_render_brief_data, }; diff --git a/lib/one_wire/ibutton/protocols/misc/protocol_metakom.h b/lib/one_wire/ibutton/protocols/misc/protocol_metakom.h new file mode 100644 index 000000000..317619e3f --- /dev/null +++ b/lib/one_wire/ibutton/protocols/misc/protocol_metakom.h @@ -0,0 +1,4 @@ +#pragma once +#include "toolbox/protocols/protocol.h" + +extern const ProtocolBase ibutton_protocol_misc_metakom; diff --git a/lib/one_wire/ibutton/protocols/protocol_common.h b/lib/one_wire/ibutton/protocols/protocol_common.h new file mode 100644 index 000000000..5383158e4 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/protocol_common.h @@ -0,0 +1,21 @@ +#pragma once + +#include +#include + +typedef int32_t iButtonProtocolId; + +enum { + iButtonProtocolIdInvalid = -1, +}; + +typedef enum { + iButtonProtocolFeatureExtData = (1U << 0), + iButtonProtocolFeatureWriteBlank = (1U << 1), + iButtonProtocolFeatureWriteCopy = (1U << 2), +} iButtonProtocolFeature; + +typedef struct { + uint8_t* ptr; + size_t size; +} iButtonEditableData; diff --git a/lib/one_wire/ibutton/protocols/protocol_common_i.h b/lib/one_wire/ibutton/protocols/protocol_common_i.h new file mode 100644 index 000000000..b80c92887 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/protocol_common_i.h @@ -0,0 +1,6 @@ +#pragma once + +#include "protocol_common.h" + +typedef void iButtonProtocolData; +typedef int32_t iButtonProtocolLocalId; diff --git a/lib/one_wire/ibutton/protocols/protocol_cyfral.h b/lib/one_wire/ibutton/protocols/protocol_cyfral.h deleted file mode 100644 index 97a98e485..000000000 --- a/lib/one_wire/ibutton/protocols/protocol_cyfral.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "toolbox/protocols/protocol.h" - -extern const ProtocolBase protocol_cyfral; \ No newline at end of file diff --git a/lib/one_wire/ibutton/protocols/protocol_group_base.h b/lib/one_wire/ibutton/protocols/protocol_group_base.h new file mode 100644 index 000000000..c8fec70fe --- /dev/null +++ b/lib/one_wire/ibutton/protocols/protocol_group_base.h @@ -0,0 +1,104 @@ +#pragma once + +#include +#include + +#include "protocol_common_i.h" + +typedef void iButtonProtocolGroupData; +typedef int32_t iButtonProtocolGroupId; + +typedef iButtonProtocolGroupData* (*iButtonProtocolGroupAllocFunc)(void); + +typedef void (*iButtonProtocolGroupFreeFunc)(iButtonProtocolGroupData*); + +typedef void (*iButtonProtocolGroupRenderFunc)( + iButtonProtocolGroupData*, + const iButtonProtocolData*, + iButtonProtocolLocalId, + FuriString*); + +typedef bool (*iButtonProtocolGroupIsValidFunc)( + iButtonProtocolGroupData*, + const iButtonProtocolData*, + iButtonProtocolLocalId); + +typedef void (*iButtonProtocolGroupGetDataFunc)( + iButtonProtocolGroupData*, + iButtonProtocolData*, + iButtonProtocolLocalId, + iButtonEditableData*); + +typedef void (*iButtonProtocolGroupApplyFunc)( + iButtonProtocolGroupData*, + iButtonProtocolData*, + iButtonProtocolLocalId); + +typedef size_t (*iButtonProtocolGropuGetSizeFunc)(iButtonProtocolGroupData*); + +typedef uint32_t ( + *iButtonProtocolGroupGetFeaturesFunc)(iButtonProtocolGroupData*, iButtonProtocolLocalId); + +typedef const char* ( + *iButtonProtocolGroupGetStringFunc)(iButtonProtocolGroupData*, iButtonProtocolLocalId); + +typedef bool (*iButtonProtocolGroupGetIdFunc)( + iButtonProtocolGroupData*, + iButtonProtocolLocalId*, + const char*); + +typedef bool (*iButtonProtocolGroupReadFunc)( + iButtonProtocolGroupData*, + iButtonProtocolData*, + iButtonProtocolLocalId*); + +typedef bool (*iButtonProtocolGroupWriteFunc)( + iButtonProtocolGroupData*, + iButtonProtocolData*, + iButtonProtocolLocalId); + +typedef bool (*iButtonProtocolGroupSaveFunc)( + iButtonProtocolGroupData*, + const iButtonProtocolData*, + iButtonProtocolLocalId, + FlipperFormat*); + +typedef bool (*iButtonProtocolGroupLoadFunc)( + iButtonProtocolGroupData*, + iButtonProtocolData*, + iButtonProtocolLocalId, + uint32_t, + FlipperFormat*); + +typedef struct { + const uint32_t protocol_count; + + iButtonProtocolGroupAllocFunc alloc; + iButtonProtocolGroupFreeFunc free; + + iButtonProtocolGropuGetSizeFunc get_max_data_size; + iButtonProtocolGroupGetIdFunc get_id_by_name; + iButtonProtocolGroupGetFeaturesFunc get_features; + + iButtonProtocolGroupGetStringFunc get_manufacturer; + iButtonProtocolGroupGetStringFunc get_name; + + iButtonProtocolGroupReadFunc read; + iButtonProtocolGroupWriteFunc write_blank; + iButtonProtocolGroupWriteFunc write_copy; + + iButtonProtocolGroupApplyFunc emulate_start; + iButtonProtocolGroupApplyFunc emulate_stop; + + iButtonProtocolGroupSaveFunc save; + iButtonProtocolGroupLoadFunc load; + + iButtonProtocolGroupRenderFunc render_data; + iButtonProtocolGroupRenderFunc render_brief_data; + iButtonProtocolGroupRenderFunc render_error; + + iButtonProtocolGroupIsValidFunc is_valid; + iButtonProtocolGroupGetDataFunc get_editable_data; + + iButtonProtocolGroupApplyFunc apply_edits; +} iButtonProtocolGroupBase; diff --git a/lib/one_wire/ibutton/protocols/protocol_group_defs.c b/lib/one_wire/ibutton/protocols/protocol_group_defs.c new file mode 100644 index 000000000..40a360f0e --- /dev/null +++ b/lib/one_wire/ibutton/protocols/protocol_group_defs.c @@ -0,0 +1,9 @@ +#include "protocol_group_defs.h" + +#include "dallas/protocol_group_dallas.h" +#include "misc/protocol_group_misc.h" + +const iButtonProtocolGroupBase* ibutton_protocol_groups[] = { + [iButtonProtocolGroupDallas] = &ibutton_protocol_group_dallas, + [iButtonProtocolGroupMisc] = &ibutton_protocol_group_misc, +}; diff --git a/lib/one_wire/ibutton/protocols/protocol_group_defs.h b/lib/one_wire/ibutton/protocols/protocol_group_defs.h new file mode 100644 index 000000000..2d41e3cb8 --- /dev/null +++ b/lib/one_wire/ibutton/protocols/protocol_group_defs.h @@ -0,0 +1,11 @@ +#pragma once + +#include "protocol_group_base.h" + +typedef enum { + iButtonProtocolGroupDallas, + iButtonProtocolGroupMisc, + iButtonProtocolGroupMax +} iButtonProtocolGroup; + +extern const iButtonProtocolGroupBase* ibutton_protocol_groups[]; diff --git a/lib/one_wire/ibutton/protocols/protocol_metakom.h b/lib/one_wire/ibutton/protocols/protocol_metakom.h deleted file mode 100644 index 5e44a2a8c..000000000 --- a/lib/one_wire/ibutton/protocols/protocol_metakom.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "toolbox/protocols/protocol.h" - -extern const ProtocolBase protocol_metakom; \ No newline at end of file diff --git a/lib/one_wire/one_wire_device.c b/lib/one_wire/one_wire_device.c deleted file mode 100644 index d9b4955db..000000000 --- a/lib/one_wire/one_wire_device.c +++ /dev/null @@ -1,59 +0,0 @@ -#include -#include "maxim_crc.h" -#include "one_wire_device.h" -#include "one_wire_slave.h" -#include "one_wire_slave_i.h" - -struct OneWireDevice { - uint8_t id_storage[8]; - OneWireSlave* bus; -}; - -OneWireDevice* onewire_device_alloc( - uint8_t id_1, - uint8_t id_2, - uint8_t id_3, - uint8_t id_4, - uint8_t id_5, - uint8_t id_6, - uint8_t id_7, - uint8_t id_8) { - OneWireDevice* device = malloc(sizeof(OneWireDevice)); - device->id_storage[0] = id_1; - device->id_storage[1] = id_2; - device->id_storage[2] = id_3; - device->id_storage[3] = id_4; - device->id_storage[4] = id_5; - device->id_storage[5] = id_6; - device->id_storage[6] = id_7; - device->id_storage[7] = id_8; - device->bus = NULL; - - return device; -} - -void onewire_device_free(OneWireDevice* device) { - if(device->bus != NULL) { - onewire_slave_detach(device->bus); - } - - free(device); -} - -void onewire_device_send_id(OneWireDevice* device) { - if(device->bus != NULL) { - onewire_slave_send(device->bus, device->id_storage, 8); - } -} - -void onewire_device_attach(OneWireDevice* device, OneWireSlave* bus) { - device->bus = bus; -} - -void onewire_device_detach(OneWireDevice* device) { - device->bus = NULL; -} - -uint8_t* onewire_device_get_id_p(OneWireDevice* device) { - return device->id_storage; -} diff --git a/lib/one_wire/one_wire_device.h b/lib/one_wire/one_wire_device.h deleted file mode 100644 index fc687c7ba..000000000 --- a/lib/one_wire/one_wire_device.h +++ /dev/null @@ -1,74 +0,0 @@ -/** - * @file one_wire_device.h - * - * 1-Wire slave library, device interface. Currently it can only emulate ID. - */ - -#pragma once -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct OneWireSlave OneWireSlave; -typedef struct OneWireDevice OneWireDevice; - -/** - * Allocate onewire device with ID - * @param id_1 - * @param id_2 - * @param id_3 - * @param id_4 - * @param id_5 - * @param id_6 - * @param id_7 - * @param id_8 - * @return OneWireDevice* - */ -OneWireDevice* onewire_device_alloc( - uint8_t id_1, - uint8_t id_2, - uint8_t id_3, - uint8_t id_4, - uint8_t id_5, - uint8_t id_6, - uint8_t id_7, - uint8_t id_8); - -/** - * Deallocate onewire device - * @param device - */ -void onewire_device_free(OneWireDevice* device); - -/** - * Send ID report, called from onewire slave - * @param device - */ -void onewire_device_send_id(OneWireDevice* device); - -/** - * Attach device to onewire slave bus - * @param device - * @param bus - */ -void onewire_device_attach(OneWireDevice* device, OneWireSlave* bus); - -/** - * Attach device from onewire slave bus - * @param device - */ -void onewire_device_detach(OneWireDevice* device); - -/** - * Get pointer to device id array - * @param device - * @return uint8_t* - */ -uint8_t* onewire_device_get_id_p(OneWireDevice* device); - -#ifdef __cplusplus -} -#endif diff --git a/lib/one_wire/one_wire_host.c b/lib/one_wire/one_wire_host.c index f3d3d3c4d..0a4a79f5c 100644 --- a/lib/one_wire/one_wire_host.c +++ b/lib/one_wire/one_wire_host.c @@ -116,6 +116,12 @@ void onewire_host_write(OneWireHost* host, uint8_t value) { } } +void onewire_host_write_bytes(OneWireHost* host, const uint8_t* buffer, uint16_t count) { + for(uint16_t i = 0; i < count; ++i) { + onewire_host_write(host, buffer[i]); + } +} + void onewire_host_skip(OneWireHost* host) { onewire_host_write(host, 0xCC); } @@ -175,10 +181,10 @@ uint8_t onewire_host_search(OneWireHost* host, uint8_t* new_addr, OneWireHostSea // issue the search command switch(mode) { - case CONDITIONAL_SEARCH: + case OneWireHostSearchModeConditional: onewire_host_write(host, 0xEC); break; - case NORMAL_SEARCH: + case OneWireHostSearchModeNormal: onewire_host_write(host, 0xF0); break; } diff --git a/lib/one_wire/one_wire_host.h b/lib/one_wire/one_wire_host.h index 9c01abc11..dc469904d 100644 --- a/lib/one_wire/one_wire_host.h +++ b/lib/one_wire/one_wire_host.h @@ -14,8 +14,8 @@ extern "C" { #endif typedef enum { - CONDITIONAL_SEARCH = 0, /**< Search for alarmed device */ - NORMAL_SEARCH = 1, /**< Search all devices */ + OneWireHostSearchModeConditional = 0, /**< Search for alarmed device */ + OneWireHostSearchModeNormal = 1, /**< Search all devices */ } OneWireHostSearchMode; typedef struct OneWireHost OneWireHost; @@ -76,6 +76,14 @@ void onewire_host_write_bit(OneWireHost* host, bool value); */ void onewire_host_write(OneWireHost* host, uint8_t value); +/** + * Write many bytes + * @param host + * @param buffer + * @param count + */ +void onewire_host_write_bytes(OneWireHost* host, const uint8_t* buffer, uint16_t count); + /** * Skip ROM command * @param host diff --git a/lib/one_wire/one_wire_slave.c b/lib/one_wire/one_wire_slave.c index 4b54c4f99..d1676cf3b 100644 --- a/lib/one_wire/one_wire_slave.c +++ b/lib/one_wire/one_wire_slave.c @@ -1,37 +1,42 @@ #include "one_wire_slave.h" -#include "one_wire_slave_i.h" -#include "one_wire_device.h" + #include #include -#define OWS_RESET_MIN 270 -#define OWS_RESET_MAX 960 -#define OWS_PRESENCE_TIMEOUT 20 -#define OWS_PRESENCE_MIN 100 -#define OWS_PRESENCE_MAX 480 -#define OWS_MSG_HIGH_TIMEOUT 15000 -#define OWS_SLOT_MAX 135 -#define OWS_READ_MIN 20 -#define OWS_READ_MAX 60 -#define OWS_WRITE_ZERO 30 +#define ONEWIRE_TRSTL_MIN 270 /* Minimum Reset Low time */ +#define ONEWIRE_TRSTL_MAX 1200 /* Maximum Reset Low time */ + +#define ONEWIRE_TPDH_TYP 20 /* Typical Presence Detect High time */ +#define ONEWIRE_TPDL_MIN 100 /* Minimum Presence Detect Low time */ +#define ONEWIRE_TPDL_MAX 480 /* Maximum Presence Detect Low time */ + +#define ONEWIRE_TSLOT_MIN 60 /* Minimum Read/Write Slot time */ +#define ONEWIRE_TSLOT_MAX 135 /* Maximum Read/Write Slot time */ + +#define ONEWIRE_TW1L_MAX 20 /* Maximum Master Write 1 time */ +#define ONEWIRE_TRL_TMSR_MAX 30 /* Maximum Master Read Low + Read Sample time */ + +#define ONEWIRE_TH_TIMEOUT 15000 /* Maximum time before general timeout */ typedef enum { - NO_ERROR = 0, - VERY_LONG_RESET, - VERY_SHORT_RESET, - PRESENCE_LOW_ON_LINE, - AWAIT_TIMESLOT_TIMEOUT_HIGH, - INCORRECT_ONEWIRE_CMD, - FIRST_BIT_OF_BYTE_TIMEOUT, - RESET_IN_PROGRESS + OneWireSlaveErrorNone = 0, + OneWireSlaveErrorResetInProgress, + OneWireSlaveErrorPresenceConflict, + OneWireSlaveErrorInvalidCommand, + OneWireSlaveErrorTimeout, } OneWireSlaveError; struct OneWireSlave { const GpioPin* gpio_pin; OneWireSlaveError error; - OneWireDevice* device; - OneWireSlaveResultCallback result_cb; - void* result_cb_ctx; + + OneWireSlaveResetCallback reset_callback; + OneWireSlaveCommandCallback command_callback; + OneWireSlaveResultCallback result_callback; + + void* reset_callback_context; + void* result_callback_context; + void* command_callback_context; }; /*********************** PRIVATE ***********************/ @@ -55,180 +60,94 @@ static uint32_t } static bool onewire_slave_show_presence(OneWireSlave* bus) { + // wait until the bus is high (might return immediately) + onewire_slave_wait_while_gpio_is(bus, ONEWIRE_TRSTL_MAX, false); // wait while master delay presence check - onewire_slave_wait_while_gpio_is(bus, OWS_PRESENCE_TIMEOUT, true); + furi_delay_us(ONEWIRE_TPDH_TYP); // show presence furi_hal_gpio_write(bus->gpio_pin, false); - furi_delay_us(OWS_PRESENCE_MIN); + furi_delay_us(ONEWIRE_TPDL_MIN); furi_hal_gpio_write(bus->gpio_pin, true); // somebody also can show presence - const uint32_t wait_low_time = OWS_PRESENCE_MAX - OWS_PRESENCE_MIN; + const uint32_t wait_low_time = ONEWIRE_TPDL_MAX - ONEWIRE_TPDL_MIN; // so we will wait if(onewire_slave_wait_while_gpio_is(bus, wait_low_time, false) == 0) { - bus->error = PRESENCE_LOW_ON_LINE; + bus->error = OneWireSlaveErrorPresenceConflict; return false; } return true; } -static bool onewire_slave_receive_bit(OneWireSlave* bus) { - // wait while bus is low - uint32_t time = OWS_SLOT_MAX; - time = onewire_slave_wait_while_gpio_is(bus, time, false); - if(time == 0) { - bus->error = RESET_IN_PROGRESS; - return false; - } - - // wait while bus is high - time = OWS_MSG_HIGH_TIMEOUT; - time = onewire_slave_wait_while_gpio_is(bus, time, true); - if(time == 0) { - bus->error = AWAIT_TIMESLOT_TIMEOUT_HIGH; - return false; - } - - // wait a time of zero - time = OWS_READ_MIN; - time = onewire_slave_wait_while_gpio_is(bus, time, false); - - return (time > 0); -} - -static bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { - const bool write_zero = !value; - - // wait while bus is low - uint32_t time = OWS_SLOT_MAX; - time = onewire_slave_wait_while_gpio_is(bus, time, false); - if(time == 0) { - bus->error = RESET_IN_PROGRESS; - return false; - } - - // wait while bus is high - time = OWS_MSG_HIGH_TIMEOUT; - time = onewire_slave_wait_while_gpio_is(bus, time, true); - if(time == 0) { - bus->error = AWAIT_TIMESLOT_TIMEOUT_HIGH; - return false; - } - - // choose write time - if(write_zero) { - furi_hal_gpio_write(bus->gpio_pin, false); - time = OWS_WRITE_ZERO; - } else { - time = OWS_READ_MAX; - } - - // hold line for ZERO or ONE time - furi_delay_us(time); - furi_hal_gpio_write(bus->gpio_pin, true); - - return true; -} - -static void onewire_slave_cmd_search_rom(OneWireSlave* bus) { - const uint8_t key_bytes = 8; - uint8_t* key = onewire_device_get_id_p(bus->device); - - for(uint8_t i = 0; i < key_bytes; i++) { - uint8_t key_byte = key[i]; - - for(uint8_t j = 0; j < 8; j++) { - bool bit = (key_byte >> j) & 0x01; - - if(!onewire_slave_send_bit(bus, bit)) return; - if(!onewire_slave_send_bit(bus, !bit)) return; - - onewire_slave_receive_bit(bus); - if(bus->error != NO_ERROR) return; - } - } -} - -static bool onewire_slave_receive_and_process_cmd(OneWireSlave* bus) { - uint8_t cmd; - onewire_slave_receive(bus, &cmd, 1); - - if(bus->error == RESET_IN_PROGRESS) - return true; - else if(bus->error != NO_ERROR) - return false; - - switch(cmd) { - case 0xF0: - // SEARCH ROM - onewire_slave_cmd_search_rom(bus); - return true; - - case 0x0F: - case 0x33: - // READ ROM - onewire_device_send_id(bus->device); - return true; - - default: // Unknown command - bus->error = INCORRECT_ONEWIRE_CMD; - return false; - } -} - -static bool onewire_slave_bus_start(OneWireSlave* bus) { - bool result = true; - - if(bus->device == NULL) { - result = false; - } else { - FURI_CRITICAL_ENTER(); - furi_hal_gpio_init(bus->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); - bus->error = NO_ERROR; - +static inline bool onewire_slave_receive_and_process_command(OneWireSlave* bus) { + /* Reset condition detected, send a presence pulse and reset protocol state */ + if(bus->error == OneWireSlaveErrorResetInProgress) { if(onewire_slave_show_presence(bus)) { - // TODO think about multiple command cycles - onewire_slave_receive_and_process_cmd(bus); - result = (bus->error == NO_ERROR || bus->error == INCORRECT_ONEWIRE_CMD); + bus->error = OneWireSlaveErrorNone; - } else { - result = false; + if(bus->reset_callback != NULL) { + bus->reset_callback(bus->reset_callback_context); + } + + return true; } - furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); - FURI_CRITICAL_EXIT(); + } else if(bus->error == OneWireSlaveErrorNone) { + uint8_t command; + if(!onewire_slave_receive(bus, &command, 1)) { + /* Upon failure, request an additional iteration to + choose the appropriate action by checking bus->error */ + return true; + } else if(bus->command_callback) { + return bus->command_callback(command, bus->command_callback_context); + } else { + bus->error = OneWireSlaveErrorInvalidCommand; + } } + return false; +} + +static inline bool onewire_slave_bus_start(OneWireSlave* bus) { + FURI_CRITICAL_ENTER(); + furi_hal_gpio_init(bus->gpio_pin, GpioModeOutputOpenDrain, GpioPullNo, GpioSpeedLow); + + /* Start in Reset state in order to send a presence pulse immediately */ + bus->error = OneWireSlaveErrorResetInProgress; + + while(onewire_slave_receive_and_process_command(bus)) + ; + + const bool result = (bus->error == OneWireSlaveErrorNone); + + furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); + FURI_CRITICAL_EXIT(); + return result; } -static void exti_cb(void* context) { +static void onewire_slave_exti_callback(void* context) { OneWireSlave* bus = context; - volatile bool input_state = furi_hal_gpio_read(bus->gpio_pin); + const volatile bool input_state = furi_hal_gpio_read(bus->gpio_pin); static uint32_t pulse_start = 0; if(input_state) { - uint32_t pulse_length = + const uint32_t pulse_length = (DWT->CYCCNT - pulse_start) / furi_hal_cortex_instructions_per_microsecond(); - if(pulse_length >= OWS_RESET_MIN) { - if(pulse_length <= OWS_RESET_MAX) { - // reset cycle ok - bool result = onewire_slave_bus_start(bus); - if(result && bus->result_cb != NULL) { - bus->result_cb(bus->result_cb_ctx); - } - } else { - bus->error = VERY_LONG_RESET; + + if((pulse_length >= ONEWIRE_TRSTL_MIN) && pulse_length <= (ONEWIRE_TRSTL_MAX)) { + const bool result = onewire_slave_bus_start(bus); + + if(result && bus->result_callback != NULL) { + bus->result_callback(bus->result_callback_context); } - } else { - bus->error = VERY_SHORT_RESET; } + } else { - //FALL event pulse_start = DWT->CYCCNT; } }; @@ -237,11 +156,10 @@ static void exti_cb(void* context) { OneWireSlave* onewire_slave_alloc(const GpioPin* gpio_pin) { OneWireSlave* bus = malloc(sizeof(OneWireSlave)); + bus->gpio_pin = gpio_pin; - bus->error = NO_ERROR; - bus->device = NULL; - bus->result_cb = NULL; - bus->result_cb_ctx = NULL; + bus->error = OneWireSlaveErrorNone; + return bus; } @@ -251,7 +169,7 @@ void onewire_slave_free(OneWireSlave* bus) { } void onewire_slave_start(OneWireSlave* bus) { - furi_hal_gpio_add_int_callback(bus->gpio_pin, exti_cb, bus); + furi_hal_gpio_add_int_callback(bus->gpio_pin, onewire_slave_exti_callback, bus); furi_hal_gpio_write(bus->gpio_pin, true); furi_hal_gpio_init(bus->gpio_pin, GpioModeInterruptRiseFall, GpioPullNo, GpioSpeedLow); } @@ -262,41 +180,98 @@ void onewire_slave_stop(OneWireSlave* bus) { furi_hal_gpio_remove_int_callback(bus->gpio_pin); } -void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device) { - bus->device = device; - onewire_device_attach(device, bus); +void onewire_slave_set_reset_callback( + OneWireSlave* bus, + OneWireSlaveResetCallback callback, + void* context) { + bus->reset_callback = callback; + bus->reset_callback_context = context; } -void onewire_slave_detach(OneWireSlave* bus) { - if(bus->device != NULL) { - onewire_device_detach(bus->device); - } - bus->device = NULL; +void onewire_slave_set_command_callback( + OneWireSlave* bus, + OneWireSlaveCommandCallback callback, + void* context) { + bus->command_callback = callback; + bus->command_callback_context = context; } void onewire_slave_set_result_callback( OneWireSlave* bus, OneWireSlaveResultCallback result_cb, void* context) { - bus->result_cb = result_cb; - bus->result_cb_ctx = context; + bus->result_callback = result_cb; + bus->result_callback_context = context; } -bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length) { - uint8_t bytes_sent = 0; +bool onewire_slave_receive_bit(OneWireSlave* bus) { + // wait while bus is low + uint32_t time = ONEWIRE_TSLOT_MAX; + time = onewire_slave_wait_while_gpio_is(bus, time, false); + if(time == 0) { + bus->error = OneWireSlaveErrorResetInProgress; + return false; + } + // wait while bus is high + time = ONEWIRE_TH_TIMEOUT; + time = onewire_slave_wait_while_gpio_is(bus, time, true); + if(time == 0) { + bus->error = OneWireSlaveErrorTimeout; + return false; + } + + // wait a time of zero + time = ONEWIRE_TW1L_MAX; + time = onewire_slave_wait_while_gpio_is(bus, time, false); + + return (time > 0); +} + +bool onewire_slave_send_bit(OneWireSlave* bus, bool value) { + // wait while bus is low + uint32_t time = ONEWIRE_TSLOT_MAX; + time = onewire_slave_wait_while_gpio_is(bus, time, false); + if(time == 0) { + bus->error = OneWireSlaveErrorResetInProgress; + return false; + } + + // wait while bus is high + time = ONEWIRE_TH_TIMEOUT; + time = onewire_slave_wait_while_gpio_is(bus, time, true); + if(time == 0) { + bus->error = OneWireSlaveErrorTimeout; + return false; + } + + // choose write time + if(!value) { + furi_hal_gpio_write(bus->gpio_pin, false); + time = ONEWIRE_TRL_TMSR_MAX; + } else { + time = ONEWIRE_TSLOT_MIN; + } + + // hold line for ZERO or ONE time + furi_delay_us(time); furi_hal_gpio_write(bus->gpio_pin, true); + return true; +} + +bool onewire_slave_send(OneWireSlave* bus, const uint8_t* data, size_t data_size) { + furi_hal_gpio_write(bus->gpio_pin, true); + + size_t bytes_sent = 0; + // bytes loop - for(; bytes_sent < data_length; ++bytes_sent) { - const uint8_t data_byte = address[bytes_sent]; + for(; bytes_sent < data_size; ++bytes_sent) { + const uint8_t data_byte = data[bytes_sent]; // bit loop for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) { if(!onewire_slave_send_bit(bus, bit_mask & data_byte)) { - // if we cannot send first bit - if((bit_mask == 0x01) && (bus->error == AWAIT_TIMESLOT_TIMEOUT_HIGH)) - bus->error = FIRST_BIT_OF_BYTE_TIMEOUT; return false; } } @@ -304,19 +279,25 @@ bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t return true; } -bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length) { - uint8_t bytes_received = 0; - +bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, size_t data_size) { furi_hal_gpio_write(bus->gpio_pin, true); - for(; bytes_received < data_length; ++bytes_received) { + size_t bytes_received = 0; + + for(; bytes_received < data_size; ++bytes_received) { uint8_t value = 0; for(uint8_t bit_mask = 0x01; bit_mask != 0; bit_mask <<= 1) { - if(onewire_slave_receive_bit(bus)) value |= bit_mask; + if(onewire_slave_receive_bit(bus)) { + value |= bit_mask; + } + + if(bus->error != OneWireSlaveErrorNone) { + return false; + } } data[bytes_received] = value; } - return (bytes_received != data_length); + return true; } diff --git a/lib/one_wire/one_wire_slave.h b/lib/one_wire/one_wire_slave.h index 2e5db3a1c..914cd9335 100644 --- a/lib/one_wire/one_wire_slave.h +++ b/lib/one_wire/one_wire_slave.h @@ -1,12 +1,14 @@ /** * @file one_wire_slave.h * - * 1-Wire slave library. Currently it can only emulate ID. + * 1-Wire slave library. */ #pragma once +#include #include #include + #include #ifdef __cplusplus @@ -15,7 +17,10 @@ extern "C" { typedef struct OneWireDevice OneWireDevice; typedef struct OneWireSlave OneWireSlave; + +typedef void (*OneWireSlaveResetCallback)(void* context); typedef void (*OneWireSlaveResultCallback)(void* context); +typedef bool (*OneWireSlaveCommandCallback)(uint8_t command, void* context); /** * Allocate onewire slave @@ -43,17 +48,54 @@ void onewire_slave_start(OneWireSlave* bus); void onewire_slave_stop(OneWireSlave* bus); /** - * Attach device for emulation - * @param bus - * @param device + * TODO: description comment */ -void onewire_slave_attach(OneWireSlave* bus, OneWireDevice* device); +bool onewire_slave_receive_bit(OneWireSlave* bus); /** - * Detach device from bus - * @param bus + * TODO: description comment */ -void onewire_slave_detach(OneWireSlave* bus); +bool onewire_slave_send_bit(OneWireSlave* bus, bool value); + +/** + * Send data + * @param bus + * @param data + * @param data_size + * @return bool + */ +bool onewire_slave_send(OneWireSlave* bus, const uint8_t* data, size_t data_size); + +/** + * Receive data + * @param bus + * @param data + * @param data_size + * @return bool + */ +bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, size_t data_size); + +/** + * Set a callback to be called on each reset + * @param bus + * @param callback + * @param context + */ +void onewire_slave_set_reset_callback( + OneWireSlave* bus, + OneWireSlaveResetCallback callback, + void* context); + +/** + * Set a callback to be called on each command + * @param bus + * @param callback + * @param context + */ +void onewire_slave_set_command_callback( + OneWireSlave* bus, + OneWireSlaveCommandCallback callback, + void* context); /** * Set a callback to report emulation success diff --git a/lib/one_wire/one_wire_slave_i.h b/lib/one_wire/one_wire_slave_i.h deleted file mode 100644 index 55e0762e4..000000000 --- a/lib/one_wire/one_wire_slave_i.h +++ /dev/null @@ -1,38 +0,0 @@ -/** - * @file one_wire_slave_i.h - * - * 1-Wire slave library, internal functions - */ - -#pragma once -#include -#include - -#ifdef __cplusplus -extern "C" { -#endif - -typedef struct OneWireDevice OneWireDevice; -typedef struct OneWireSlave OneWireSlave; - -/** - * Send data, called from emulated device - * @param bus - * @param address - * @param data_length - * @return bool - */ -bool onewire_slave_send(OneWireSlave* bus, const uint8_t* address, const uint8_t data_length); - -/** - * Receive data, called from emulated device - * @param bus - * @param data - * @param data_length - * @return bool - */ -bool onewire_slave_receive(OneWireSlave* bus, uint8_t* data, const uint8_t data_length); - -#ifdef __cplusplus -} -#endif diff --git a/lib/subghz/blocks/generic.c b/lib/subghz/blocks/generic.c index 54a401e05..331606fe5 100644 --- a/lib/subghz/blocks/generic.c +++ b/lib/subghz/blocks/generic.c @@ -20,12 +20,12 @@ void subghz_block_generic_get_preset_name(const char* preset_name, FuriString* p furi_string_set(preset_str, preset_name_temp); } -bool subghz_block_generic_serialize( +SubGhzProtocolStatus subghz_block_generic_serialize( SubGhzBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); do { @@ -33,11 +33,13 @@ bool subghz_block_generic_serialize( if(!flipper_format_write_header_cstr( flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { FURI_LOG_E(TAG, "Unable to add header"); + res = SubGhzProtocolStatusErrorParserHeader; break; } if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { FURI_LOG_E(TAG, "Unable to add Frequency"); + res = SubGhzProtocolStatusErrorParserFrequency; break; } @@ -45,27 +47,32 @@ bool subghz_block_generic_serialize( if(!flipper_format_write_string_cstr( flipper_format, "Preset", furi_string_get_cstr(temp_str))) { FURI_LOG_E(TAG, "Unable to add Preset"); + res = SubGhzProtocolStatusErrorParserPreset; break; } if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { if(!flipper_format_write_string_cstr( flipper_format, "Custom_preset_module", "CC1101")) { FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } if(!flipper_format_write_hex( flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } } if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) { FURI_LOG_E(TAG, "Unable to add Protocol"); + res = SubGhzProtocolStatusErrorParserProtocolName; break; } uint32_t temp = instance->data_count_bit; if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) { FURI_LOG_E(TAG, "Unable to add Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } @@ -76,6 +83,7 @@ bool subghz_block_generic_serialize( if(!flipper_format_write_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); + res = SubGhzProtocolStatusErrorParserKey; break; } @@ -88,15 +96,16 @@ bool subghz_block_generic_serialize( break; } } - res = true; + res = SubGhzProtocolStatusOk; } while(false); furi_string_free(temp_str); return res; } -bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format) { furi_assert(instance); - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); uint32_t temp_data = 0; @@ -104,10 +113,12 @@ bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperForma do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } instance->data_count_bit = (uint16_t)temp_data; @@ -115,16 +126,36 @@ bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperForma uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Missing Key"); + res = SubGhzProtocolStatusErrorParserKey; break; } for(uint8_t i = 0; i < sizeof(uint64_t); i++) { instance->data = instance->data << 8 | key_data[i]; } - res = true; + res = SubGhzProtocolStatusOk; } while(0); furi_string_free(temp_str); return res; } + +SubGhzProtocolStatus subghz_block_generic_deserialize_check_count_bit( + SubGhzBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit) { + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; + do { + ret = subghz_block_generic_deserialize(instance, flipper_format); + if(ret != SubGhzProtocolStatusOk) { + break; + } + if(instance->data_count_bit != count_bit) { + FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; + break; + } + } while(false); + return ret; +} \ No newline at end of file diff --git a/lib/subghz/blocks/generic.h b/lib/subghz/blocks/generic.h index e69de8b4f..10e7b63fa 100644 --- a/lib/subghz/blocks/generic.h +++ b/lib/subghz/blocks/generic.h @@ -39,9 +39,9 @@ void subghz_block_generic_get_preset_name(const char* preset_name, FuriString* p * @param instance Pointer to a SubGhzBlockGeneric instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return Status Error */ -bool subghz_block_generic_serialize( +SubGhzProtocolStatus subghz_block_generic_serialize( SubGhzBlockGeneric* instance, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -50,9 +50,22 @@ bool subghz_block_generic_serialize( * Deserialize data SubGhzBlockGeneric. * @param instance Pointer to a SubGhzBlockGeneric instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return Status Error */ -bool subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_block_generic_deserialize(SubGhzBlockGeneric* instance, FlipperFormat* flipper_format); + +/** + * Deserialize data SubGhzBlockGeneric. + * @param instance Pointer to a SubGhzBlockGeneric instance + * @param flipper_format Pointer to a FlipperFormat instance + * @param count_bit Count bit protocol + * @return Status Error + */ +SubGhzProtocolStatus subghz_block_generic_deserialize_check_count_bit( + SubGhzBlockGeneric* instance, + FlipperFormat* flipper_format, + uint16_t count_bit); #ifdef __cplusplus } diff --git a/lib/subghz/protocols/alutech_at_4n.c b/lib/subghz/protocols/alutech_at_4n.c index 15887cd6d..7b1bd5e76 100644 --- a/lib/subghz/protocols/alutech_at_4n.c +++ b/lib/subghz/protocols/alutech_at_4n.c @@ -320,7 +320,8 @@ bool subghz_protocol_alutech_at_4n_create_data( instance->generic.data_count_bit = 72; bool res = subghz_protocol_alutech_at_4n_gen_data(instance, btn); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -499,14 +500,15 @@ static bool subghz_protocol_encoder_alutech_at_4n_get_upload( return true; } -bool subghz_protocol_encoder_alutech_at_4n_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_alutech_at_4n_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderAlutech_at_4n* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -540,7 +542,7 @@ bool subghz_protocol_encoder_alutech_at_4n_deserialize( instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -740,46 +742,46 @@ uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context) { return (uint8_t)instance->crc; } -bool subghz_protocol_decoder_alutech_at_4n_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_alutech_at_4n_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderAlutech_at_4n* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { + SubGhzProtocolStatus res = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if((res == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32(flipper_format, "CRC", &instance->crc, 1)) { FURI_LOG_E(TAG, "Unable to add CRC"); - res = false; + res = SubGhzProtocolStatusErrorParserOthers; } return res; - - return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_alutech_at_4n_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_alutech_at_4n_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderAlutech_at_4n* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_alutech_at_4n_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_alutech_at_4n_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "CRC", (uint32_t*)&instance->crc, 1)) { FURI_LOG_E(TAG, "Missing CRC"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/alutech_at_4n.h b/lib/subghz/protocols/alutech_at_4n.h index b0ac056dd..89adbb5c6 100644 --- a/lib/subghz/protocols/alutech_at_4n.h +++ b/lib/subghz/protocols/alutech_at_4n.h @@ -55,9 +55,8 @@ bool subghz_protocol_alutech_at_4n_create_data( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_alutech_at_4n_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_alutech_at_4n_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -111,9 +110,9 @@ uint8_t subghz_protocol_decoder_alutech_at_4n_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_alutech_at_4n_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_alutech_at_4n_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -122,11 +121,10 @@ bool subghz_protocol_decoder_alutech_at_4n_serialize( * Deserialize data SubGhzProtocolDecoderAlutech_at_4n. * @param context Pointer to a SubGhzProtocolDecoderAlutech_at_4n instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_alutech_at_4n_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_alutech_at_4n_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/ansonic.c b/lib/subghz/protocols/ansonic.c index 81b196e36..9a122629b 100644 --- a/lib/subghz/protocols/ansonic.c +++ b/lib/subghz/protocols/ansonic.c @@ -136,28 +136,29 @@ static bool subghz_protocol_encoder_ansonic_get_upload(SubGhzProtocolEncoderAnso return true; } -bool subghz_protocol_encoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderAnsonic* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + res = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_ansonic_const.min_count_bit_for_found); + if(res != SubGhzProtocolStatusOk) { FURI_LOG_E(TAG, "Deserialize error"); break; } - if(instance->generic.data_count_bit != - subghz_protocol_ansonic_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_ansonic_get_upload(instance)) break; + if(!subghz_protocol_encoder_ansonic_get_upload(instance)) { + res = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); return res; @@ -301,7 +302,7 @@ uint8_t subghz_protocol_decoder_ansonic_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_ansonic_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_ansonic_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -310,22 +311,12 @@ bool subghz_protocol_decoder_ansonic_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderAnsonic* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_ansonic_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_ansonic_const.min_count_bit_for_found); } void subghz_protocol_decoder_ansonic_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/ansonic.h b/lib/subghz/protocols/ansonic.h index 0170a6048..955853187 100644 --- a/lib/subghz/protocols/ansonic.h +++ b/lib/subghz/protocols/ansonic.h @@ -30,7 +30,8 @@ void subghz_protocol_encoder_ansonic_free(void* context); * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -86,7 +87,7 @@ uint8_t subghz_protocol_decoder_ansonic_get_hash_data(void* context); * @param preset The modulation on which the signal was received, SubGhzRadioPreset * @return true On success */ -bool subghz_protocol_decoder_ansonic_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_ansonic_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -97,7 +98,8 @@ bool subghz_protocol_decoder_ansonic_serialize( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_decoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_ansonic_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/base.c b/lib/subghz/protocols/base.c index 36f33b9a5..37d1a308f 100644 --- a/lib/subghz/protocols/base.c +++ b/lib/subghz/protocols/base.c @@ -23,11 +23,11 @@ bool subghz_protocol_decoder_base_get_string( return status; } -bool subghz_protocol_decoder_base_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_base_serialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { - bool status = false; + SubGhzProtocolStatus status = SubGhzProtocolStatusError; if(decoder_base->protocol && decoder_base->protocol->decoder && decoder_base->protocol->decoder->serialize) { @@ -37,10 +37,10 @@ bool subghz_protocol_decoder_base_serialize( return status; } -bool subghz_protocol_decoder_base_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_base_deserialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format) { - bool status = false; + SubGhzProtocolStatus status = SubGhzProtocolStatusError; if(decoder_base->protocol && decoder_base->protocol->decoder && decoder_base->protocol->decoder->deserialize) { diff --git a/lib/subghz/protocols/base.h b/lib/subghz/protocols/base.h index 1f3d3e1be..1d819ab5e 100644 --- a/lib/subghz/protocols/base.h +++ b/lib/subghz/protocols/base.h @@ -49,9 +49,9 @@ bool subghz_protocol_decoder_base_get_string( * @param decoder_base Pointer to a SubGhzProtocolDecoderBase instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return Status Error */ -bool subghz_protocol_decoder_base_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_base_serialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -60,9 +60,9 @@ bool subghz_protocol_decoder_base_serialize( * Deserialize data SubGhzProtocolDecoderBase. * @param decoder_base Pointer to a SubGhzProtocolDecoderBase instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return Status Error */ -bool subghz_protocol_decoder_base_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_base_deserialize( SubGhzProtocolDecoderBase* decoder_base, FlipperFormat* flipper_format); diff --git a/lib/subghz/protocols/bett.c b/lib/subghz/protocols/bett.c index 644d80fd8..de13472ac 100644 --- a/lib/subghz/protocols/bett.c +++ b/lib/subghz/protocols/bett.c @@ -155,31 +155,32 @@ static bool subghz_protocol_encoder_bett_get_upload(SubGhzProtocolEncoderBETT* i return true; } -bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderBETT* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_bett_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { FURI_LOG_E(TAG, "Deserialize error"); break; } - if(instance->generic.data_count_bit != - subghz_protocol_bett_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_bett_get_upload(instance)) break; + if(!subghz_protocol_encoder_bett_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_bett_stop(void* context) { @@ -295,7 +296,7 @@ uint8_t subghz_protocol_decoder_bett_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_bett_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_bett_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -304,22 +305,12 @@ bool subghz_protocol_decoder_bett_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderBETT* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_bett_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_bett_const.min_count_bit_for_found); } void subghz_protocol_decoder_bett_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/bett.h b/lib/subghz/protocols/bett.h index c0ce0b7f4..0a11cbe69 100644 --- a/lib/subghz/protocols/bett.h +++ b/lib/subghz/protocols/bett.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_bett_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderBETT instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_bett_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_bett_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderBETT instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_bett_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_bett_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_bett_serialize( * Deserialize data SubGhzProtocolDecoderBETT. * @param context Pointer to a SubGhzProtocolDecoderBETT instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_bett_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/bin_raw.c b/lib/subghz/protocols/bin_raw.c index 67e0467ee..003cc5edd 100644 --- a/lib/subghz/protocols/bin_raw.c +++ b/lib/subghz/protocols/bin_raw.c @@ -219,20 +219,23 @@ static bool subghz_protocol_encoder_bin_raw_get_upload(SubGhzProtocolEncoderBinR return true; } -bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderBinRAW* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; uint32_t temp_data = 0; do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } @@ -240,6 +243,7 @@ bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* f if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); + res = SubGhzProtocolStatusErrorParserTe; break; } @@ -251,11 +255,13 @@ bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* f while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { FURI_LOG_E(TAG, "Markup overflow"); + res = SubGhzProtocolStatusErrorParserOthers; break; } byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); if(byte_count > BIN_RAW_BUF_DATA_SIZE) { FURI_LOG_E(TAG, "Receive buffer overflow"); + res = SubGhzProtocolStatusErrorParserOthers; break; } @@ -270,6 +276,7 @@ bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* f subghz_protocol_bin_raw_get_full_byte(temp_data))) { instance->data_markup[ind].bit_count = 0; FURI_LOG_E(TAG, "Missing Data_RAW"); + res = SubGhzProtocolStatusErrorParserOthers; break; } ind++; @@ -297,16 +304,20 @@ bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* f #endif if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) break; + if(!subghz_protocol_encoder_bin_raw_get_upload(instance)) { + break; + res = SubGhzProtocolStatusErrorEncoderGetUpload; + } instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(0); return res; @@ -957,14 +968,14 @@ uint8_t subghz_protocol_decoder_bin_raw_get_hash_data(void* context) { subghz_protocol_bin_raw_get_full_byte(instance->data_markup[0].bit_count)); } -bool subghz_protocol_decoder_bin_raw_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_bin_raw_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderBinRAW* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); do { @@ -972,11 +983,13 @@ bool subghz_protocol_decoder_bin_raw_serialize( if(!flipper_format_write_header_cstr( flipper_format, SUBGHZ_KEY_FILE_TYPE, SUBGHZ_KEY_FILE_VERSION)) { FURI_LOG_E(TAG, "Unable to add header"); + res = SubGhzProtocolStatusErrorParserHeader; break; } if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) { FURI_LOG_E(TAG, "Unable to add Frequency"); + res = SubGhzProtocolStatusErrorParserFrequency; break; } @@ -984,34 +997,40 @@ bool subghz_protocol_decoder_bin_raw_serialize( if(!flipper_format_write_string_cstr( flipper_format, "Preset", furi_string_get_cstr(temp_str))) { FURI_LOG_E(TAG, "Unable to add Preset"); + res = SubGhzProtocolStatusErrorParserPreset; break; } if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) { if(!flipper_format_write_string_cstr( flipper_format, "Custom_preset_module", "CC1101")) { FURI_LOG_E(TAG, "Unable to add Custom_preset_module"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } if(!flipper_format_write_hex( flipper_format, "Custom_preset_data", preset->data, preset->data_size)) { FURI_LOG_E(TAG, "Unable to add Custom_preset_data"); + res = SubGhzProtocolStatusErrorParserCustomPreset; break; } } if(!flipper_format_write_string_cstr( flipper_format, "Protocol", instance->generic.protocol_name)) { FURI_LOG_E(TAG, "Unable to add Protocol"); + res = SubGhzProtocolStatusErrorParserProtocolName; break; } uint32_t temp = instance->generic.data_count_bit; if(!flipper_format_write_uint32(flipper_format, "Bit", &temp, 1)) { FURI_LOG_E(TAG, "Unable to add Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } if(!flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { FURI_LOG_E(TAG, "Unable to add TE"); + res = SubGhzProtocolStatusErrorParserTe; break; } @@ -1020,6 +1039,7 @@ bool subghz_protocol_decoder_bin_raw_serialize( temp = instance->data_markup[i].bit_count; if(!flipper_format_write_uint32(flipper_format, "Bit_RAW", &temp, 1)) { FURI_LOG_E(TAG, "Bit_RAW"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_write_hex( @@ -1028,31 +1048,35 @@ bool subghz_protocol_decoder_bin_raw_serialize( instance->data + instance->data_markup[i].byte_bias, subghz_protocol_bin_raw_get_full_byte(instance->data_markup[i].bit_count))) { FURI_LOG_E(TAG, "Unable to add Data_RAW"); + res = SubGhzProtocolStatusErrorParserOthers; break; } i++; } - res = true; + res = SubGhzProtocolStatusOk; } while(false); furi_string_free(temp_str); return res; } -bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderBinRAW* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; uint32_t temp_data = 0; do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) { FURI_LOG_E(TAG, "Missing Bit"); + res = SubGhzProtocolStatusErrorParserBitCount; break; } @@ -1060,6 +1084,7 @@ bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* f if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); + res = SubGhzProtocolStatusErrorParserTe; break; } @@ -1071,11 +1096,13 @@ bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* f while(flipper_format_read_uint32(flipper_format, "Bit_RAW", (uint32_t*)&temp_data, 1)) { if(ind >= BIN_RAW_MAX_MARKUP_COUNT) { FURI_LOG_E(TAG, "Markup overflow"); + res = SubGhzProtocolStatusErrorParserOthers; break; } byte_count += subghz_protocol_bin_raw_get_full_byte(temp_data); if(byte_count > BIN_RAW_BUF_DATA_SIZE) { FURI_LOG_E(TAG, "Receive buffer overflow"); + res = SubGhzProtocolStatusErrorParserOthers; break; } @@ -1090,12 +1117,13 @@ bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* f subghz_protocol_bin_raw_get_full_byte(temp_data))) { instance->data_markup[ind].bit_count = 0; FURI_LOG_E(TAG, "Missing Data_RAW"); + res = SubGhzProtocolStatusErrorParserOthers; break; } ind++; } - res = true; + res = SubGhzProtocolStatusOk; } while(0); return res; diff --git a/lib/subghz/protocols/bin_raw.h b/lib/subghz/protocols/bin_raw.h index c63f86ce6..82775e575 100644 --- a/lib/subghz/protocols/bin_raw.h +++ b/lib/subghz/protocols/bin_raw.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_bin_raw_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderBinRAW instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -88,9 +89,9 @@ void subghz_protocol_decoder_bin_raw_data_input_rssi( * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_bin_raw_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_bin_raw_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -99,9 +100,10 @@ bool subghz_protocol_decoder_bin_raw_serialize( * Deserialize data SubGhzProtocolDecoderBinRAW. * @param context Pointer to a SubGhzProtocolDecoderBinRAW instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_bin_raw_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/came.c b/lib/subghz/protocols/came.c index 00e2f49f2..14b2e0101 100644 --- a/lib/subghz/protocols/came.c +++ b/lib/subghz/protocols/came.c @@ -13,6 +13,7 @@ */ #define TAG "SubGhzProtocolCAME" +#define CAME_12_COUNT_BIT 12 #define CAME_24_COUNT_BIT 24 #define PRASTEL_COUNT_BIT 25 #define PRASTEL_NAME "Prastel" @@ -108,6 +109,7 @@ void subghz_protocol_encoder_came_free(void* context) { */ static bool subghz_protocol_encoder_came_get_upload(SubGhzProtocolEncoderCame* instance) { furi_assert(instance); + uint32_t header_te = 0; size_t index = 0; size_t size_upload = (instance->generic.data_count_bit * 2) + 2; if(size_upload > instance->encoder.size_upload) { @@ -117,25 +119,28 @@ static bool subghz_protocol_encoder_came_get_upload(SubGhzProtocolEncoderCame* i instance->encoder.size_upload = size_upload; } //Send header - // CAME 24 Bit = 24320 us - if(instance->generic.data_count_bit == CAME_24_COUNT_BIT) { - instance->encoder.upload[index++] = - level_duration_make(false, (uint32_t)subghz_protocol_came_const.te_short * 76); - } else if( - (instance->generic.data_count_bit == subghz_protocol_came_const.min_count_bit_for_found) || - (instance->generic.data_count_bit == AIRFORCE_COUNT_BIT)) { + + switch(instance->generic.data_count_bit) { + case CAME_24_COUNT_BIT: + // CAME 24 Bit = 24320 us + header_te = 76; + break; + case CAME_12_COUNT_BIT: + case AIRFORCE_COUNT_BIT: // CAME 12 Bit Original only! and Airforce protocol = 15040 us - instance->encoder.upload[index++] = - level_duration_make(false, (uint32_t)subghz_protocol_came_const.te_short * 47); - } else if(instance->generic.data_count_bit == PRASTEL_COUNT_BIT) { + header_te = 47; + break; + case PRASTEL_COUNT_BIT: // PRASTEL = 11520 us - instance->encoder.upload[index++] = - level_duration_make(false, (uint32_t)subghz_protocol_came_const.te_short * 36); - } else { + header_te = 36; + break; + default: // Some wrong detected protocols, 5120 us - instance->encoder.upload[index++] = - level_duration_make(false, (uint32_t)subghz_protocol_came_const.te_short * 16); + header_te = 16; + break; } + instance->encoder.upload[index++] = + level_duration_make(false, (uint32_t)subghz_protocol_came_const.te_short * header_te); //Send start bit instance->encoder.upload[index++] = level_duration_make(true, (uint32_t)subghz_protocol_came_const.te_short); @@ -158,30 +163,33 @@ static bool subghz_protocol_encoder_came_get_upload(SubGhzProtocolEncoderCame* i return true; } -bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderCame* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit > PRASTEL_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_came_get_upload(instance)) break; + if(!subghz_protocol_encoder_came_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_came_stop(void* context) { @@ -256,8 +264,11 @@ void subghz_protocol_decoder_came_feed(void* context, bool level, uint32_t durat if(!level) { //save interval if(duration >= (subghz_protocol_came_const.te_short * 4)) { instance->decoder.parser_step = CameDecoderStepFoundStartBit; - if(instance->decoder.decode_count_bit >= - subghz_protocol_came_const.min_count_bit_for_found) { + if((instance->decoder.decode_count_bit == + subghz_protocol_came_const.min_count_bit_for_found) || + (instance->decoder.decode_count_bit == AIRFORCE_COUNT_BIT) || + (instance->decoder.decode_count_bit == PRASTEL_COUNT_BIT) || + (instance->decoder.decode_count_bit == CAME_24_COUNT_BIT)) { instance->generic.serial = 0x0; instance->generic.btn = 0x0; @@ -306,7 +317,7 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_came_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -315,19 +326,21 @@ bool subghz_protocol_decoder_came_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCame* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit > PRASTEL_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/came.h b/lib/subghz/protocols/came.h index 253c93aae..fffa017ff 100644 --- a/lib/subghz/protocols/came.h +++ b/lib/subghz/protocols/came.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_came_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderCame instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_came_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_came_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderCame instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_came_serialize( * Deserialize data SubGhzProtocolDecoderCame. * @param context Pointer to a SubGhzProtocolDecoderCame instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_came_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/came_atomo.c b/lib/subghz/protocols/came_atomo.c index 45403d279..870afede3 100644 --- a/lib/subghz/protocols/came_atomo.c +++ b/lib/subghz/protocols/came_atomo.c @@ -223,12 +223,14 @@ static void instance->generic.data &= 0xFFFFFFFFFFFFFFF; } -bool subghz_protocol_encoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderCameAtomo* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -255,7 +257,7 @@ bool subghz_protocol_encoder_came_atomo_deserialize(void* context, FlipperFormat instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -549,7 +551,7 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_came_atomo_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_atomo_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -558,22 +560,14 @@ bool subghz_protocol_decoder_came_atomo_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCameAtomo* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_came_atomo_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_came_atomo_const.min_count_bit_for_found); } void subghz_protocol_decoder_came_atomo_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/came_atomo.h b/lib/subghz/protocols/came_atomo.h index 736aee850..c5e45a68d 100644 --- a/lib/subghz/protocols/came_atomo.h +++ b/lib/subghz/protocols/came_atomo.h @@ -33,7 +33,8 @@ void subghz_protocol_encoder_came_atomo_free(void* context); * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -87,9 +88,9 @@ uint8_t subghz_protocol_decoder_came_atomo_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderCameAtomo instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_atomo_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_atomo_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -98,9 +99,10 @@ bool subghz_protocol_decoder_came_atomo_serialize( * Deserialize data SubGhzProtocolDecoderCameAtomo. * @param context Pointer to a SubGhzProtocolDecoderCameAtomo instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_came_atomo_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/came_twee.c b/lib/subghz/protocols/came_twee.c index e7eb33c42..6fe615813 100644 --- a/lib/subghz/protocols/came_twee.c +++ b/lib/subghz/protocols/came_twee.c @@ -241,18 +241,17 @@ static void subghz_protocol_came_twee_remote_controller(SubGhzBlockGeneric* inst instance->cnt = data >> 6; } -bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderCameTwee* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_came_twee_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + res = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_came_twee_const.min_count_bit_for_found); + if(res != SubGhzProtocolStatusOk) { break; } //optional parameter parameter @@ -262,8 +261,6 @@ bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* subghz_protocol_came_twee_remote_controller(&instance->generic); subghz_protocol_encoder_came_twee_get_upload(instance); instance->encoder.is_running = true; - - res = true; } while(false); return res; @@ -419,7 +416,7 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_came_twee_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_twee_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -428,22 +425,14 @@ bool subghz_protocol_decoder_came_twee_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderCameTwee* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_came_twee_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_came_twee_const.min_count_bit_for_found); } void subghz_protocol_decoder_came_twee_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/came_twee.h b/lib/subghz/protocols/came_twee.h index 359b964da..f26f1e806 100644 --- a/lib/subghz/protocols/came_twee.h +++ b/lib/subghz/protocols/came_twee.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_came_twee_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderCameTwee instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_came_twee_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderCameTwee instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_twee_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_came_twee_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_came_twee_serialize( * Deserialize data SubGhzProtocolDecoderCameTwee. * @param context Pointer to a SubGhzProtocolDecoderCameTwee instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_came_twee_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/chamberlain_code.c b/lib/subghz/protocols/chamberlain_code.c index 9c8e5ee4a..be0877fb5 100644 --- a/lib/subghz/protocols/chamberlain_code.c +++ b/lib/subghz/protocols/chamberlain_code.c @@ -207,31 +207,35 @@ static bool return true; } -bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderChamb_Code* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if(instance->generic.data_count_bit > subghz_protocol_chamb_code_const.min_count_bit_for_found) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_chamb_code_get_upload(instance)) break; + if(!subghz_protocol_encoder_chamb_code_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_chamb_code_stop(void* context) { @@ -425,7 +429,7 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_chamb_code_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_chamb_code_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -434,20 +438,22 @@ bool subghz_protocol_decoder_chamb_code_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderChamb_Code* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if(instance->generic.data_count_bit > subghz_protocol_chamb_code_const.min_count_bit_for_found) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/chamberlain_code.h b/lib/subghz/protocols/chamberlain_code.h index f87b64d90..c8ffed5c5 100644 --- a/lib/subghz/protocols/chamberlain_code.h +++ b/lib/subghz/protocols/chamberlain_code.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_chamb_code_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderChamb_Code instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_chamb_code_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_chamb_code_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_chamb_code_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_chamb_code_serialize( * Deserialize data SubGhzProtocolDecoderChamb_Code. * @param context Pointer to a SubGhzProtocolDecoderChamb_Code instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_chamb_code_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/clemsa.c b/lib/subghz/protocols/clemsa.c index a2cb7a18b..a0547a113 100644 --- a/lib/subghz/protocols/clemsa.c +++ b/lib/subghz/protocols/clemsa.c @@ -155,31 +155,32 @@ static bool subghz_protocol_encoder_clemsa_get_upload(SubGhzProtocolEncoderClems return true; } -bool subghz_protocol_encoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderClemsa* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_clemsa_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_clemsa_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_clemsa_get_upload(instance)) break; + if(!subghz_protocol_encoder_clemsa_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_clemsa_stop(void* context) { @@ -316,7 +317,7 @@ uint8_t subghz_protocol_decoder_clemsa_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_clemsa_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_clemsa_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -325,22 +326,12 @@ bool subghz_protocol_decoder_clemsa_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderClemsa* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_clemsa_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_clemsa_const.min_count_bit_for_found); } void subghz_protocol_decoder_clemsa_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/clemsa.h b/lib/subghz/protocols/clemsa.h index 8858c1a3b..f14cd3dac 100644 --- a/lib/subghz/protocols/clemsa.h +++ b/lib/subghz/protocols/clemsa.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_clemsa_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderClemsa instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_clemsa_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderClemsa instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_clemsa_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_clemsa_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_clemsa_serialize( * Deserialize data SubGhzProtocolDecoderClemsa. * @param context Pointer to a SubGhzProtocolDecoderClemsa instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_clemsa_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/doitrand.c b/lib/subghz/protocols/doitrand.c index 6b31d4f27..69b8bba4a 100644 --- a/lib/subghz/protocols/doitrand.c +++ b/lib/subghz/protocols/doitrand.c @@ -136,31 +136,31 @@ static bool subghz_protocol_encoder_doitrand_get_upload(SubGhzProtocolEncoderDoi return true; } -bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderDoitrand* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_doitrand_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_doitrand_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_doitrand_get_upload(instance)) break; + if(!subghz_protocol_encoder_doitrand_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_doitrand_stop(void* context) { @@ -310,7 +310,7 @@ uint8_t subghz_protocol_decoder_doitrand_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_doitrand_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_doitrand_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -319,22 +319,14 @@ bool subghz_protocol_decoder_doitrand_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderDoitrand* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_doitrand_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_doitrand_const.min_count_bit_for_found); } void subghz_protocol_decoder_doitrand_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/doitrand.h b/lib/subghz/protocols/doitrand.h index 30f1fffd0..5dbc6678f 100644 --- a/lib/subghz/protocols/doitrand.h +++ b/lib/subghz/protocols/doitrand.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_doitrand_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderDoitrand instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_doitrand_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderDoitrand instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_doitrand_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_doitrand_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_doitrand_serialize( * Deserialize data SubGhzProtocolDecoderDoitrand. * @param context Pointer to a SubGhzProtocolDecoderDoitrand instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_doitrand_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/dooya.c b/lib/subghz/protocols/dooya.c index c70b6d54e..47e95209e 100644 --- a/lib/subghz/protocols/dooya.c +++ b/lib/subghz/protocols/dooya.c @@ -146,31 +146,31 @@ static bool subghz_protocol_encoder_dooya_get_upload(SubGhzProtocolEncoderDooya* return true; } -bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderDooya* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_dooya_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_dooya_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_dooya_get_upload(instance)) break; + if(!subghz_protocol_encoder_dooya_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_dooya_stop(void* context) { @@ -354,7 +354,7 @@ uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_dooya_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_dooya_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -363,22 +363,12 @@ bool subghz_protocol_decoder_dooya_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderDooya* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_dooya_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_dooya_const.min_count_bit_for_found); } /** diff --git a/lib/subghz/protocols/dooya.h b/lib/subghz/protocols/dooya.h index f0cf843c0..ffe9d41ef 100644 --- a/lib/subghz/protocols/dooya.h +++ b/lib/subghz/protocols/dooya.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_dooya_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderDooya instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_dooya_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderDooya instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_dooya_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_dooya_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_dooya_serialize( * Deserialize data SubGhzProtocolDecoderDooya. * @param context Pointer to a SubGhzProtocolDecoderDooya instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_dooya_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/faac_slh.c b/lib/subghz/protocols/faac_slh.c index 4b69ae73d..c1c96b7a7 100644 --- a/lib/subghz/protocols/faac_slh.c +++ b/lib/subghz/protocols/faac_slh.c @@ -169,7 +169,8 @@ bool subghz_protocol_faac_slh_create_data( instance->generic.data_count_bit = 64; bool res = subghz_protocol_faac_slh_gen_data(instance); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -217,12 +218,14 @@ static bool subghz_protocol_encoder_faac_slh_get_upload(SubGhzProtocolEncoderFaa return true; } -bool subghz_protocol_encoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderFaacSLH* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -261,7 +264,7 @@ bool subghz_protocol_encoder_faac_slh_deserialize(void* context, FlipperFormat* instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -422,22 +425,24 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_faac_slh_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_faac_slh_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus res = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); uint8_t seed_data[sizeof(uint32_t)] = {0}; for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; } - if(res && !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) { + if((res == SubGhzProtocolStatusOk) && + !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) { FURI_LOG_E(TAG, "Unable to add Seed"); - res = false; + res = SubGhzProtocolStatusError; } instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; @@ -448,12 +453,14 @@ bool subghz_protocol_decoder_faac_slh_serialize( return res; } -bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderFaacSLH* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -478,7 +485,7 @@ bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* FURI_LOG_E(TAG, "Rewind error"); break; } - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; diff --git a/lib/subghz/protocols/faac_slh.h b/lib/subghz/protocols/faac_slh.h index 9390da43a..bab042ca6 100644 --- a/lib/subghz/protocols/faac_slh.h +++ b/lib/subghz/protocols/faac_slh.h @@ -52,7 +52,8 @@ bool subghz_protocol_faac_slh_create_data( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -106,9 +107,9 @@ uint8_t subghz_protocol_decoder_faac_slh_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderFaacSLH instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_faac_slh_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_faac_slh_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -117,9 +118,10 @@ bool subghz_protocol_decoder_faac_slh_serialize( * Deserialize data SubGhzProtocolDecoderFaacSLH. * @param context Pointer to a SubGhzProtocolDecoderFaacSLH instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_faac_slh_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/gate_tx.c b/lib/subghz/protocols/gate_tx.c index 4c7c2d484..51a424fed 100644 --- a/lib/subghz/protocols/gate_tx.c +++ b/lib/subghz/protocols/gate_tx.c @@ -129,31 +129,31 @@ static bool subghz_protocol_encoder_gate_tx_get_upload(SubGhzProtocolEncoderGate return true; } -bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderGateTx* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_gate_tx_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_gate_tx_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_gate_tx_get_upload(instance)) break; + if(!subghz_protocol_encoder_gate_tx_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_gate_tx_stop(void* context) { @@ -290,7 +290,7 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_gate_tx_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_gate_tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -299,22 +299,12 @@ bool subghz_protocol_decoder_gate_tx_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderGateTx* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_gate_tx_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_gate_tx_const.min_count_bit_for_found); } void subghz_protocol_decoder_gate_tx_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/gate_tx.h b/lib/subghz/protocols/gate_tx.h index 4bfba3597..a6abede0d 100644 --- a/lib/subghz/protocols/gate_tx.h +++ b/lib/subghz/protocols/gate_tx.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_gate_tx_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderGateTx instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_gate_tx_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderGateTx instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_gate_tx_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_gate_tx_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_gate_tx_serialize( * Deserialize data SubGhzProtocolDecoderGateTx. * @param context Pointer to a SubGhzProtocolDecoderGateTx instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_gate_tx_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/holtek.c b/lib/subghz/protocols/holtek.c index 8aaad3b71..294bd124d 100644 --- a/lib/subghz/protocols/holtek.c +++ b/lib/subghz/protocols/holtek.c @@ -142,31 +142,31 @@ static bool subghz_protocol_encoder_holtek_get_upload(SubGhzProtocolEncoderHolte return true; } -bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderHoltek* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_holtek_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_holtek_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_holtek_get_upload(instance)) break; + if(!subghz_protocol_encoder_holtek_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_holtek_stop(void* context) { @@ -322,7 +322,7 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_holtek_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_holtek_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -331,22 +331,12 @@ bool subghz_protocol_decoder_holtek_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHoltek* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_holtek_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_holtek_const.min_count_bit_for_found); } void subghz_protocol_decoder_holtek_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/holtek.h b/lib/subghz/protocols/holtek.h index 252a26dc7..19081308d 100644 --- a/lib/subghz/protocols/holtek.h +++ b/lib/subghz/protocols/holtek.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_holtek_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderHoltek instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_holtek_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderHoltek instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_holtek_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_holtek_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_holtek_serialize( * Deserialize data SubGhzProtocolDecoderHoltek. * @param context Pointer to a SubGhzProtocolDecoderHoltek instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_holtek_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/holtek_ht12x.c b/lib/subghz/protocols/holtek_ht12x.c index 169387ded..831f824dd 100644 --- a/lib/subghz/protocols/holtek_ht12x.c +++ b/lib/subghz/protocols/holtek_ht12x.c @@ -147,39 +147,41 @@ static bool return true; } -bool subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderHoltek_HT12X* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_holtek_th12x_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_holtek_th12x_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorParserTe; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_holtek_th12x_get_upload(instance)) break; + if(!subghz_protocol_encoder_holtek_th12x_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_holtek_th12x_stop(void* context) { @@ -327,42 +329,45 @@ uint8_t subghz_protocol_decoder_holtek_th12x_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_holtek_th12x_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_holtek_th12x_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderHoltek_HT12X* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { FURI_LOG_E(TAG, "Unable to add TE"); - res = false; + ret = SubGhzProtocolStatusErrorParserTe; } - return res; + return ret; } -bool subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHoltek_HT12X* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_holtek_th12x_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_holtek_th12x_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); + ret = SubGhzProtocolStatusErrorParserTe; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/holtek_ht12x.h b/lib/subghz/protocols/holtek_ht12x.h index 7b5c31dd7..500c061aa 100644 --- a/lib/subghz/protocols/holtek_ht12x.h +++ b/lib/subghz/protocols/holtek_ht12x.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_holtek_th12x_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderHoltek_HT12X instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_holtek_th12x_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_holtek_th12x_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_holtek_th12x_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_holtek_th12x_serialize( * Deserialize data SubGhzProtocolDecoderHoltek_HT12X. * @param context Pointer to a SubGhzProtocolDecoderHoltek_HT12X instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_holtek_th12x_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/honeywell_wdb.c b/lib/subghz/protocols/honeywell_wdb.c index 3b940fc67..7fd8d66d6 100644 --- a/lib/subghz/protocols/honeywell_wdb.c +++ b/lib/subghz/protocols/honeywell_wdb.c @@ -142,33 +142,32 @@ static bool subghz_protocol_encoder_honeywell_wdb_get_upload( return true; } -bool subghz_protocol_encoder_honeywell_wdb_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_honeywell_wdb_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderHoneywell_WDB* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_honeywell_wdb_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_honeywell_wdb_get_upload(instance)) break; + if(!subghz_protocol_encoder_honeywell_wdb_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_honeywell_wdb_stop(void* context) { @@ -345,7 +344,7 @@ uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_honeywell_wdb_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_wdb_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -354,24 +353,15 @@ bool subghz_protocol_decoder_honeywell_wdb_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_honeywell_wdb_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_wdb_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHoneywell_WDB* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_honeywell_wdb_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_honeywell_wdb_const.min_count_bit_for_found); } void subghz_protocol_decoder_honeywell_wdb_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/honeywell_wdb.h b/lib/subghz/protocols/honeywell_wdb.h index 828631837..91728691b 100644 --- a/lib/subghz/protocols/honeywell_wdb.h +++ b/lib/subghz/protocols/honeywell_wdb.h @@ -28,11 +28,10 @@ void subghz_protocol_encoder_honeywell_wdb_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderHoneywell_WDB instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_honeywell_wdb_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_honeywell_wdb_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -86,9 +85,9 @@ uint8_t subghz_protocol_decoder_honeywell_wdb_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_honeywell_wdb_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_honeywell_wdb_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -97,11 +96,10 @@ bool subghz_protocol_decoder_honeywell_wdb_serialize( * Deserialize data SubGhzProtocolDecoderHoneywell_WDB. * @param context Pointer to a SubGhzProtocolDecoderHoneywell_WDB instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_honeywell_wdb_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_honeywell_wdb_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/hormann.c b/lib/subghz/protocols/hormann.c index 67b8cdfca..4c5c68cc4 100644 --- a/lib/subghz/protocols/hormann.c +++ b/lib/subghz/protocols/hormann.c @@ -140,31 +140,31 @@ static bool subghz_protocol_encoder_hormann_get_upload(SubGhzProtocolEncoderHorm return true; } -bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderHormann* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_hormann_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_hormann_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_hormann_get_upload(instance)) break; + if(!subghz_protocol_encoder_hormann_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_hormann_stop(void* context) { @@ -295,7 +295,7 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_hormann_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_hormann_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -304,22 +304,12 @@ bool subghz_protocol_decoder_hormann_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderHormann* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_hormann_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_hormann_const.min_count_bit_for_found); } void subghz_protocol_decoder_hormann_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/hormann.h b/lib/subghz/protocols/hormann.h index 857a50041..8cb45aec3 100644 --- a/lib/subghz/protocols/hormann.h +++ b/lib/subghz/protocols/hormann.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_hormann_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderHormann instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_hormann_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_hormann_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderHormann instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_hormann_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_hormann_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_hormann_serialize( * Deserialize data SubGhzProtocolDecoderHormann. * @param context Pointer to a SubGhzProtocolDecoderHormann instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_hormann_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/ido.c b/lib/subghz/protocols/ido.c index dff9defc0..70870dd93 100644 --- a/lib/subghz/protocols/ido.c +++ b/lib/subghz/protocols/ido.c @@ -180,7 +180,7 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_ido_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_ido_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -189,21 +189,12 @@ bool subghz_protocol_decoder_ido_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderIDo* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != subghz_protocol_ido_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_ido_const.min_count_bit_for_found); } void subghz_protocol_decoder_ido_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/ido.h b/lib/subghz/protocols/ido.h index 634f6ff89..949320246 100644 --- a/lib/subghz/protocols/ido.h +++ b/lib/subghz/protocols/ido.h @@ -50,9 +50,9 @@ uint8_t subghz_protocol_decoder_ido_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderIDo instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_ido_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_ido_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -61,9 +61,10 @@ bool subghz_protocol_decoder_ido_serialize( * Deserialize data SubGhzProtocolDecoderIDo. * @param context Pointer to a SubGhzProtocolDecoderIDo instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_ido_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/intertechno_v3.c b/lib/subghz/protocols/intertechno_v3.c index 2c4e514cc..7fe952995 100644 --- a/lib/subghz/protocols/intertechno_v3.c +++ b/lib/subghz/protocols/intertechno_v3.c @@ -158,34 +158,36 @@ static bool subghz_protocol_encoder_intertechno_v3_get_upload( return true; } -bool subghz_protocol_encoder_intertechno_v3_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_intertechno_v3_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderIntertechno_V3* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit != subghz_protocol_intertechno_v3_const.min_count_bit_for_found) && (instance->generic.data_count_bit != INTERTECHNO_V3_DIMMING_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_intertechno_v3_get_upload(instance)) break; + if(!subghz_protocol_encoder_intertechno_v3_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_intertechno_v3_stop(void* context) { @@ -404,7 +406,7 @@ uint8_t subghz_protocol_decoder_intertechno_v3_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_intertechno_v3_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_intertechno_v3_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -413,23 +415,24 @@ bool subghz_protocol_decoder_intertechno_v3_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_intertechno_v3_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_intertechno_v3_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderIntertechno_V3* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit != subghz_protocol_intertechno_v3_const.min_count_bit_for_found) && (instance->generic.data_count_bit != INTERTECHNO_V3_DIMMING_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/intertechno_v3.h b/lib/subghz/protocols/intertechno_v3.h index ffee14b04..4d1c24cb6 100644 --- a/lib/subghz/protocols/intertechno_v3.h +++ b/lib/subghz/protocols/intertechno_v3.h @@ -28,9 +28,9 @@ void subghz_protocol_encoder_intertechno_v3_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderIntertechno_V3 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return Starus error */ -bool subghz_protocol_encoder_intertechno_v3_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_intertechno_v3_deserialize( void* context, FlipperFormat* flipper_format); @@ -86,9 +86,9 @@ uint8_t subghz_protocol_decoder_intertechno_v3_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return Starus error */ -bool subghz_protocol_decoder_intertechno_v3_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_intertechno_v3_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -97,9 +97,9 @@ bool subghz_protocol_decoder_intertechno_v3_serialize( * Deserialize data SubGhzProtocolDecoderIntertechno_V3. * @param context Pointer to a SubGhzProtocolDecoderIntertechno_V3 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return Starus error */ -bool subghz_protocol_decoder_intertechno_v3_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_intertechno_v3_deserialize( void* context, FlipperFormat* flipper_format); diff --git a/lib/subghz/protocols/keeloq.c b/lib/subghz/protocols/keeloq.c index a58a95ed6..e4731d112 100644 --- a/lib/subghz/protocols/keeloq.c +++ b/lib/subghz/protocols/keeloq.c @@ -312,7 +312,8 @@ bool subghz_protocol_keeloq_create_data( instance->generic.data_count_bit = 64; bool res = subghz_protocol_keeloq_gen_data(instance, btn, false); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -337,7 +338,8 @@ bool subghz_protocol_keeloq_bft_create_data( // roguuemaster don't steal.!!!! bool res = subghz_protocol_keeloq_gen_data(instance, btn, false); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -532,13 +534,17 @@ static bool return true; } -bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderKeeloq* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_keeloq_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(instance->generic.data_count_bit != @@ -578,10 +584,13 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_keeloq_get_upload(instance, instance->generic.btn)) break; - + if(!subghz_protocol_encoder_keeloq_get_upload(instance, instance->generic.btn)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } uint8_t key_data[sizeof(uint64_t)] = {0}; @@ -590,15 +599,14 @@ bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* fl } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); + ret = SubGhzProtocolStatusErrorParserKey; break; } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_keeloq_stop(void* context) { @@ -1172,14 +1180,15 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_keeloq_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_keeloq_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus res = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); subghz_protocol_keeloq_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); @@ -1189,28 +1198,32 @@ bool subghz_protocol_decoder_keeloq_serialize( for(size_t i = 0; i < sizeof(uint32_t); i++) { seed_data[sizeof(uint32_t) - i - 1] = (instance->generic.seed >> i * 8) & 0xFF; } - if(res && !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) { + if((res == SubGhzProtocolStatusOk) && + !flipper_format_write_hex(flipper_format, "Seed", seed_data, sizeof(uint32_t))) { FURI_LOG_E(TAG, "DECODER Serialize: Unable to add Seed"); - res = false; + res = SubGhzProtocolStatusError; } instance->generic.seed = seed_data[0] << 24 | seed_data[1] << 16 | seed_data[2] << 8 | seed_data[3]; } - if(res && !flipper_format_write_string_cstr( - flipper_format, "Manufacture", instance->manufacture_name)) { + if((res == SubGhzProtocolStatusOk) && + !flipper_format_write_string_cstr( + flipper_format, "Manufacture", instance->manufacture_name)) { FURI_LOG_E(TAG, "DECODER Serialize: Unable to add manufacture name"); - res = false; + res = SubGhzProtocolStatusError; } return res; } -bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderKeeloq* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -1244,7 +1257,7 @@ bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* fl break; } - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; diff --git a/lib/subghz/protocols/keeloq.h b/lib/subghz/protocols/keeloq.h index 9ddf17d89..f0715648c 100644 --- a/lib/subghz/protocols/keeloq.h +++ b/lib/subghz/protocols/keeloq.h @@ -81,9 +81,10 @@ bool subghz_protocol_keeloq_bft_create_data( * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderKeeloq instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -137,9 +138,9 @@ uint8_t subghz_protocol_decoder_keeloq_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderKeeloq instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return SubGhzProtocolStatus */ -bool subghz_protocol_decoder_keeloq_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_keeloq_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -148,9 +149,10 @@ bool subghz_protocol_decoder_keeloq_serialize( * Deserialize data SubGhzProtocolDecoderKeeloq. * @param context Pointer to a SubGhzProtocolDecoderKeeloq instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return SubGhzProtocolStatus */ -bool subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_keeloq_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/kia.c b/lib/subghz/protocols/kia.c index a5d9e37ef..1d134f7ba 100644 --- a/lib/subghz/protocols/kia.c +++ b/lib/subghz/protocols/kia.c @@ -230,7 +230,7 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_kia_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_kia_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -239,21 +239,12 @@ bool subghz_protocol_decoder_kia_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderKIA* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != subghz_protocol_kia_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_kia_const.min_count_bit_for_found); } void subghz_protocol_decoder_kia_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/kia.h b/lib/subghz/protocols/kia.h index a9afcf149..749ff8afd 100644 --- a/lib/subghz/protocols/kia.h +++ b/lib/subghz/protocols/kia.h @@ -50,9 +50,9 @@ uint8_t subghz_protocol_decoder_kia_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderKIA instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_kia_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_kia_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -61,9 +61,10 @@ bool subghz_protocol_decoder_kia_serialize( * Deserialize data SubGhzProtocolDecoderKIA. * @param context Pointer to a SubGhzProtocolDecoderKIA instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_kia_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/kinggates_stylo_4k.c b/lib/subghz/protocols/kinggates_stylo_4k.c index 1823a072a..a9127d2b1 100644 --- a/lib/subghz/protocols/kinggates_stylo_4k.c +++ b/lib/subghz/protocols/kinggates_stylo_4k.c @@ -263,14 +263,15 @@ static bool subghz_protocol_encoder_kinggates_stylo_4k_get_upload( return true; } -bool subghz_protocol_encoder_kinggates_stylo_4k_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_kinggates_stylo_4k_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderKingGates_stylo_4k* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -314,7 +315,7 @@ bool subghz_protocol_encoder_kinggates_stylo_4k_deserialize( instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -509,57 +510,57 @@ uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context) &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_kinggates_stylo_4k_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { key_data[sizeof(uint64_t) - i - 1] = (instance->generic.data_2 >> (i * 8)) & 0xFF; } - if(res && !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Data"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } - return res; - - return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return ret; } -bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_kinggates_stylo_4k_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderKingGates_stylo_4k* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_kinggates_stylo_4k_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Missing Data"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } for(uint8_t i = 0; i < sizeof(uint64_t); i++) { instance->generic.data_2 = instance->generic.data_2 << 8 | key_data[i]; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/kinggates_stylo_4k.h b/lib/subghz/protocols/kinggates_stylo_4k.h index 9717f6715..cdefebc84 100644 --- a/lib/subghz/protocols/kinggates_stylo_4k.h +++ b/lib/subghz/protocols/kinggates_stylo_4k.h @@ -29,7 +29,7 @@ void subghz_protocol_encoder_kinggates_stylo_4k_free(void* context); * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_kinggates_stylo_4k_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_kinggates_stylo_4k_deserialize( void* context, FlipperFormat* flipper_format); @@ -85,9 +85,9 @@ uint8_t subghz_protocol_decoder_kinggates_stylo_4k_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_kinggates_stylo_4k_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -96,9 +96,9 @@ bool subghz_protocol_decoder_kinggates_stylo_4k_serialize( * Deserialize data SubGhzProtocolDecoderKingGates_stylo_4k. * @param context Pointer to a SubGhzProtocolDecoderKingGates_stylo_4k instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_kinggates_stylo_4k_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_kinggates_stylo_4k_deserialize( void* context, FlipperFormat* flipper_format); diff --git a/lib/subghz/protocols/linear.c b/lib/subghz/protocols/linear.c index 2fc8b20c8..8d3735796 100644 --- a/lib/subghz/protocols/linear.c +++ b/lib/subghz/protocols/linear.c @@ -147,31 +147,31 @@ static bool subghz_protocol_encoder_linear_get_upload(SubGhzProtocolEncoderLinea return true; } -bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderLinear* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_linear_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_linear_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_linear_get_upload(instance)) break; + if(!subghz_protocol_encoder_linear_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_linear_stop(void* context) { @@ -300,7 +300,7 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_linear_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_linear_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -309,22 +309,12 @@ bool subghz_protocol_decoder_linear_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderLinear* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_linear_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, flipper_format, subghz_protocol_linear_const.min_count_bit_for_found); } void subghz_protocol_decoder_linear_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/linear.h b/lib/subghz/protocols/linear.h index 923337ac2..b692b911c 100644 --- a/lib/subghz/protocols/linear.h +++ b/lib/subghz/protocols/linear.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_linear_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderLinear instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_linear_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_linear_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderLinear instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_linear_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_linear_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_linear_serialize( * Deserialize data SubGhzProtocolDecoderLinear. * @param context Pointer to a SubGhzProtocolDecoderLinear instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_linear_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/linear_delta3.c b/lib/subghz/protocols/linear_delta3.c index 869edac84..97ac5cc5a 100644 --- a/lib/subghz/protocols/linear_delta3.c +++ b/lib/subghz/protocols/linear_delta3.c @@ -150,33 +150,32 @@ static bool return true; } -bool subghz_protocol_encoder_linear_delta3_deserialize( +SubGhzProtocolStatus subghz_protocol_encoder_linear_delta3_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderLinearDelta3* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_linear_delta3_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_linear_delta3_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_linear_delta3_get_upload(instance)) break; + if(!subghz_protocol_encoder_linear_delta3_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_linear_delta3_stop(void* context) { @@ -312,7 +311,7 @@ uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8)); } -bool subghz_protocol_decoder_linear_delta3_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_linear_delta3_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -321,24 +320,15 @@ bool subghz_protocol_decoder_linear_delta3_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_linear_delta3_deserialize( +SubGhzProtocolStatus subghz_protocol_decoder_linear_delta3_deserialize( void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderLinearDelta3* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_linear_delta3_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_linear_delta3_const.min_count_bit_for_found); } void subghz_protocol_decoder_linear_delta3_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/linear_delta3.h b/lib/subghz/protocols/linear_delta3.h index 2f0a32e68..22f6730f4 100644 --- a/lib/subghz/protocols/linear_delta3.h +++ b/lib/subghz/protocols/linear_delta3.h @@ -28,11 +28,10 @@ void subghz_protocol_encoder_linear_delta3_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderLinearDelta3 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_linear_delta3_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_linear_delta3_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -86,9 +85,9 @@ uint8_t subghz_protocol_decoder_linear_delta3_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_linear_delta3_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_linear_delta3_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -97,11 +96,10 @@ bool subghz_protocol_decoder_linear_delta3_serialize( * Deserialize data SubGhzProtocolDecoderLinearDelta3. * @param context Pointer to a SubGhzProtocolDecoderLinearDelta3 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_linear_delta3_deserialize( - void* context, - FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_linear_delta3_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/magellan.c b/lib/subghz/protocols/magellan.c index 67d3fe3d3..2d02a866c 100644 --- a/lib/subghz/protocols/magellan.c +++ b/lib/subghz/protocols/magellan.c @@ -150,31 +150,31 @@ static bool subghz_protocol_encoder_magellan_get_upload(SubGhzProtocolEncoderMag return true; } -bool subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderMagellan* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_magellan_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_magellan_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_magellan_get_upload(instance)) break; + if(!subghz_protocol_encoder_magellan_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_magellan_stop(void* context) { @@ -397,7 +397,7 @@ uint8_t subghz_protocol_decoder_magellan_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_magellan_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_magellan_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -406,22 +406,14 @@ bool subghz_protocol_decoder_magellan_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderMagellan* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_magellan_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_magellan_const.min_count_bit_for_found); } void subghz_protocol_decoder_magellan_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/magellan.h b/lib/subghz/protocols/magellan.h index a179c9cb4..e0fb7ca52 100644 --- a/lib/subghz/protocols/magellan.h +++ b/lib/subghz/protocols/magellan.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_magellan_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderMagellan instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_magellan_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_magellan_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderMagellan instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_magellan_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_magellan_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_magellan_serialize( * Deserialize data SubGhzProtocolDecoderMagellan. * @param context Pointer to a SubGhzProtocolDecoderMagellan instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_magellan_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/marantec.c b/lib/subghz/protocols/marantec.c index d557c29b0..fc4aa0dca 100644 --- a/lib/subghz/protocols/marantec.c +++ b/lib/subghz/protocols/marantec.c @@ -188,18 +188,17 @@ static void subghz_protocol_marantec_remote_controller(SubGhzBlockGeneric* insta instance->serial = ((instance->data >> 12) & 0xFFFFFF00) | ((instance->data >> 8) & 0xFF); } -bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderMarantec* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_marantec_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_marantec_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter @@ -209,11 +208,9 @@ bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* subghz_protocol_marantec_remote_controller(&instance->generic); subghz_protocol_encoder_marantec_get_upload(instance); instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_marantec_stop(void* context) { @@ -346,7 +343,7 @@ uint8_t subghz_protocol_decoder_marantec_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_marantec_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_marantec_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -355,22 +352,14 @@ bool subghz_protocol_decoder_marantec_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderMarantec* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_marantec_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_marantec_const.min_count_bit_for_found); } void subghz_protocol_decoder_marantec_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/marantec.h b/lib/subghz/protocols/marantec.h index e330ccf16..485c563b2 100644 --- a/lib/subghz/protocols/marantec.h +++ b/lib/subghz/protocols/marantec.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_marantec_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderMarantec instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_marantec_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_marantec_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderMarantec instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_marantec_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_marantec_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_marantec_serialize( * Deserialize data SubGhzProtocolDecoderMarantec. * @param context Pointer to a SubGhzProtocolDecoderMarantec instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_marantec_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/megacode.c b/lib/subghz/protocols/megacode.c index 05b5b6894..ba58bc445 100644 --- a/lib/subghz/protocols/megacode.c +++ b/lib/subghz/protocols/megacode.c @@ -175,31 +175,31 @@ static bool subghz_protocol_encoder_megacode_get_upload(SubGhzProtocolEncoderMeg return true; } -bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderMegaCode* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_megacode_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_megacode_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_megacode_get_upload(instance)) break; + if(!subghz_protocol_encoder_megacode_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_megacode_stop(void* context) { @@ -381,7 +381,7 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_megacode_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_megacode_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -390,22 +390,14 @@ bool subghz_protocol_decoder_megacode_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderMegaCode* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_megacode_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_megacode_const.min_count_bit_for_found); } void subghz_protocol_decoder_megacode_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/megacode.h b/lib/subghz/protocols/megacode.h index e31434fa3..616ecdf64 100644 --- a/lib/subghz/protocols/megacode.h +++ b/lib/subghz/protocols/megacode.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_megacode_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderMegaCode instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_megacode_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_megacode_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_megacode_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_megacode_serialize( * Deserialize data SubGhzProtocolDecoderMegaCode. * @param context Pointer to a SubGhzProtocolDecoderMegaCode instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_megacode_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/nero_radio.c b/lib/subghz/protocols/nero_radio.c index c8126b1e1..d7731dca6 100644 --- a/lib/subghz/protocols/nero_radio.c +++ b/lib/subghz/protocols/nero_radio.c @@ -154,31 +154,31 @@ static bool return true; } -bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderNeroRadio* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_nero_radio_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_nero_radio_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_nero_radio_get_upload(instance)) break; + if(!subghz_protocol_encoder_nero_radio_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_nero_radio_stop(void* context) { @@ -343,7 +343,7 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_nero_radio_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nero_radio_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -352,22 +352,14 @@ bool subghz_protocol_decoder_nero_radio_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNeroRadio* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_nero_radio_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_nero_radio_const.min_count_bit_for_found); } void subghz_protocol_decoder_nero_radio_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/nero_radio.h b/lib/subghz/protocols/nero_radio.h index 361da6173..0598aee6c 100644 --- a/lib/subghz/protocols/nero_radio.h +++ b/lib/subghz/protocols/nero_radio.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_nero_radio_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderNeroRadio instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_nero_radio_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderNeroRadio instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nero_radio_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nero_radio_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_nero_radio_serialize( * Deserialize data SubGhzProtocolDecoderNeroRadio. * @param context Pointer to a SubGhzProtocolDecoderNeroRadio instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_nero_radio_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/nero_sketch.c b/lib/subghz/protocols/nero_sketch.c index b124b717b..09cd0255a 100644 --- a/lib/subghz/protocols/nero_sketch.c +++ b/lib/subghz/protocols/nero_sketch.c @@ -148,31 +148,31 @@ static bool return true; } -bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderNeroSketch* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_nero_sketch_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_nero_sketch_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_nero_sketch_get_upload(instance)) break; + if(!subghz_protocol_encoder_nero_sketch_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_nero_sketch_stop(void* context) { @@ -328,7 +328,7 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_nero_sketch_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nero_sketch_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -337,22 +337,14 @@ bool subghz_protocol_decoder_nero_sketch_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNeroSketch* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_nero_sketch_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_nero_sketch_const.min_count_bit_for_found); } void subghz_protocol_decoder_nero_sketch_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/nero_sketch.h b/lib/subghz/protocols/nero_sketch.h index ac87fb00a..b557772d2 100644 --- a/lib/subghz/protocols/nero_sketch.h +++ b/lib/subghz/protocols/nero_sketch.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_nero_sketch_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderNeroSketch instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_nero_sketch_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderNeroSketch instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nero_sketch_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nero_sketch_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_nero_sketch_serialize( * Deserialize data SubGhzProtocolDecoderNeroSketch. * @param context Pointer to a SubGhzProtocolDecoderNeroSketch instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_nero_sketch_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/nice_flo.c b/lib/subghz/protocols/nice_flo.c index a57d5f4da..af81d9f90 100644 --- a/lib/subghz/protocols/nice_flo.c +++ b/lib/subghz/protocols/nice_flo.c @@ -129,13 +129,14 @@ static bool subghz_protocol_encoder_nice_flo_get_upload(SubGhzProtocolEncoderNic return true; } -bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderNiceFlo* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit < @@ -143,19 +144,21 @@ bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* (instance->generic.data_count_bit > 2 * subghz_protocol_nice_flo_const.min_count_bit_for_found)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_nice_flo_get_upload(instance)) break; + if(!subghz_protocol_encoder_nice_flo_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_nice_flo_stop(void* context) { @@ -280,7 +283,7 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_nice_flo_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nice_flo_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -289,12 +292,14 @@ bool subghz_protocol_decoder_nice_flo_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNiceFlo* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit < @@ -302,9 +307,9 @@ bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* (instance->generic.data_count_bit > 2 * subghz_protocol_nice_flo_const.min_count_bit_for_found)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/nice_flo.h b/lib/subghz/protocols/nice_flo.h index e382e6146..9a4b53d12 100644 --- a/lib/subghz/protocols/nice_flo.h +++ b/lib/subghz/protocols/nice_flo.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_nice_flo_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderNiceFlo instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_nice_flo_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nice_flo_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nice_flo_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_nice_flo_serialize( * Deserialize data SubGhzProtocolDecoderNiceFlo. * @param context Pointer to a SubGhzProtocolDecoderNiceFlo instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_nice_flo_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/nice_flor_s.c b/lib/subghz/protocols/nice_flor_s.c index 135bd4972..dbdb4c8b5 100644 --- a/lib/subghz/protocols/nice_flor_s.c +++ b/lib/subghz/protocols/nice_flor_s.c @@ -306,12 +306,14 @@ static void subghz_protocol_encoder_nice_flor_s_get_upload( instance->encoder.size_upload = index; } -bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderNiceFlorS* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -353,7 +355,7 @@ bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperForma instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -573,9 +575,10 @@ bool subghz_protocol_nice_flor_s_create_data( } } - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus res = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - return res; + return res == SubGhzProtocolStatusOk; } void* subghz_protocol_decoder_nice_flor_s_alloc(SubGhzEnvironment* environment) { @@ -765,51 +768,55 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_nice_flor_s_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nice_flor_s_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { - if(res && + if((ret == SubGhzProtocolStatusOk) && !flipper_format_write_uint32(flipper_format, "Data", (uint32_t*)&instance->data, 1)) { FURI_LOG_E(TAG, "Unable to add Data"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } } - return res; + return ret; } -bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderNiceFlorS* instance = context; - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + ret = subghz_block_generic_deserialize(&instance->generic, flipper_format); + if(ret != SubGhzProtocolStatusOk) { break; } if((instance->generic.data_count_bit != subghz_protocol_nice_flor_s_const.min_count_bit_for_found) && (instance->generic.data_count_bit != NICE_ONE_COUNT_BIT)) { FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorValueBitCount; break; } if(instance->generic.data_count_bit == NICE_ONE_COUNT_BIT) { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } uint32_t temp = 0; if(!flipper_format_read_uint32(flipper_format, "Data", (uint32_t*)&temp, 1)) { FURI_LOG_E(TAG, "Missing Data"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } instance->data = (uint64_t)temp; } - - ret = true; } while(false); return ret; } diff --git a/lib/subghz/protocols/nice_flor_s.h b/lib/subghz/protocols/nice_flor_s.h index 3b22db304..679b31812 100644 --- a/lib/subghz/protocols/nice_flor_s.h +++ b/lib/subghz/protocols/nice_flor_s.h @@ -38,7 +38,8 @@ void subghz_protocol_encoder_nice_flor_s_free(void* context); * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -114,9 +115,9 @@ uint8_t subghz_protocol_decoder_nice_flor_s_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderNiceFlorS instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nice_flor_s_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_nice_flor_s_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -125,9 +126,10 @@ bool subghz_protocol_decoder_nice_flor_s_serialize( * Deserialize data SubGhzProtocolDecoderNiceFlorS. * @param context Pointer to a SubGhzProtocolDecoderNiceFlorS instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_nice_flor_s_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/phoenix_v2.c b/lib/subghz/protocols/phoenix_v2.c index b3d6f1e98..4ed9766ef 100644 --- a/lib/subghz/protocols/phoenix_v2.c +++ b/lib/subghz/protocols/phoenix_v2.c @@ -132,31 +132,31 @@ static bool return true; } -bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderPhoenix_V2* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_phoenix_v2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_phoenix_v2_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_phoenix_v2_get_upload(instance)) break; + if(!subghz_protocol_encoder_phoenix_v2_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_phoenix_v2_stop(void* context) { @@ -293,7 +293,7 @@ uint8_t subghz_protocol_decoder_phoenix_v2_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_phoenix_v2_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_phoenix_v2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -302,22 +302,14 @@ bool subghz_protocol_decoder_phoenix_v2_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPhoenix_V2* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_phoenix_v2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_phoenix_v2_const.min_count_bit_for_found); } void subghz_protocol_decoder_phoenix_v2_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/phoenix_v2.h b/lib/subghz/protocols/phoenix_v2.h index 48487535e..0724de1f0 100644 --- a/lib/subghz/protocols/phoenix_v2.h +++ b/lib/subghz/protocols/phoenix_v2.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_phoenix_v2_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderPhoenix_V2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_phoenix_v2_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderPhoenix_V2 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_phoenix_v2_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_phoenix_v2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_phoenix_v2_serialize( * Deserialize data SubGhzProtocolDecoderPhoenix_V2. * @param context Pointer to a SubGhzProtocolDecoderPhoenix_V2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_phoenix_v2_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/power_smart.c b/lib/subghz/protocols/power_smart.c index 1e8d10e95..d03282f73 100644 --- a/lib/subghz/protocols/power_smart.c +++ b/lib/subghz/protocols/power_smart.c @@ -192,18 +192,17 @@ static void subghz_protocol_power_smart_remote_controller(SubGhzBlockGeneric* in instance->cnt = ((instance->data >> 49) & 0x3F); } -bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderPowerSmart* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_power_smart_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_power_smart_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter @@ -213,11 +212,9 @@ bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperForma subghz_protocol_power_smart_remote_controller(&instance->generic); subghz_protocol_encoder_power_smart_get_upload(instance); instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_power_smart_stop(void* context) { @@ -345,7 +342,7 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_power_smart_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_power_smart_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -354,22 +351,14 @@ bool subghz_protocol_decoder_power_smart_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPowerSmart* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_power_smart_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_power_smart_const.min_count_bit_for_found); } void subghz_protocol_decoder_power_smart_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/power_smart.h b/lib/subghz/protocols/power_smart.h index 806729f8e..5687cf8b1 100644 --- a/lib/subghz/protocols/power_smart.h +++ b/lib/subghz/protocols/power_smart.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_power_smart_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderPowerSmart instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_power_smart_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_power_smart_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_power_smart_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_power_smart_serialize( * Deserialize data SubGhzProtocolDecoderPowerSmart. * @param context Pointer to a SubGhzProtocolDecoderPowerSmart instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_power_smart_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/princeton.c b/lib/subghz/protocols/princeton.c index 7fc8f6524..aa15b8b41 100644 --- a/lib/subghz/protocols/princeton.c +++ b/lib/subghz/protocols/princeton.c @@ -141,39 +141,41 @@ static bool return true; } -bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderPrinceton* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_princeton_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_princeton_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorParserTe; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_princeton_get_upload(instance)) break; + if(!subghz_protocol_encoder_princeton_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_princeton_stop(void* context) { @@ -308,46 +310,48 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_princeton_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_princeton_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { FURI_LOG_E(TAG, "Unable to add TE"); - res = false; + ret = SubGhzProtocolStatusErrorParserTe; } - return res; + return ret; } -bool subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderPrinceton* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_princeton_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_princeton_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); + ret = SubGhzProtocolStatusErrorParserTe; break; } - res = true; } while(false); - return res; + return ret; } void subghz_protocol_decoder_princeton_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/princeton.h b/lib/subghz/protocols/princeton.h index a2a11292e..7c775292d 100644 --- a/lib/subghz/protocols/princeton.h +++ b/lib/subghz/protocols/princeton.h @@ -32,9 +32,10 @@ void subghz_protocol_encoder_princeton_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderPrinceton instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_princeton_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -88,9 +89,9 @@ uint8_t subghz_protocol_decoder_princeton_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderPrinceton instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_princeton_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_princeton_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -99,9 +100,10 @@ bool subghz_protocol_decoder_princeton_serialize( * Deserialize data SubGhzProtocolDecoderPrinceton. * @param context Pointer to a SubGhzProtocolDecoderPrinceton instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_princeton_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/raw.c b/lib/subghz/protocols/raw.c index 01a229047..eaad78b91 100644 --- a/lib/subghz/protocols/raw.c +++ b/lib/subghz/protocols/raw.c @@ -259,12 +259,13 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati } } -bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); UNUSED(context); UNUSED(flipper_format); //ToDo stub, for backwards compatibility - return true; + return SubGhzProtocolStatusOk; } void subghz_protocol_decoder_raw_get_string(void* context, FuriString* output) { @@ -342,25 +343,32 @@ void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* } while(false); } -bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderRAW* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; FuriString* temp_str; temp_str = furi_string_alloc(); do { if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + res = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_string(flipper_format, "File_name", temp_str)) { FURI_LOG_E(TAG, "Missing File_name"); + res = SubGhzProtocolStatusErrorParserOthers; break; } furi_string_set(instance->file_name, temp_str); - res = subghz_protocol_encoder_raw_worker_init(instance); + if(!subghz_protocol_encoder_raw_worker_init(instance)) { + res = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } + res = SubGhzProtocolStatusOk; } while(false); furi_string_free(temp_str); return res; diff --git a/lib/subghz/protocols/raw.h b/lib/subghz/protocols/raw.h index 44c7faec5..4f67a4e2f 100644 --- a/lib/subghz/protocols/raw.h +++ b/lib/subghz/protocols/raw.h @@ -73,9 +73,10 @@ void subghz_protocol_decoder_raw_feed(void* context, bool level, uint32_t durati * Deserialize data SubGhzProtocolDecoderRAW. * @param context Pointer to a SubGhzProtocolDecoderRAW instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_raw_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. @@ -132,9 +133,10 @@ void subghz_protocol_raw_gen_fff_data(FlipperFormat* flipper_format, const char* * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderRAW instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_raw_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting the level and duration of the upload to be loaded into DMA. diff --git a/lib/subghz/protocols/scher_khan.c b/lib/subghz/protocols/scher_khan.c index a5de7d04b..b68e3c869 100644 --- a/lib/subghz/protocols/scher_khan.c +++ b/lib/subghz/protocols/scher_khan.c @@ -249,7 +249,7 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_scher_khan_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_scher_khan_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -258,7 +258,8 @@ bool subghz_protocol_decoder_scher_khan_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderScherKhan* instance = context; return subghz_block_generic_deserialize(&instance->generic, flipper_format); diff --git a/lib/subghz/protocols/scher_khan.h b/lib/subghz/protocols/scher_khan.h index b7e84ea1f..58545069c 100644 --- a/lib/subghz/protocols/scher_khan.h +++ b/lib/subghz/protocols/scher_khan.h @@ -50,9 +50,9 @@ uint8_t subghz_protocol_decoder_scher_khan_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderScherKhan instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_scher_khan_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_scher_khan_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -61,9 +61,10 @@ bool subghz_protocol_decoder_scher_khan_serialize( * Deserialize data SubGhzProtocolDecoderScherKhan. * @param context Pointer to a SubGhzProtocolDecoderScherKhan instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_scher_khan_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/secplus_v1.c b/lib/subghz/protocols/secplus_v1.c index 3ef95db36..55373cc21 100644 --- a/lib/subghz/protocols/secplus_v1.c +++ b/lib/subghz/protocols/secplus_v1.c @@ -264,18 +264,17 @@ static bool subghz_protocol_secplus_v1_encode(SubGhzProtocolEncoderSecPlus_v1* i return true; } -bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderSecPlus_v1* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } //optional parameter parameter @@ -283,9 +282,12 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); if(!subghz_protocol_secplus_v1_encode(instance)) { + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!subghz_protocol_encoder_secplus_v1_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + ; break; } @@ -295,15 +297,14 @@ bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); + ret = SubGhzProtocolStatusErrorParserKey; break; } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_secplus_v1_stop(void* context) { @@ -516,7 +517,7 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_secplus_v1_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_secplus_v1_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -525,22 +526,14 @@ bool subghz_protocol_decoder_secplus_v1_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v1* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + 2 * subghz_protocol_secplus_v1_const.min_count_bit_for_found); } bool subghz_protocol_secplus_v1_check_fixed(uint32_t fixed) { diff --git a/lib/subghz/protocols/secplus_v1.h b/lib/subghz/protocols/secplus_v1.h index 99480b62b..3490f2ca5 100644 --- a/lib/subghz/protocols/secplus_v1.h +++ b/lib/subghz/protocols/secplus_v1.h @@ -27,9 +27,10 @@ void subghz_protocol_encoder_secplus_v1_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderSecPlus_v1 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -83,9 +84,9 @@ uint8_t subghz_protocol_decoder_secplus_v1_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_secplus_v1_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_secplus_v1_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -94,9 +95,10 @@ bool subghz_protocol_decoder_secplus_v1_serialize( * Deserialize data SubGhzProtocolDecoderSecPlus_v1. * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v1 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_secplus_v1_deserialize(void* context, FlipperFormat* flipper_format); /** * Validation of fixed parts SubGhzProtocolDecoderSecPlus_v1. diff --git a/lib/subghz/protocols/secplus_v2.c b/lib/subghz/protocols/secplus_v2.c index 9f8c31654..a55930552 100644 --- a/lib/subghz/protocols/secplus_v2.c +++ b/lib/subghz/protocols/secplus_v2.c @@ -504,24 +504,24 @@ static void instance->encoder.size_upload = index; } -bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderSecPlus_v2* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_secplus_v2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_secplus_v2_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex( flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Secplus_packet_1"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } for(uint8_t i = 0; i < sizeof(uint64_t); i++) { @@ -542,6 +542,7 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat } if(!flipper_format_update_hex(flipper_format, "Key", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Key"); + ret = SubGhzProtocolStatusErrorParserKey; break; } @@ -551,15 +552,14 @@ bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat if(!flipper_format_update_hex( flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Secplus_packet_1"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_secplus_v2_stop(void* context) { @@ -600,19 +600,20 @@ bool subghz_protocol_secplus_v2_create_data( instance->generic.data_count_bit = (uint8_t)subghz_protocol_secplus_v2_const.min_count_bit_for_found; subghz_protocol_secplus_v2_encode(instance); - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus res = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> (i * 8)) & 0xFF; } - if(res && + if((res == SubGhzProtocolStatusOk) && !flipper_format_write_hex(flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Secplus_packet_1"); - res = false; + res = SubGhzProtocolStatusError; } - return res; + return res == SubGhzProtocolStatusOk; } void* subghz_protocol_decoder_secplus_v2_alloc(SubGhzEnvironment* environment) { @@ -755,58 +756,59 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_secplus_v2_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_secplus_v2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v2* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); uint8_t key_data[sizeof(uint64_t)] = {0}; for(size_t i = 0; i < sizeof(uint64_t); i++) { key_data[sizeof(uint64_t) - i - 1] = (instance->secplus_packet_1 >> (i * 8)) & 0xFF; } - if(res && + if((ret == SubGhzProtocolStatusOk) && !flipper_format_write_hex(flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Unable to add Secplus_packet_1"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } - return res; + return ret; } -bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSecPlus_v2* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_secplus_v2_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_secplus_v2_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } uint8_t key_data[sizeof(uint64_t)] = {0}; if(!flipper_format_read_hex( flipper_format, "Secplus_packet_1", key_data, sizeof(uint64_t))) { FURI_LOG_E(TAG, "Missing Secplus_packet_1"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } for(uint8_t i = 0; i < sizeof(uint64_t); i++) { instance->secplus_packet_1 = instance->secplus_packet_1 << 8 | key_data[i]; } - res = true; } while(false); - return res; + return ret; } void subghz_protocol_decoder_secplus_v2_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/secplus_v2.h b/lib/subghz/protocols/secplus_v2.h index bea8cdb5d..0eea732af 100644 --- a/lib/subghz/protocols/secplus_v2.h +++ b/lib/subghz/protocols/secplus_v2.h @@ -27,9 +27,10 @@ void subghz_protocol_encoder_secplus_v2_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderSecPlus_v2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -102,9 +103,9 @@ uint8_t subghz_protocol_decoder_secplus_v2_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_secplus_v2_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_secplus_v2_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -113,9 +114,10 @@ bool subghz_protocol_decoder_secplus_v2_serialize( * Deserialize data SubGhzProtocolDecoderSecPlus_v2. * @param context Pointer to a SubGhzProtocolDecoderSecPlus_v2 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_secplus_v2_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/smc5326.c b/lib/subghz/protocols/smc5326.c index 9c9b5d4fd..bfb36b76a 100644 --- a/lib/subghz/protocols/smc5326.c +++ b/lib/subghz/protocols/smc5326.c @@ -155,39 +155,41 @@ static bool subghz_protocol_encoder_smc5326_get_upload(SubGhzProtocolEncoderSMC5 return true; } -bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderSMC5326* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_smc5326_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_smc5326_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = SubGhzProtocolStatusErrorParserTe; break; } //optional parameter parameter flipper_format_read_uint32( flipper_format, "Repeat", (uint32_t*)&instance->encoder.repeat, 1); - if(!subghz_protocol_encoder_smc5326_get_upload(instance)) break; + if(!subghz_protocol_encoder_smc5326_get_upload(instance)) { + ret = SubGhzProtocolStatusErrorEncoderGetUpload; + break; + } instance->encoder.is_running = true; - - res = true; } while(false); - return res; + return ret; } void subghz_protocol_encoder_smc5326_stop(void* context) { @@ -313,46 +315,48 @@ uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_smc5326_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_smc5326_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderSMC5326* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32(flipper_format, "TE", &instance->te, 1)) { FURI_LOG_E(TAG, "Unable to add TE"); - res = false; + ret = SubGhzProtocolStatusErrorParserTe; } - return res; + return ret; } -bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSMC5326* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_smc5326_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_smc5326_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32(flipper_format, "TE", (uint32_t*)&instance->te, 1)) { FURI_LOG_E(TAG, "Missing TE"); + ret = SubGhzProtocolStatusErrorParserTe; break; } - res = true; } while(false); - return res; + return ret; } static void subghz_protocol_smc5326_get_event_serialize(uint8_t event, FuriString* output) { diff --git a/lib/subghz/protocols/smc5326.h b/lib/subghz/protocols/smc5326.h index ddc954bd5..911226cf9 100644 --- a/lib/subghz/protocols/smc5326.h +++ b/lib/subghz/protocols/smc5326.h @@ -28,9 +28,10 @@ void subghz_protocol_encoder_smc5326_free(void* context); * Deserialize and generating an upload to send. * @param context Pointer to a SubGhzProtocolEncoderSMC5326 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -84,9 +85,9 @@ uint8_t subghz_protocol_decoder_smc5326_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_smc5326_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_smc5326_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -95,9 +96,10 @@ bool subghz_protocol_decoder_smc5326_serialize( * Deserialize data SubGhzProtocolDecoderSMC5326. * @param context Pointer to a SubGhzProtocolDecoderSMC5326 instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_smc5326_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/somfy_keytis.c b/lib/subghz/protocols/somfy_keytis.c index 1bcd89f42..dd860a61d 100644 --- a/lib/subghz/protocols/somfy_keytis.c +++ b/lib/subghz/protocols/somfy_keytis.c @@ -192,7 +192,8 @@ bool subghz_protocol_somfy_keytis_create_data( instance->generic.data_count_bit = 80; bool res = subghz_protocol_somfy_keytis_gen_data(instance, btn); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -390,12 +391,14 @@ static bool subghz_protocol_encoder_somfy_keytis_get_upload( return true; } -bool subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderSomfyKeytis* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -421,7 +424,7 @@ bool subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperForm instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -729,37 +732,39 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_somfy_keytis_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_somfy_keytis_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { furi_assert(context); SubGhzProtocolDecoderSomfyKeytis* instance = context; - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_uint32( - flipper_format, "Duration_Counter", &instance->press_duration_counter, 1)) { + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_uint32( + flipper_format, "Duration_Counter", &instance->press_duration_counter, 1)) { FURI_LOG_E(TAG, "Unable to add Duration_Counter"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } - return res; + return ret; } -bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSomfyKeytis* instance = context; - bool res = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - FURI_LOG_E(TAG, "Deserialize error"); - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_somfy_keytis_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); + ret = subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_somfy_keytis_const.min_count_bit_for_found); + if(ret != SubGhzProtocolStatusOk) { break; } if(!flipper_format_rewind(flipper_format)) { FURI_LOG_E(TAG, "Rewind error"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } if(!flipper_format_read_uint32( @@ -768,12 +773,12 @@ bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperForm (uint32_t*)&instance->press_duration_counter, 1)) { FURI_LOG_E(TAG, "Missing Duration_Counter"); + ret = SubGhzProtocolStatusErrorParserOthers; break; } - res = true; } while(false); - return res; + return ret; } void subghz_protocol_decoder_somfy_keytis_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/somfy_keytis.h b/lib/subghz/protocols/somfy_keytis.h index b08da3641..0e339c889 100644 --- a/lib/subghz/protocols/somfy_keytis.h +++ b/lib/subghz/protocols/somfy_keytis.h @@ -48,7 +48,8 @@ bool subghz_protocol_somfy_keytis_create_data( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -102,9 +103,9 @@ uint8_t subghz_protocol_decoder_somfy_keytis_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderSomfyKeytis instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_somfy_keytis_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_somfy_keytis_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -113,9 +114,10 @@ bool subghz_protocol_decoder_somfy_keytis_serialize( * Deserialize data SubGhzProtocolDecoderSomfyKeytis. * @param context Pointer to a SubGhzProtocolDecoderSomfyKeytis instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_somfy_keytis_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/somfy_telis.c b/lib/subghz/protocols/somfy_telis.c index 5d6b1c6f3..0294a1922 100644 --- a/lib/subghz/protocols/somfy_telis.c +++ b/lib/subghz/protocols/somfy_telis.c @@ -252,7 +252,8 @@ bool subghz_protocol_somfy_telis_create_data( instance->generic.data_count_bit = 56; bool res = subghz_protocol_somfy_telis_gen_data(instance, btn, true); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -390,12 +391,14 @@ static bool subghz_protocol_encoder_somfy_telis_get_upload( return true; } -bool subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderSomfyTelis* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -421,7 +424,7 @@ bool subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperForma instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -718,7 +721,7 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_somfy_telis_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_somfy_telis_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -727,22 +730,14 @@ bool subghz_protocol_decoder_somfy_telis_serialize( return subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } -bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderSomfyTelis* instance = context; - bool ret = false; - do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { - break; - } - if(instance->generic.data_count_bit != - subghz_protocol_somfy_telis_const.min_count_bit_for_found) { - FURI_LOG_E(TAG, "Wrong number of bits in key"); - break; - } - ret = true; - } while(false); - return ret; + return subghz_block_generic_deserialize_check_count_bit( + &instance->generic, + flipper_format, + subghz_protocol_somfy_telis_const.min_count_bit_for_found); } void subghz_protocol_decoder_somfy_telis_get_string(void* context, FuriString* output) { diff --git a/lib/subghz/protocols/somfy_telis.h b/lib/subghz/protocols/somfy_telis.h index bca58b64b..36f6c70b5 100644 --- a/lib/subghz/protocols/somfy_telis.h +++ b/lib/subghz/protocols/somfy_telis.h @@ -56,7 +56,8 @@ bool subghz_protocol_somfy_telis_create_data( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -110,9 +111,9 @@ uint8_t subghz_protocol_decoder_somfy_telis_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderSomfyTelis instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_somfy_telis_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_somfy_telis_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -121,9 +122,10 @@ bool subghz_protocol_decoder_somfy_telis_serialize( * Deserialize data SubGhzProtocolDecoderSomfyTelis. * @param context Pointer to a SubGhzProtocolDecoderSomfyTelis instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_somfy_telis_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/protocols/star_line.c b/lib/subghz/protocols/star_line.c index e09e7e951..5f96d3fcb 100644 --- a/lib/subghz/protocols/star_line.c +++ b/lib/subghz/protocols/star_line.c @@ -221,7 +221,8 @@ bool subghz_protocol_star_line_create_data( instance->generic.data_count_bit = 64; bool res = subghz_protocol_star_line_gen_data(instance, btn); if(res) { - res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + return SubGhzProtocolStatusOk == + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); } return res; } @@ -280,12 +281,14 @@ static bool subghz_protocol_encoder_star_line_get_upload( return true; } -bool subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolEncoderStarLine* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -323,7 +326,7 @@ bool subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* instance->encoder.is_running = true; - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; @@ -702,7 +705,7 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context) { &instance->decoder, (instance->decoder.decode_count_bit / 8) + 1); } -bool subghz_protocol_decoder_star_line_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_star_line_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset) { @@ -710,27 +713,32 @@ bool subghz_protocol_decoder_star_line_serialize( SubGhzProtocolDecoderStarLine* instance = context; subghz_protocol_star_line_check_remote_controller( &instance->generic, instance->keystore, &instance->manufacture_name); - bool res = subghz_block_generic_serialize(&instance->generic, flipper_format, preset); + SubGhzProtocolStatus ret = + subghz_block_generic_serialize(&instance->generic, flipper_format, preset); - if(res && !flipper_format_write_string_cstr( - flipper_format, "Manufacture", instance->manufacture_name)) { + if((ret == SubGhzProtocolStatusOk) && + !flipper_format_write_string_cstr( + flipper_format, "Manufacture", instance->manufacture_name)) { FURI_LOG_E(TAG, "Unable to add manufacture name"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } - if(res && instance->generic.data_count_bit != - subghz_protocol_star_line_const.min_count_bit_for_found) { + if((ret == SubGhzProtocolStatusOk) && + instance->generic.data_count_bit != + subghz_protocol_star_line_const.min_count_bit_for_found) { FURI_LOG_E(TAG, "Wrong number of bits in key"); - res = false; + ret = SubGhzProtocolStatusErrorParserOthers; } - return res; + return ret; } -bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* flipper_format) { furi_assert(context); SubGhzProtocolDecoderStarLine* instance = context; - bool res = false; + SubGhzProtocolStatus res = SubGhzProtocolStatusError; do { - if(!subghz_block_generic_deserialize(&instance->generic, flipper_format)) { + if(SubGhzProtocolStatusOk != + subghz_block_generic_deserialize(&instance->generic, flipper_format)) { FURI_LOG_E(TAG, "Deserialize error"); break; } @@ -744,7 +752,7 @@ bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* FURI_LOG_D(TAG, "DECODER: Missing Manufacture"); } - res = true; + res = SubGhzProtocolStatusOk; } while(false); return res; diff --git a/lib/subghz/protocols/star_line.h b/lib/subghz/protocols/star_line.h index e8873d41a..901b82f7c 100644 --- a/lib/subghz/protocols/star_line.h +++ b/lib/subghz/protocols/star_line.h @@ -54,7 +54,8 @@ bool subghz_protocol_star_line_create_data( * @param flipper_format Pointer to a FlipperFormat instance * @return true On success */ -bool subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_encoder_star_line_deserialize(void* context, FlipperFormat* flipper_format); /** * Forced transmission stop. @@ -108,9 +109,9 @@ uint8_t subghz_protocol_decoder_star_line_get_hash_data(void* context); * @param context Pointer to a SubGhzProtocolDecoderStarLine instance * @param flipper_format Pointer to a FlipperFormat instance * @param preset The modulation on which the signal was received, SubGhzRadioPreset - * @return true On success + * @return status */ -bool subghz_protocol_decoder_star_line_serialize( +SubGhzProtocolStatus subghz_protocol_decoder_star_line_serialize( void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); @@ -119,9 +120,10 @@ bool subghz_protocol_decoder_star_line_serialize( * Deserialize data SubGhzProtocolDecoderStarLine. * @param context Pointer to a SubGhzProtocolDecoderStarLine instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_protocol_decoder_star_line_deserialize(void* context, FlipperFormat* flipper_format); /** * Getting a textual representation of the received data. diff --git a/lib/subghz/transmitter.c b/lib/subghz/transmitter.c index 8507ee054..81be143b5 100644 --- a/lib/subghz/transmitter.c +++ b/lib/subghz/transmitter.c @@ -47,9 +47,10 @@ bool subghz_transmitter_stop(SubGhzTransmitter* instance) { return ret; } -bool subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* flipper_format) { +SubGhzProtocolStatus + subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* flipper_format) { furi_assert(instance); - bool ret = false; + SubGhzProtocolStatus ret = SubGhzProtocolStatusError; if(instance->protocol && instance->protocol->encoder && instance->protocol->encoder->deserialize) { ret = diff --git a/lib/subghz/transmitter.h b/lib/subghz/transmitter.h index cce98a463..a1c4cda08 100644 --- a/lib/subghz/transmitter.h +++ b/lib/subghz/transmitter.h @@ -39,9 +39,10 @@ bool subghz_transmitter_stop(SubGhzTransmitter* instance); * Deserialize and generating an upload to send. * @param instance Pointer to a SubGhzTransmitter instance * @param flipper_format Pointer to a FlipperFormat instance - * @return true On success + * @return status */ -bool subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* flipper_format); +SubGhzProtocolStatus + subghz_transmitter_deserialize(SubGhzTransmitter* instance, FlipperFormat* flipper_format); /** * Getting the level and duration of the upload to be loaded into DMA. diff --git a/lib/subghz/types.h b/lib/subghz/types.h index 9d121dc3c..e0ed95654 100644 --- a/lib/subghz/types.h +++ b/lib/subghz/types.h @@ -29,14 +29,36 @@ typedef struct { size_t data_size; } SubGhzRadioPreset; +typedef enum { + SubGhzProtocolStatusOk = 0, + // Errors + SubGhzProtocolStatusError = (-1), ///< General unclassified error + // Serialize/De-serialize + SubGhzProtocolStatusErrorParserHeader = (-2), ///< Missing or invalid file header + SubGhzProtocolStatusErrorParserFrequency = (-3), ///< Missing `Frequency` + SubGhzProtocolStatusErrorParserPreset = (-4), ///< Missing `Preset` + SubGhzProtocolStatusErrorParserCustomPreset = (-5), ///< Missing `Custom_preset_module` + SubGhzProtocolStatusErrorParserProtocolName = (-6), ///< Missing `Protocol` name + SubGhzProtocolStatusErrorParserBitCount = (-7), ///< Missing `Bit` + SubGhzProtocolStatusErrorParserKey = (-8), ///< Missing `Key` + SubGhzProtocolStatusErrorParserTe = (-9), ///< Missing `Te` + SubGhzProtocolStatusErrorParserOthers = (-10), ///< Missing some other mandatory keys + // Invalid data + SubGhzProtocolStatusErrorValueBitCount = (-11), ///< Invalid bit count value + // Encoder issue + SubGhzProtocolStatusErrorEncoderGetUpload = (-12), ///< Payload encoder failure + // Special Values + SubGhzProtocolStatusReserved = 0x7FFFFFFF, ///< Prevents enum down-size compiler optimization. +} SubGhzProtocolStatus; + // Allocator and Deallocator typedef void* (*SubGhzAlloc)(SubGhzEnvironment* environment); typedef void (*SubGhzFree)(void* context); // Serialize and Deserialize -typedef bool ( +typedef SubGhzProtocolStatus ( *SubGhzSerialize)(void* context, FlipperFormat* flipper_format, SubGhzRadioPreset* preset); -typedef bool (*SubGhzDeserialize)(void* context, FlipperFormat* flipper_format); +typedef SubGhzProtocolStatus (*SubGhzDeserialize)(void* context, FlipperFormat* flipper_format); // Decoder specific typedef void (*SubGhzDecoderFeed)(void* decoder, bool level, uint32_t duration); diff --git a/lib/toolbox/SConscript b/lib/toolbox/SConscript index da6c1115c..c01e32a6b 100644 --- a/lib/toolbox/SConscript +++ b/lib/toolbox/SConscript @@ -27,6 +27,7 @@ env.Append( File("stream/string_stream.h"), File("stream/buffered_file_stream.h"), File("protocols/protocol_dict.h"), + File("pretty_format.h"), ], ) diff --git a/lib/toolbox/dir_walk.c b/lib/toolbox/dir_walk.c index e5a3cf32b..509ceb5b4 100644 --- a/lib/toolbox/dir_walk.c +++ b/lib/toolbox/dir_walk.c @@ -83,7 +83,7 @@ static DirWalkResult end = true; } - if((info.flags & FSF_DIRECTORY) && dir_walk->recursive) { + if(file_info_is_dir(&info) && dir_walk->recursive) { // step into DirIndexList_push_back(dir_walk->index_list, dir_walk->current_index); dir_walk->current_index = 0; diff --git a/lib/toolbox/pretty_format.c b/lib/toolbox/pretty_format.c new file mode 100644 index 000000000..d5ba10381 --- /dev/null +++ b/lib/toolbox/pretty_format.c @@ -0,0 +1,60 @@ +#include "pretty_format.h" + +#include +#include + +#define PRETTY_FORMAT_MAX_CANONICAL_DATA_SIZE 256U + +void pretty_format_bytes_hex_canonical( + FuriString* result, + size_t num_places, + const char* line_prefix, + const uint8_t* data, + size_t data_size) { + furi_assert(data); + + bool is_truncated = false; + + if(data_size > PRETTY_FORMAT_MAX_CANONICAL_DATA_SIZE) { + data_size = PRETTY_FORMAT_MAX_CANONICAL_DATA_SIZE; + is_truncated = true; + } + + /* Only num_places byte(s) can be on a single line, therefore: */ + const size_t line_count = + data_size / num_places + (data_size % num_places != 0 ? 1 : 0) + (is_truncated ? 2 : 0); + /* Line length = Prefix length + 3 * num_places (2 hex digits + space) + 1 * num_places + + + 1 pipe character + 1 newline character */ + const size_t line_length = (line_prefix ? strlen(line_prefix) : 0) + 4 * num_places + 2; + + /* Reserve memory in adance in order to avoid unnecessary reallocs */ + furi_string_reset(result); + furi_string_reserve(result, line_count * line_length); + + for(size_t i = 0; i < data_size; i += num_places) { + if(line_prefix) { + furi_string_cat(result, line_prefix); + } + + const size_t begin_idx = i; + const size_t end_idx = MIN(i + num_places, data_size); + + for(size_t j = begin_idx; j < end_idx; j++) { + furi_string_cat_printf(result, "%02X ", data[j]); + } + + furi_string_push_back(result, '|'); + + for(size_t j = begin_idx; j < end_idx; j++) { + const char c = data[j]; + const char sep = ((j < end_idx - 1) ? ' ' : '\n'); + const char* fmt = ((j < data_size - 1) ? "%c%c" : "%c"); + furi_string_cat_printf(result, fmt, (c > 0x1f && c < 0x7f) ? c : '.', sep); + } + } + + if(is_truncated) { + furi_string_cat_printf( + result, "\n(Data is too big. Showing only the first %zu bytes.)", data_size); + } +} diff --git a/lib/toolbox/pretty_format.h b/lib/toolbox/pretty_format.h new file mode 100644 index 000000000..860528e4c --- /dev/null +++ b/lib/toolbox/pretty_format.h @@ -0,0 +1,29 @@ +#pragma once + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define PRETTY_FORMAT_FONT_BOLD "\e#" +#define PRETTY_FORMAT_FONT_MONOSPACE "\e*" + +/** + * Format a data buffer as a canonical HEX dump + * @param [out] result pointer to the output string (must be initialised) + * @param [in] num_places the number of bytes on one line (both as HEX and ASCII) + * @param [in] line_prefix if not NULL, prepend this string to each line + * @param [in] data pointer to the input data buffer + * @param [in] data_size input data size + */ +void pretty_format_bytes_hex_canonical( + FuriString* result, + size_t num_places, + const char* line_prefix, + const uint8_t* data, + size_t data_size); + +#ifdef __cplusplus +} +#endif diff --git a/lib/toolbox/stream/buffered_file_stream.c b/lib/toolbox/stream/buffered_file_stream.c index 3b20a391c..3b485e80d 100644 --- a/lib/toolbox/stream/buffered_file_stream.c +++ b/lib/toolbox/stream/buffered_file_stream.c @@ -95,6 +95,7 @@ FS_Error buffered_file_stream_get_error(Stream* _stream) { static void buffered_file_stream_free(BufferedFileStream* stream) { furi_assert(stream); + buffered_file_stream_sync((Stream*)stream); stream_free(stream->file_stream); stream_cache_free(stream->cache); free(stream); diff --git a/lib/toolbox/tar/tar_archive.c b/lib/toolbox/tar/tar_archive.c index 01969b471..fcfc22a70 100644 --- a/lib/toolbox/tar/tar_archive.c +++ b/lib/toolbox/tar/tar_archive.c @@ -344,7 +344,7 @@ bool tar_archive_add_dir(TarArchive* archive, const char* fs_full_path, const ch furi_string_set(element_name, name); } - if(file_info.flags & FSF_DIRECTORY) { + if(file_info_is_dir(&file_info)) { success = tar_archive_dir_add_element(archive, furi_string_get_cstr(element_name)) && tar_archive_add_dir( diff --git a/scripts/fbt/appmanifest.py b/scripts/fbt/appmanifest.py index 7ee86de02..624113101 100644 --- a/scripts/fbt/appmanifest.py +++ b/scripts/fbt/appmanifest.py @@ -322,6 +322,7 @@ class ApplicationsCGenerator: return f""" {{.app = {app.entry_point}, .name = "{app.name}", + .appid = "{app.appid}", .stack_size = {app.stack_size}, .icon = {f"&{app.icon}" if app.icon else "NULL"}, .flags = {'|'.join(f"FlipperApplicationFlag{flag}" for flag in app.flags)} }}"""