mirror of
https://github.com/Next-Flip/Momentum-Firmware.git
synced 2026-05-14 22:28:36 -07:00
Merge branch 'dev' of https://github.com/DarkFlippers/unleashed-firmware into xfw-dev
This commit is contained in:
@@ -44,3 +44,6 @@
|
|||||||
|
|
||||||
# Functions that always return the same error code
|
# Functions that always return the same error code
|
||||||
//-V:picopass_device_decrypt:1048
|
//-V:picopass_device_decrypt:1048
|
||||||
|
|
||||||
|
# Examples
|
||||||
|
//V_EXCLUDE_PATH applications/examples/
|
||||||
@@ -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;
|
size_t size = strlen(clean_dir) + strlen(name) + 1 + 1;
|
||||||
char* fullname = malloc(size);
|
char* fullname = malloc(size);
|
||||||
snprintf(fullname, size, "%s/%s", clean_dir, name);
|
snprintf(fullname, size, "%s/%s", clean_dir, name);
|
||||||
if(fileinfo.flags & FSF_DIRECTORY) {
|
if(file_info_is_dir(&fileinfo)) {
|
||||||
clean_directory(fs_api, fullname);
|
clean_directory(fs_api, fullname);
|
||||||
}
|
}
|
||||||
FS_Error error = storage_common_remove(fs_api, fullname);
|
FS_Error error = storage_common_remove(fs_api, fullname);
|
||||||
@@ -608,8 +608,7 @@ static void test_rpc_storage_list_create_expected_list(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if(path_contains_only_ascii(name)) {
|
if(path_contains_only_ascii(name)) {
|
||||||
list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ?
|
list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR :
|
||||||
PB_Storage_File_FileType_DIR :
|
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
list->file[i].size = fileinfo.size;
|
list->file[i].size = fileinfo.size;
|
||||||
list->file[i].data = NULL;
|
list->file[i].data = NULL;
|
||||||
@@ -873,7 +872,7 @@ static void test_rpc_storage_stat_run(const char* path, uint32_t command_id) {
|
|||||||
if(error == FSE_OK) {
|
if(error == FSE_OK) {
|
||||||
response->which_content = PB_Main_storage_stat_response_tag;
|
response->which_content = PB_Main_storage_stat_response_tag;
|
||||||
response->content.storage_stat_response.has_file = true;
|
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_DIR :
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
response->content.storage_stat_response.file.size = fileinfo.size;
|
response->content.storage_stat_response.file.size = fileinfo.size;
|
||||||
|
|||||||
@@ -179,7 +179,7 @@ MU_TEST_1(test_dirwalk_full, Storage* storage) {
|
|||||||
|
|
||||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
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);
|
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) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
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);
|
dir_walk_free(dir_walk);
|
||||||
@@ -219,7 +219,7 @@ static bool test_dirwalk_filter_no_folder_ext(const char* name, FileInfo* filein
|
|||||||
UNUSED(ctx);
|
UNUSED(ctx);
|
||||||
|
|
||||||
// only files
|
// only files
|
||||||
if(!(fileinfo->flags & FSF_DIRECTORY)) {
|
if(!file_info_is_dir(fileinfo)) {
|
||||||
// with ".test" in name
|
// with ".test" in name
|
||||||
if(strstr(name, ".test") != NULL) {
|
if(strstr(name, ".test") != NULL) {
|
||||||
return true;
|
return true;
|
||||||
@@ -243,7 +243,7 @@ MU_TEST_1(test_dirwalk_filter, Storage* storage) {
|
|||||||
|
|
||||||
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
while(dir_walk_read(dir_walk, path, &fileinfo) == DirWalkOK) {
|
||||||
furi_string_right(path, strlen(EXT_PATH("dirwalk/")));
|
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);
|
dir_walk_free(dir_walk);
|
||||||
|
|||||||
@@ -2,9 +2,40 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
// DO NOT USE THIS IN PRODUCTION CODE
|
||||||
|
// This is a hack to access internal storage functions and definitions
|
||||||
|
#include <storage/storage_i.h>
|
||||||
|
|
||||||
|
#define UNIT_TESTS_PATH(path) EXT_PATH("unit_tests/" path)
|
||||||
|
|
||||||
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
#define STORAGE_LOCKED_FILE EXT_PATH("locked_file.test")
|
||||||
#define STORAGE_LOCKED_DIR STORAGE_INT_PATH_PREFIX
|
#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() {
|
static void storage_file_open_lock_setup() {
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
File* file = storage_file_alloc(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);
|
File* file = storage_file_alloc(storage);
|
||||||
furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
furi_check(storage_dir_open(file, STORAGE_LOCKED_DIR));
|
||||||
furi_semaphore_release(semaphore);
|
furi_semaphore_release(semaphore);
|
||||||
furi_delay_ms(1000);
|
furi_delay_ms(100);
|
||||||
|
|
||||||
furi_check(storage_dir_close(file));
|
furi_check(storage_dir_close(file));
|
||||||
furi_record_close(RECORD_STORAGE);
|
furi_record_close(RECORD_STORAGE);
|
||||||
@@ -152,9 +183,21 @@ MU_TEST(storage_dir_open_lock) {
|
|||||||
mu_assert(result, "cannot open locked dir");
|
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_TEST_SUITE(storage_dir) {
|
||||||
MU_RUN_TEST(storage_dir_open_close);
|
MU_RUN_TEST(storage_dir_open_close);
|
||||||
MU_RUN_TEST(storage_dir_open_lock);
|
MU_RUN_TEST(storage_dir_open_lock);
|
||||||
|
MU_RUN_TEST(storage_dir_exists_test);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char* const storage_copy_test_paths[] = {
|
static const char* const storage_copy_test_paths[] = {
|
||||||
@@ -303,9 +346,256 @@ MU_TEST_SUITE(storage_rename) {
|
|||||||
furi_record_close(RECORD_STORAGE);
|
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() {
|
int run_minunit_test_storage() {
|
||||||
MU_RUN_SUITE(storage_file);
|
MU_RUN_SUITE(storage_file);
|
||||||
MU_RUN_SUITE(storage_dir);
|
MU_RUN_SUITE(storage_dir);
|
||||||
MU_RUN_SUITE(storage_rename);
|
MU_RUN_SUITE(storage_rename);
|
||||||
|
MU_RUN_SUITE(test_data_path);
|
||||||
|
MU_RUN_SUITE(test_storage_common);
|
||||||
return MU_EXIT_CODE;
|
return MU_EXIT_CODE;
|
||||||
}
|
}
|
||||||
|
|||||||
18
applications/examples/example_apps_data/README.md
Normal file
18
applications/examples/example_apps_data/README.md
Normal file
@@ -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")`.
|
||||||
9
applications/examples/example_apps_data/application.fam
Normal file
9
applications/examples/example_apps_data/application.fam
Normal file
@@ -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",
|
||||||
|
)
|
||||||
40
applications/examples/example_apps_data/example_apps_data.c
Normal file
40
applications/examples/example_apps_data/example_apps_data.c
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#include <furi.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
|
// 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/<app_name>
|
||||||
|
// 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;
|
||||||
|
}
|
||||||
@@ -451,7 +451,7 @@ static bool archive_is_dir_exists(FuriString* path) {
|
|||||||
FileInfo file_info;
|
FileInfo file_info;
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) {
|
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;
|
state = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -532,12 +532,16 @@ void archive_enter_dir(ArchiveBrowserView* browser, FuriString* path) {
|
|||||||
browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
|
browser->view, ArchiveBrowserViewModel * model, { idx_temp = model->item_idx; }, false);
|
||||||
|
|
||||||
furi_string_set(browser->path, path);
|
furi_string_set(browser->path, path);
|
||||||
|
|
||||||
file_browser_worker_folder_enter(browser->worker, path, idx_temp);
|
file_browser_worker_folder_enter(browser->worker, path, idx_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
void archive_leave_dir(ArchiveBrowserView* browser) {
|
void archive_leave_dir(ArchiveBrowserView* browser) {
|
||||||
furi_assert(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);
|
file_browser_worker_folder_exit(browser->worker);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -160,7 +160,7 @@ bool archive_favorites_read(void* context) {
|
|||||||
if(storage_file_exists(storage, furi_string_get_cstr(buffer))) {
|
if(storage_file_exists(storage, furi_string_get_cstr(buffer))) {
|
||||||
storage_common_stat(storage, furi_string_get_cstr(buffer), &file_info);
|
storage_common_stat(storage, furi_string_get_cstr(buffer), &file_info);
|
||||||
archive_add_file_item(
|
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++;
|
file_count++;
|
||||||
} else {
|
} else {
|
||||||
need_refresh = true;
|
need_refresh = true;
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ void archive_delete_file(void* context, const char* format, ...) {
|
|||||||
|
|
||||||
bool res = false;
|
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));
|
res = storage_simply_remove_recursive(fs_api, furi_string_get_cstr(filename));
|
||||||
} else {
|
} else {
|
||||||
res = (storage_common_remove(fs_api, furi_string_get_cstr(filename)) == FSE_OK);
|
res = (storage_common_remove(fs_api, furi_string_get_cstr(filename)) == FSE_OK);
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <gui/modules/loading.h>
|
#include <gui/modules/loading.h>
|
||||||
#include <dialogs/dialogs.h>
|
#include <dialogs/dialogs.h>
|
||||||
|
#include <toolbox/path.h>
|
||||||
#include <flipper_application/flipper_application.h>
|
#include <flipper_application/flipper_application.h>
|
||||||
#include "elf_cpp/elf_hashtable.h"
|
#include "elf_cpp/elf_hashtable.h"
|
||||||
#include "fap_loader_app.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");
|
FURI_LOG_I(TAG, "FAP Loader is starting app");
|
||||||
|
|
||||||
FuriThread* thread = flipper_application_spawn(loader->app, NULL);
|
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_start(thread);
|
||||||
furi_thread_join(thread);
|
furi_thread_join(thread);
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,6 @@
|
|||||||
#include "ibutton.h"
|
|
||||||
#include "assets_icons.h"
|
|
||||||
#include "ibutton_i.h"
|
#include "ibutton_i.h"
|
||||||
#include "ibutton/scenes/ibutton_scene.h"
|
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
#include <flipper_format/flipper_format.h>
|
|
||||||
#include <rpc/rpc_app.h>
|
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
#define TAG "iButtonApp"
|
#define TAG "iButtonApp"
|
||||||
@@ -34,50 +30,13 @@ static const NotificationSequence* ibutton_notification_sequences[] = {
|
|||||||
};
|
};
|
||||||
|
|
||||||
static void ibutton_make_app_folder(iButton* ibutton) {
|
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");
|
dialog_message_show_storage_error(ibutton->dialogs, "Cannot create\napp folder");
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog) {
|
furi_record_close(RECORD_STORAGE);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void ibutton_rpc_command_callback(RpcAppSystemEvent event, void* context) {
|
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) {
|
if(event == RpcAppEventSessionClose) {
|
||||||
view_dispatcher_send_custom_event(
|
view_dispatcher_send_custom_event(
|
||||||
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
ibutton->view_dispatcher, iButtonCustomEventRpcSessionClose);
|
||||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
rpc_system_app_set_callback(ibutton->rpc, NULL, NULL);
|
||||||
ibutton->rpc_ctx = NULL;
|
ibutton->rpc = NULL;
|
||||||
} else if(event == RpcAppEventAppExit) {
|
} else if(event == RpcAppEventAppExit) {
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcExit);
|
||||||
} else if(event == RpcAppEventLoadFile) {
|
} else if(event == RpcAppEventLoadFile) {
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventRpcLoad);
|
||||||
} else {
|
} 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->gui = furi_record_open(RECORD_GUI);
|
||||||
|
|
||||||
ibutton->storage = furi_record_open(RECORD_STORAGE);
|
|
||||||
ibutton->dialogs = furi_record_open(RECORD_DIALOGS);
|
ibutton->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||||
ibutton->notifications = furi_record_open(RECORD_NOTIFICATION);
|
ibutton->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||||
|
|
||||||
ibutton->key = ibutton_key_alloc();
|
ibutton->protocols = ibutton_protocols_alloc();
|
||||||
ibutton->key_worker = ibutton_worker_alloc();
|
ibutton->key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(ibutton->protocols));
|
||||||
ibutton_worker_start_thread(ibutton->key_worker);
|
ibutton->worker = ibutton_worker_alloc(ibutton->protocols);
|
||||||
|
ibutton_worker_start_thread(ibutton->worker);
|
||||||
|
|
||||||
ibutton->submenu = submenu_alloc();
|
ibutton->submenu = submenu_alloc();
|
||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
@@ -163,9 +122,9 @@ iButton* ibutton_alloc() {
|
|||||||
view_dispatcher_add_view(
|
view_dispatcher_add_view(
|
||||||
ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget));
|
ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget));
|
||||||
|
|
||||||
ibutton->dialog_ex = dialog_ex_alloc();
|
ibutton->loading = loading_alloc();
|
||||||
view_dispatcher_add_view(
|
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;
|
return ibutton;
|
||||||
}
|
}
|
||||||
@@ -173,8 +132,8 @@ iButton* ibutton_alloc() {
|
|||||||
void ibutton_free(iButton* ibutton) {
|
void ibutton_free(iButton* ibutton) {
|
||||||
furi_assert(ibutton);
|
furi_assert(ibutton);
|
||||||
|
|
||||||
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewDialogEx);
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewLoading);
|
||||||
dialog_ex_free(ibutton->dialog_ex);
|
loading_free(ibutton->loading);
|
||||||
|
|
||||||
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget);
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
widget_free(ibutton->widget);
|
widget_free(ibutton->widget);
|
||||||
@@ -194,9 +153,6 @@ void ibutton_free(iButton* ibutton) {
|
|||||||
view_dispatcher_free(ibutton->view_dispatcher);
|
view_dispatcher_free(ibutton->view_dispatcher);
|
||||||
scene_manager_free(ibutton->scene_manager);
|
scene_manager_free(ibutton->scene_manager);
|
||||||
|
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
ibutton->storage = NULL;
|
|
||||||
|
|
||||||
furi_record_close(RECORD_NOTIFICATION);
|
furi_record_close(RECORD_NOTIFICATION);
|
||||||
ibutton->notifications = NULL;
|
ibutton->notifications = NULL;
|
||||||
|
|
||||||
@@ -206,103 +162,83 @@ void ibutton_free(iButton* ibutton) {
|
|||||||
furi_record_close(RECORD_GUI);
|
furi_record_close(RECORD_GUI);
|
||||||
ibutton->gui = NULL;
|
ibutton->gui = NULL;
|
||||||
|
|
||||||
ibutton_worker_stop_thread(ibutton->key_worker);
|
ibutton_worker_stop_thread(ibutton->worker);
|
||||||
ibutton_worker_free(ibutton->key_worker);
|
ibutton_worker_free(ibutton->worker);
|
||||||
ibutton_key_free(ibutton->key);
|
ibutton_key_free(ibutton->key);
|
||||||
|
ibutton_protocols_free(ibutton->protocols);
|
||||||
|
|
||||||
furi_string_free(ibutton->file_path);
|
furi_string_free(ibutton->file_path);
|
||||||
|
|
||||||
free(ibutton);
|
free(ibutton);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_file_select(iButton* ibutton) {
|
bool ibutton_load_key(iButton* ibutton) {
|
||||||
DialogsFileBrowserOptions browser_options;
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewLoading);
|
||||||
dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px);
|
|
||||||
browser_options.base_path = IBUTTON_APP_FOLDER;
|
|
||||||
|
|
||||||
bool success = dialog_file_browser_show(
|
const bool success = ibutton_protocols_load(
|
||||||
ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options);
|
ibutton->protocols, ibutton->key, furi_string_get_cstr(ibutton->file_path));
|
||||||
|
|
||||||
if(success) {
|
if(!success) {
|
||||||
success = ibutton_load_key_data(ibutton, ibutton->file_path, true);
|
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;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_save_key(iButton* ibutton, const char* key_name) {
|
bool ibutton_select_and_load_key(iButton* ibutton) {
|
||||||
// Create ibutton directory if necessary
|
DialogsFileBrowserOptions browser_options;
|
||||||
ibutton_make_app_folder(ibutton);
|
dialog_file_browser_set_basic_options(&browser_options, IBUTTON_APP_EXTENSION, &I_ibutt_10px);
|
||||||
|
browser_options.base_path = IBUTTON_APP_FOLDER;
|
||||||
|
|
||||||
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
|
if(furi_string_empty(ibutton->file_path)) {
|
||||||
iButtonKey* key = ibutton->key;
|
furi_string_set(ibutton->file_path, browser_options.base_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);
|
return dialog_file_browser_show(
|
||||||
|
ibutton->dialogs, ibutton->file_path, ibutton->file_path, &browser_options) &&
|
||||||
|
ibutton_load_key(ibutton);
|
||||||
|
}
|
||||||
|
|
||||||
// Open file for write
|
bool ibutton_save_key(iButton* ibutton) {
|
||||||
if(!flipper_format_file_open_always(file, furi_string_get_cstr(ibutton->file_path))) break;
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewLoading);
|
||||||
|
|
||||||
// Write header
|
ibutton_make_app_folder(ibutton);
|
||||||
if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break;
|
|
||||||
|
|
||||||
// Write key type
|
iButtonKey* key = ibutton->key;
|
||||||
if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom"))
|
const bool success =
|
||||||
break;
|
ibutton_protocols_save(ibutton->protocols, key, furi_string_get_cstr(ibutton->file_path));
|
||||||
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(!success) {
|
||||||
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
|
|
||||||
dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file");
|
dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file");
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_delete_key(iButton* ibutton) {
|
bool ibutton_delete_key(iButton* ibutton) {
|
||||||
bool result = false;
|
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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ibutton_text_store_set(iButton* ibutton, const char* text, ...) {
|
void ibutton_reset_key(iButton* ibutton) {
|
||||||
va_list args;
|
memset(ibutton->key_name, 0, IBUTTON_KEY_NAME_SIZE + 1);
|
||||||
va_start(args, text);
|
furi_string_reset(ibutton->file_path);
|
||||||
|
ibutton_key_reset(ibutton->key);
|
||||||
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_notification_message(iButton* ibutton, uint32_t message) {
|
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]);
|
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* ibutton = ibutton_alloc();
|
||||||
|
|
||||||
ibutton_make_app_folder(ibutton);
|
ibutton_make_app_folder(ibutton);
|
||||||
|
|
||||||
bool key_loaded = false;
|
bool key_loaded = false;
|
||||||
bool rpc_mode = false;
|
|
||||||
|
|
||||||
if(p && strlen(p)) {
|
if((arg != NULL) && (strlen(arg) != 0)) {
|
||||||
uint32_t rpc_ctx = 0;
|
if(sscanf(arg, "RPC %lX", (uint32_t*)&ibutton->rpc) == 1) {
|
||||||
if(sscanf(p, "RPC %lX", &rpc_ctx) == 1) {
|
|
||||||
FURI_LOG_D(TAG, "Running in RPC mode");
|
FURI_LOG_D(TAG, "Running in RPC mode");
|
||||||
ibutton->rpc_ctx = (void*)rpc_ctx;
|
|
||||||
rpc_mode = true;
|
rpc_system_app_set_callback(ibutton->rpc, ibutton_rpc_command_callback, ibutton);
|
||||||
rpc_system_app_set_callback(ibutton->rpc_ctx, ibutton_rpc_command_callback, ibutton);
|
rpc_system_app_send_started(ibutton->rpc);
|
||||||
rpc_system_app_send_started(ibutton->rpc_ctx);
|
|
||||||
} else {
|
} else {
|
||||||
furi_string_set(ibutton->file_path, (const char*)p);
|
furi_string_set(ibutton->file_path, (const char*)arg);
|
||||||
if(ibutton_load_key_data(ibutton, ibutton->file_path, true)) {
|
key_loaded = ibutton_load_key(ibutton);
|
||||||
key_loaded = true;
|
|
||||||
// TODO: Display an error if the key from p could not be loaded
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(rpc_mode) {
|
if(ibutton->rpc != NULL) {
|
||||||
view_dispatcher_attach_to_gui(
|
view_dispatcher_attach_to_gui(
|
||||||
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop);
|
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeDesktop);
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRpc);
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
view_dispatcher_attach_to_gui(
|
view_dispatcher_attach_to_gui(
|
||||||
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen);
|
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen);
|
||||||
@@ -353,9 +297,9 @@ int32_t ibutton_app(void* p) {
|
|||||||
|
|
||||||
view_dispatcher_run(ibutton->view_dispatcher);
|
view_dispatcher_run(ibutton->view_dispatcher);
|
||||||
|
|
||||||
if(ibutton->rpc_ctx) {
|
if(ibutton->rpc) {
|
||||||
rpc_system_app_set_callback(ibutton->rpc_ctx, NULL, NULL);
|
rpc_system_app_set_callback(ibutton->rpc, NULL, NULL);
|
||||||
rpc_system_app_send_exited(ibutton->rpc_ctx);
|
rpc_system_app_send_exited(ibutton->rpc);
|
||||||
}
|
}
|
||||||
ibutton_free(ibutton);
|
ibutton_free(ibutton);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
#include <stdarg.h>
|
|
||||||
#include <cli/cli.h>
|
#include <cli/cli.h>
|
||||||
#include <lib/toolbox/args.h>
|
#include <toolbox/args.h>
|
||||||
#include <one_wire/ibutton/ibutton_worker.h>
|
|
||||||
#include <one_wire/one_wire_host.h>
|
#include <one_wire/one_wire_host.h>
|
||||||
|
|
||||||
|
#include <one_wire/ibutton/ibutton_key.h>
|
||||||
|
#include <one_wire/ibutton/ibutton_worker.h>
|
||||||
|
#include <one_wire/ibutton/ibutton_protocols.h>
|
||||||
|
|
||||||
static void ibutton_cli(Cli* cli, FuriString* args, void* context);
|
static void ibutton_cli(Cli* cli, FuriString* args, void* context);
|
||||||
static void onewire_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
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void ibutton_cli_print_usage() {
|
static void ibutton_cli_print_usage() {
|
||||||
printf("Usage:\r\n");
|
printf("Usage:\r\n");
|
||||||
printf("ikey read\r\n");
|
printf("ikey read\r\n");
|
||||||
printf("ikey emulate <key_type> <key_data>\r\n");
|
printf("ikey emulate <key_type> <key_data>\r\n");
|
||||||
@@ -34,30 +38,52 @@ void ibutton_cli_print_usage() {
|
|||||||
printf("\t<key_data> are hex-formatted\r\n");
|
printf("\t<key_data> 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;
|
bool result = false;
|
||||||
|
FuriString* name = furi_string_alloc();
|
||||||
|
|
||||||
if(furi_string_cmp_str(data, "Dallas") == 0 || furi_string_cmp_str(data, "dallas") == 0) {
|
do {
|
||||||
result = true;
|
// Read protocol name
|
||||||
*type = iButtonKeyDS1990;
|
if(!args_read_string_and_trim(args, name)) break;
|
||||||
} 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
// 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;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ibutton_cli_print_key_data(iButtonKey* key) {
|
static void ibutton_cli_print_key(iButtonProtocols* protocols, iButtonKey* key) {
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
const char* name = ibutton_protocols_get_name(protocols, ibutton_key_get_protocol_id(key));
|
||||||
iButtonKeyType type = ibutton_key_get_type(key);
|
|
||||||
|
|
||||||
printf("%s ", ibutton_key_get_string_by_type(type));
|
if(strncmp(name, "DS", 2) == 0) {
|
||||||
for(size_t i = 0; i < ibutton_key_get_size_by_type(type); i++) {
|
name = "Dallas";
|
||||||
printf("%02X", key_data[i]);
|
}
|
||||||
|
|
||||||
|
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");
|
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);
|
furi_event_flag_set(event, EVENT_FLAG_IBUTTON_COMPLETE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ibutton_cli_read(Cli* cli) {
|
static void ibutton_cli_read(Cli* cli) {
|
||||||
iButtonKey* key = ibutton_key_alloc();
|
iButtonProtocols* protocols = ibutton_protocols_alloc();
|
||||||
iButtonWorker* worker = ibutton_worker_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();
|
FuriEventFlag* event = furi_event_flag_alloc();
|
||||||
|
|
||||||
ibutton_worker_start_thread(worker);
|
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");
|
printf("Reading iButton...\r\nPress Ctrl+C to abort\r\n");
|
||||||
ibutton_worker_read_start(worker, key);
|
ibutton_worker_read_start(worker, key);
|
||||||
|
|
||||||
while(true) {
|
while(true) {
|
||||||
uint32_t flags =
|
uint32_t flags =
|
||||||
furi_event_flag_wait(event, EVENT_FLAG_IBUTTON_COMPLETE, FuriFlagWaitAny, 100);
|
furi_event_flag_wait(event, EVENT_FLAG_IBUTTON_COMPLETE, FuriFlagWaitAny, 100);
|
||||||
|
|
||||||
if(flags & EVENT_FLAG_IBUTTON_COMPLETE) {
|
if(flags & EVENT_FLAG_IBUTTON_COMPLETE) {
|
||||||
ibutton_cli_print_key_data(key);
|
ibutton_cli_print_key(protocols, 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");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(cli_cmd_interrupt_received(cli)) break;
|
if(cli_cmd_interrupt_received(cli)) break;
|
||||||
}
|
}
|
||||||
ibutton_worker_stop(worker);
|
|
||||||
|
|
||||||
|
ibutton_worker_stop(worker);
|
||||||
ibutton_worker_stop_thread(worker);
|
ibutton_worker_stop_thread(worker);
|
||||||
ibutton_worker_free(worker);
|
|
||||||
ibutton_key_free(key);
|
ibutton_key_free(key);
|
||||||
|
ibutton_worker_free(worker);
|
||||||
|
ibutton_protocols_free(protocols);
|
||||||
|
|
||||||
furi_event_flag_free(event);
|
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) {
|
void ibutton_cli_write(Cli* cli, FuriString* args) {
|
||||||
iButtonKey* key = ibutton_key_alloc();
|
iButtonProtocols* protocols = ibutton_protocols_alloc();
|
||||||
iButtonWorker* worker = ibutton_worker_alloc();
|
iButtonWorker* worker = ibutton_worker_alloc(protocols);
|
||||||
iButtonKeyType type;
|
iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
|
||||||
iButtonWriteContext write_context;
|
|
||||||
uint8_t key_data[IBUTTON_KEY_DATA_SIZE];
|
|
||||||
FuriString* data;
|
|
||||||
|
|
||||||
|
iButtonWriteContext write_context;
|
||||||
write_context.event = furi_event_flag_alloc();
|
write_context.event = furi_event_flag_alloc();
|
||||||
|
|
||||||
data = furi_string_alloc();
|
|
||||||
ibutton_worker_start_thread(worker);
|
ibutton_worker_start_thread(worker);
|
||||||
ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context);
|
ibutton_worker_write_set_callback(worker, ibutton_cli_worker_write_cb, &write_context);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!args_read_string_and_trim(args, data)) {
|
if(!ibutton_cli_parse_key(protocols, key, args)) {
|
||||||
ibutton_cli_print_usage();
|
ibutton_cli_print_usage();
|
||||||
break;
|
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();
|
ibutton_cli_print_usage();
|
||||||
break;
|
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 ");
|
printf("Writing key ");
|
||||||
ibutton_cli_print_key_data(key);
|
ibutton_cli_print_key(protocols, key);
|
||||||
printf("Press Ctrl+C to abort\r\n");
|
printf("Press Ctrl+C to abort\r\n");
|
||||||
|
|
||||||
ibutton_worker_write_start(worker, key);
|
ibutton_worker_write_blank_start(worker, key);
|
||||||
while(true) {
|
while(true) {
|
||||||
uint32_t flags = furi_event_flag_wait(
|
uint32_t flags = furi_event_flag_wait(
|
||||||
write_context.event, EVENT_FLAG_IBUTTON_COMPLETE, FuriFlagWaitAny, 100);
|
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;
|
if(cli_cmd_interrupt_received(cli)) break;
|
||||||
}
|
}
|
||||||
ibutton_worker_stop(worker);
|
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
furi_string_free(data);
|
ibutton_worker_stop(worker);
|
||||||
ibutton_worker_stop_thread(worker);
|
ibutton_worker_stop_thread(worker);
|
||||||
ibutton_worker_free(worker);
|
|
||||||
ibutton_key_free(key);
|
ibutton_key_free(key);
|
||||||
|
ibutton_worker_free(worker);
|
||||||
|
ibutton_protocols_free(protocols);
|
||||||
|
|
||||||
furi_event_flag_free(write_context.event);
|
furi_event_flag_free(write_context.event);
|
||||||
};
|
}
|
||||||
|
|
||||||
void ibutton_cli_emulate(Cli* cli, FuriString* args) {
|
void ibutton_cli_emulate(Cli* cli, FuriString* args) {
|
||||||
iButtonKey* key = ibutton_key_alloc();
|
iButtonProtocols* protocols = ibutton_protocols_alloc();
|
||||||
iButtonWorker* worker = ibutton_worker_alloc();
|
iButtonWorker* worker = ibutton_worker_alloc(protocols);
|
||||||
iButtonKeyType type;
|
iButtonKey* key = ibutton_key_alloc(ibutton_protocols_get_max_data_size(protocols));
|
||||||
uint8_t key_data[IBUTTON_KEY_DATA_SIZE];
|
|
||||||
FuriString* data;
|
|
||||||
|
|
||||||
data = furi_string_alloc();
|
|
||||||
ibutton_worker_start_thread(worker);
|
ibutton_worker_start_thread(worker);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!args_read_string_and_trim(args, data)) {
|
if(!ibutton_cli_parse_key(protocols, key, args)) {
|
||||||
ibutton_cli_print_usage();
|
ibutton_cli_print_usage();
|
||||||
break;
|
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 ");
|
printf("Emulating key ");
|
||||||
ibutton_cli_print_key_data(key);
|
ibutton_cli_print_key(protocols, key);
|
||||||
printf("Press Ctrl+C to abort\r\n");
|
printf("Press Ctrl+C to abort\r\n");
|
||||||
|
|
||||||
ibutton_worker_emulate_start(worker, key);
|
ibutton_worker_emulate_start(worker, key);
|
||||||
|
|
||||||
while(!cli_cmd_interrupt_received(cli)) {
|
while(!cli_cmd_interrupt_received(cli)) {
|
||||||
furi_delay_ms(100);
|
furi_delay_ms(100);
|
||||||
};
|
};
|
||||||
ibutton_worker_stop(worker);
|
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
furi_string_free(data);
|
ibutton_worker_stop(worker);
|
||||||
ibutton_worker_stop_thread(worker);
|
ibutton_worker_stop_thread(worker);
|
||||||
ibutton_worker_free(worker);
|
|
||||||
ibutton_key_free(key);
|
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);
|
UNUSED(context);
|
||||||
FuriString* cmd;
|
FuriString* cmd;
|
||||||
cmd = furi_string_alloc();
|
cmd = furi_string_alloc();
|
||||||
@@ -264,7 +258,7 @@ static void ibutton_cli(Cli* cli, FuriString* args, void* context) {
|
|||||||
furi_string_free(cmd);
|
furi_string_free(cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
void onewire_cli_print_usage() {
|
static void onewire_cli_print_usage() {
|
||||||
printf("Usage:\r\n");
|
printf("Usage:\r\n");
|
||||||
printf("onewire search\r\n");
|
printf("onewire search\r\n");
|
||||||
};
|
};
|
||||||
@@ -281,7 +275,7 @@ static void onewire_cli_search(Cli* cli) {
|
|||||||
furi_hal_power_enable_otg();
|
furi_hal_power_enable_otg();
|
||||||
|
|
||||||
while(!done) {
|
while(!done) {
|
||||||
if(onewire_host_search(onewire, address, NORMAL_SEARCH) != 1) {
|
if(onewire_host_search(onewire, address, OneWireHostSearchModeNormal) != 1) {
|
||||||
printf("Search finished\r\n");
|
printf("Search finished\r\n");
|
||||||
onewire_host_reset_search(onewire);
|
onewire_host_reset_search(onewire);
|
||||||
done = true;
|
done = true;
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ enum iButtonCustomEvent {
|
|||||||
|
|
||||||
iButtonCustomEventBack,
|
iButtonCustomEventBack,
|
||||||
iButtonCustomEventTextEditResult,
|
iButtonCustomEventTextEditResult,
|
||||||
|
iButtonCustomEventByteEditChanged,
|
||||||
iButtonCustomEventByteEditResult,
|
iButtonCustomEventByteEditResult,
|
||||||
iButtonCustomEventWorkerEmulated,
|
iButtonCustomEventWorkerEmulated,
|
||||||
iButtonCustomEventWorkerRead,
|
iButtonCustomEventWorkerRead,
|
||||||
|
|||||||
@@ -4,31 +4,40 @@
|
|||||||
|
|
||||||
#include <gui/gui.h>
|
#include <gui/gui.h>
|
||||||
#include <gui/view.h>
|
#include <gui/view.h>
|
||||||
#include <assets_icons.h>
|
|
||||||
#include <gui/view_dispatcher.h>
|
|
||||||
#include <gui/scene_manager.h>
|
#include <gui/scene_manager.h>
|
||||||
#include <notification/notification_messages.h>
|
#include <gui/view_dispatcher.h>
|
||||||
|
|
||||||
#include <one_wire/ibutton/ibutton_worker.h>
|
#include <one_wire/ibutton/ibutton_worker.h>
|
||||||
|
#include <one_wire/ibutton/ibutton_protocols.h>
|
||||||
|
|
||||||
|
#include <rpc/rpc_app.h>
|
||||||
#include <storage/storage.h>
|
#include <storage/storage.h>
|
||||||
#include <dialogs/dialogs.h>
|
#include <dialogs/dialogs.h>
|
||||||
|
#include <notification/notification.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
#include <gui/modules/submenu.h>
|
#include <gui/modules/submenu.h>
|
||||||
#include <gui/modules/popup.h>
|
#include <gui/modules/popup.h>
|
||||||
#include <gui/modules/dialog_ex.h>
|
|
||||||
#include <gui/modules/text_input.h>
|
#include <gui/modules/text_input.h>
|
||||||
#include <gui/modules/byte_input.h>
|
#include <gui/modules/byte_input.h>
|
||||||
#include <gui/modules/widget.h>
|
#include <gui/modules/widget.h>
|
||||||
|
#include <gui/modules/loading.h>
|
||||||
|
|
||||||
|
#include <assets_icons.h>
|
||||||
|
|
||||||
#include "ibutton_custom_event.h"
|
#include "ibutton_custom_event.h"
|
||||||
#include "scenes/ibutton_scene.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_FOLDER ANY_PATH("ibutton")
|
||||||
#define IBUTTON_APP_EXTENSION ".ibtn"
|
#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 {
|
struct iButton {
|
||||||
SceneManager* scene_manager;
|
SceneManager* scene_manager;
|
||||||
@@ -38,21 +47,22 @@ struct iButton {
|
|||||||
Storage* storage;
|
Storage* storage;
|
||||||
DialogsApp* dialogs;
|
DialogsApp* dialogs;
|
||||||
NotificationApp* notifications;
|
NotificationApp* notifications;
|
||||||
|
RpcAppSystem* rpc;
|
||||||
|
|
||||||
iButtonWorker* key_worker;
|
|
||||||
iButtonKey* key;
|
iButtonKey* key;
|
||||||
|
iButtonWorker* worker;
|
||||||
|
iButtonProtocols* protocols;
|
||||||
|
iButtonWriteMode write_mode;
|
||||||
|
|
||||||
FuriString* file_path;
|
FuriString* file_path;
|
||||||
char text_store[IBUTTON_TEXT_STORE_SIZE + 1];
|
char key_name[IBUTTON_KEY_NAME_SIZE + 1];
|
||||||
|
|
||||||
Submenu* submenu;
|
Submenu* submenu;
|
||||||
ByteInput* byte_input;
|
ByteInput* byte_input;
|
||||||
TextInput* text_input;
|
TextInput* text_input;
|
||||||
Popup* popup;
|
Popup* popup;
|
||||||
Widget* widget;
|
Widget* widget;
|
||||||
DialogEx* dialog_ex;
|
Loading* loading;
|
||||||
|
|
||||||
void* rpc_ctx;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -61,7 +71,7 @@ typedef enum {
|
|||||||
iButtonViewTextInput,
|
iButtonViewTextInput,
|
||||||
iButtonViewPopup,
|
iButtonViewPopup,
|
||||||
iButtonViewWidget,
|
iButtonViewWidget,
|
||||||
iButtonViewDialogEx,
|
iButtonViewLoading,
|
||||||
} iButtonView;
|
} iButtonView;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
@@ -78,10 +88,12 @@ typedef enum {
|
|||||||
iButtonNotificationMessageBlinkStop,
|
iButtonNotificationMessageBlinkStop,
|
||||||
} iButtonNotificationMessage;
|
} iButtonNotificationMessage;
|
||||||
|
|
||||||
bool ibutton_file_select(iButton* ibutton);
|
bool ibutton_select_and_load_key(iButton* ibutton);
|
||||||
bool ibutton_load_key_data(iButton* ibutton, FuriString* key_path, bool show_dialog);
|
bool ibutton_load_key(iButton* ibutton);
|
||||||
bool ibutton_save_key(iButton* ibutton, const char* key_name);
|
bool ibutton_save_key(iButton* ibutton);
|
||||||
bool ibutton_delete_key(iButton* ibutton);
|
bool ibutton_delete_key(iButton* ibutton);
|
||||||
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
|
void ibutton_reset_key(iButton* ibutton);
|
||||||
void ibutton_text_store_clear(iButton* ibutton);
|
|
||||||
void ibutton_notification_message(iButton* ibutton, uint32_t message);
|
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);
|
||||||
|
|||||||
@@ -1,54 +1,57 @@
|
|||||||
#include "../ibutton_i.h"
|
#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) {
|
void ibutton_scene_add_type_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Submenu* submenu = ibutton->submenu;
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
submenu_add_item(
|
FuriString* tmp = furi_string_alloc();
|
||||||
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);
|
|
||||||
|
|
||||||
submenu_set_selected_item(
|
for(uint32_t protocol_id = 0; protocol_id < ibutton_protocols_get_protocol_count();
|
||||||
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddType));
|
++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);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
furi_string_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
iButtonKey* key = ibutton->key;
|
iButtonKey* key = ibutton->key;
|
||||||
|
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneAddType, event.event);
|
const iButtonProtocolId protocol_id = 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");
|
|
||||||
}
|
|
||||||
|
|
||||||
furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
|
ibutton_key_reset(key);
|
||||||
ibutton_key_clear_data(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);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue);
|
||||||
|
|
||||||
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
|
|||||||
@@ -1,42 +1,52 @@
|
|||||||
#include "../ibutton_i.h"
|
#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;
|
iButton* ibutton = context;
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult);
|
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) {
|
void ibutton_scene_add_value_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
iButtonKey* key = ibutton->key;
|
byte_input_set_header_text(ibutton->byte_input, "Enter the key");
|
||||||
uint8_t* new_key_data = malloc(IBUTTON_KEY_DATA_SIZE);
|
|
||||||
|
|
||||||
scene_manager_set_scene_state(
|
iButtonEditableData editable_data;
|
||||||
ibutton->scene_manager, iButtonSceneAddValue, (uint32_t)new_key_data);
|
ibutton_protocols_get_editable_data(ibutton->protocols, ibutton->key, &editable_data);
|
||||||
memcpy(new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key));
|
|
||||||
|
|
||||||
byte_input_set_result_callback(
|
byte_input_set_result_callback(
|
||||||
ibutton->byte_input,
|
ibutton->byte_input,
|
||||||
ibutton_scene_add_type_byte_input_callback,
|
ibutton_scene_add_type_byte_input_callback,
|
||||||
NULL,
|
ibutton_scene_add_type_byte_changed_callback,
|
||||||
ibutton,
|
context,
|
||||||
new_key_data,
|
editable_data.ptr,
|
||||||
ibutton_key_get_data_size(key));
|
editable_data.size);
|
||||||
|
|
||||||
byte_input_set_header_text(ibutton->byte_input, "Enter the key");
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewByteInput);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewByteInput);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
uint8_t* new_key_data =
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
(uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue);
|
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventByteEditResult) {
|
if(event.event == iButtonCustomEventByteEditResult) {
|
||||||
ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE);
|
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||||
scene_manager_next_scene(ibutton->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) {
|
void ibutton_scene_add_value_on_exit(void* context) {
|
||||||
iButton* ibutton = 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_result_callback(ibutton->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||||
byte_input_set_header_text(ibutton->byte_input, NULL);
|
byte_input_set_header_text(ibutton->byte_input, NULL);
|
||||||
free(new_key_data);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,8 +6,7 @@ ADD_SCENE(ibutton, info, Info)
|
|||||||
ADD_SCENE(ibutton, read, Read)
|
ADD_SCENE(ibutton, read, Read)
|
||||||
ADD_SCENE(ibutton, read_key_menu, ReadKeyMenu)
|
ADD_SCENE(ibutton, read_key_menu, ReadKeyMenu)
|
||||||
ADD_SCENE(ibutton, read_success, ReadSuccess)
|
ADD_SCENE(ibutton, read_success, ReadSuccess)
|
||||||
ADD_SCENE(ibutton, read_crc_error, ReadCRCError)
|
ADD_SCENE(ibutton, read_error, ReadError)
|
||||||
ADD_SCENE(ibutton, read_not_key_error, ReadNotKeyError)
|
|
||||||
ADD_SCENE(ibutton, select_key, SelectKey)
|
ADD_SCENE(ibutton, select_key, SelectKey)
|
||||||
ADD_SCENE(ibutton, add_type, AddType)
|
ADD_SCENE(ibutton, add_type, AddType)
|
||||||
ADD_SCENE(ibutton, add_value, AddValue)
|
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, delete_success, DeleteSuccess)
|
||||||
ADD_SCENE(ibutton, retry_confirm, RetryConfirm)
|
ADD_SCENE(ibutton, retry_confirm, RetryConfirm)
|
||||||
ADD_SCENE(ibutton, exit_confirm, ExitConfirm)
|
ADD_SCENE(ibutton, exit_confirm, ExitConfirm)
|
||||||
|
ADD_SCENE(ibutton, view_data, ViewData)
|
||||||
ADD_SCENE(ibutton, rpc, Rpc)
|
ADD_SCENE(ibutton, rpc, Rpc)
|
||||||
|
|||||||
@@ -1,74 +1,29 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
|
|
||||||
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) {
|
void ibutton_scene_delete_confirm_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Widget* widget = ibutton->widget;
|
|
||||||
iButtonKey* key = ibutton->key;
|
iButtonKey* key = ibutton->key;
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
Widget* widget = ibutton->widget;
|
||||||
|
|
||||||
FuriString* key_name;
|
FuriString* tmp = furi_string_alloc();
|
||||||
key_name = furi_string_alloc();
|
|
||||||
path_extract_filename(ibutton->file_path, key_name, true);
|
|
||||||
|
|
||||||
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", furi_string_get_cstr(key_name));
|
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", ibutton_widget_callback, context);
|
||||||
widget_add_text_box_element(
|
|
||||||
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, true);
|
|
||||||
widget_add_button_element(
|
widget_add_button_element(
|
||||||
widget, GuiButtonTypeLeft, "Cancel", ibutton_scene_delete_confirm_widget_callback, ibutton);
|
widget, GuiButtonTypeRight, "Delete", ibutton_widget_callback, context);
|
||||||
widget_add_button_element(
|
|
||||||
widget,
|
|
||||||
GuiButtonTypeRight,
|
|
||||||
"Delete",
|
|
||||||
ibutton_scene_delete_confirm_widget_callback,
|
|
||||||
ibutton);
|
|
||||||
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
furi_string_printf(tmp, "Delete %s?", ibutton->key_name);
|
||||||
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_add_string_element(
|
||||||
widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Dallas");
|
widget, 128 / 2, 0, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp));
|
||||||
break;
|
|
||||||
|
|
||||||
case iButtonKeyCyfral:
|
furi_string_reset(tmp);
|
||||||
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
|
ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp);
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 34, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
|
|
||||||
break;
|
|
||||||
|
|
||||||
case iButtonKeyMetakom:
|
widget_add_string_multiline_element(
|
||||||
ibutton_text_store_set(
|
widget, 128 / 2, 16, AlignCenter, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
|
||||||
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;
|
|
||||||
}
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 46, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
furi_string_free(tmp);
|
||||||
furi_string_free(key_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
|
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(event.event == GuiButtonTypeRight) {
|
||||||
if(ibutton_delete_key(ibutton)) {
|
if(ibutton_delete_key(ibutton)) {
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneDeleteSuccess);
|
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) {
|
} else if(event.event == GuiButtonTypeLeft) {
|
||||||
scene_manager_previous_scene(scene_manager);
|
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) {
|
void ibutton_scene_delete_confirm_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
ibutton_text_store_clear(ibutton);
|
|
||||||
widget_reset(ibutton->widget);
|
widget_reset(ibutton->widget);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,61 +14,32 @@ static void ibutton_scene_emulate_callback(void* context, bool emulated) {
|
|||||||
|
|
||||||
void ibutton_scene_emulate_on_enter(void* context) {
|
void ibutton_scene_emulate_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Widget* widget = ibutton->widget;
|
|
||||||
iButtonKey* key = ibutton->key;
|
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;
|
widget_add_icon_element(widget, 3, 10, &I_iButtonKey_49x44);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
// check that stored key has name
|
furi_string_printf(
|
||||||
if(!furi_string_empty(key_name)) {
|
tmp,
|
||||||
ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
|
"%s\n[%s]",
|
||||||
} else {
|
furi_string_empty(ibutton->file_path) ? "Unsaved Key" : ibutton->key_name,
|
||||||
// if not, show key data
|
ibutton_protocols_get_name(ibutton->protocols, ibutton_key_get_protocol_id(key)));
|
||||||
switch(ibutton_key_get_type(key)) {
|
|
||||||
case iButtonKeyDS1990:
|
widget_add_text_box_element(
|
||||||
ibutton_text_store_set(
|
widget, 52, 38, 75, 26, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true);
|
||||||
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_string_multiline_element(
|
widget_add_string_multiline_element(
|
||||||
widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nemulating");
|
widget, 88, 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);
|
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
ibutton_worker_emulate_set_callback(ibutton->worker, ibutton_scene_emulate_callback, ibutton);
|
||||||
|
ibutton_worker_emulate_start(ibutton->worker, key);
|
||||||
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_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
|
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) {
|
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) {
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
uint32_t cnt = scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate);
|
uint32_t cnt = scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneEmulate);
|
||||||
if(cnt > 0) {
|
if(cnt > 0) {
|
||||||
cnt--;
|
if(--cnt == 0) {
|
||||||
if(cnt == 0) {
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateBlink);
|
||||||
}
|
}
|
||||||
scene_manager_set_scene_state(ibutton->scene_manager, iButtonSceneEmulate, cnt);
|
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) {
|
void ibutton_scene_emulate_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
ibutton_worker_stop(ibutton->key_worker);
|
ibutton_worker_stop(ibutton->worker);
|
||||||
widget_reset(ibutton->widget);
|
widget_reset(ibutton->widget);
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,66 +1,54 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <toolbox/path.h>
|
|
||||||
|
|
||||||
void ibutton_scene_info_on_enter(void* context) {
|
void ibutton_scene_info_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Widget* widget = ibutton->widget;
|
|
||||||
iButtonKey* key = ibutton->key;
|
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;
|
FuriString* tmp = furi_string_alloc();
|
||||||
key_name = furi_string_alloc();
|
|
||||||
path_extract_filename(ibutton->file_path, key_name, true);
|
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_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)) {
|
furi_string_reset(tmp);
|
||||||
case iButtonKeyDS1990:
|
ibutton_protocols_render_brief_data(ibutton->protocols, key, tmp);
|
||||||
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;
|
|
||||||
|
|
||||||
case iButtonKeyMetakom:
|
widget_add_string_multiline_element(
|
||||||
ibutton_text_store_set(
|
widget, 0, 16, AlignLeft, AlignTop, FontSecondary, furi_string_get_cstr(tmp));
|
||||||
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;
|
|
||||||
|
|
||||||
case iButtonKeyCyfral:
|
if(ibutton_protocols_get_features(ibutton->protocols, protocol_id) &
|
||||||
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
|
iButtonProtocolFeatureExtData) {
|
||||||
widget_add_string_element(widget, 64, 36, AlignCenter, AlignBottom, FontPrimary, "Cyfral");
|
widget_add_button_element(
|
||||||
break;
|
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);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
furi_string_free(tmp);
|
||||||
furi_string_free(key_name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
UNUSED(context);
|
iButton* ibutton = context;
|
||||||
UNUSED(event);
|
bool consumed = false;
|
||||||
return 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) {
|
void ibutton_scene_info_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
ibutton_text_store_clear(ibutton);
|
|
||||||
widget_reset(ibutton->widget);
|
widget_reset(ibutton->widget);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,14 +11,13 @@ void ibutton_scene_read_on_enter(void* context) {
|
|||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Popup* popup = ibutton->popup;
|
Popup* popup = ibutton->popup;
|
||||||
iButtonKey* key = ibutton->key;
|
iButtonKey* key = ibutton->key;
|
||||||
iButtonWorker* worker = ibutton->key_worker;
|
iButtonWorker* worker = ibutton->worker;
|
||||||
|
|
||||||
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
|
popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
|
popup_set_text(popup, "Waiting\nfor key ...", 95, 30, AlignCenter, AlignTop);
|
||||||
popup_set_icon(popup, 0, 5, XTREME_ASSETS()->I_DolphinWait_61x59);
|
popup_set_icon(popup, 0, 5, XTREME_ASSETS()->I_DolphinWait_61x59);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
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_set_callback(worker, ibutton_scene_read_callback, ibutton);
|
||||||
ibutton_worker_read_start(worker, key);
|
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) {
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventWorkerRead) {
|
if(event.event == iButtonCustomEventWorkerRead) {
|
||||||
bool success = false;
|
if(ibutton_protocols_is_valid(ibutton->protocols, ibutton->key)) {
|
||||||
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) {
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess);
|
scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess);
|
||||||
|
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
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) {
|
void ibutton_scene_read_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Popup* popup = ibutton->popup;
|
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_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
popup_set_icon(popup, 0, 0, NULL);
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
|||||||
@@ -1,70 +0,0 @@
|
|||||||
#include "../ibutton_i.h"
|
|
||||||
#include <one_wire/maxim_crc.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
58
applications/main/ibutton/scenes/ibutton_scene_read_error.c
Normal file
58
applications/main/ibutton/scenes/ibutton_scene_read_error.c
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <one_wire/maxim_crc.h>
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
@@ -4,7 +4,9 @@
|
|||||||
typedef enum {
|
typedef enum {
|
||||||
SubmenuIndexSave,
|
SubmenuIndexSave,
|
||||||
SubmenuIndexEmulate,
|
SubmenuIndexEmulate,
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexViewData,
|
||||||
|
SubmenuIndexWriteBlank,
|
||||||
|
SubmenuIndexWriteCopy,
|
||||||
} SubmenuIndex;
|
} SubmenuIndex;
|
||||||
|
|
||||||
void ibutton_scene_read_key_menu_submenu_callback(void* context, uint32_t index) {
|
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;
|
iButton* ibutton = context;
|
||||||
Submenu* submenu = ibutton->submenu;
|
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_add_item(
|
||||||
submenu, "Save", SubmenuIndexSave, ibutton_scene_read_key_menu_submenu_callback, ibutton);
|
submenu, "Save", SubmenuIndexSave, ibutton_scene_read_key_menu_submenu_callback, ibutton);
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
@@ -24,36 +29,66 @@ void ibutton_scene_read_key_menu_on_enter(void* context) {
|
|||||||
SubmenuIndexEmulate,
|
SubmenuIndexEmulate,
|
||||||
ibutton_scene_read_key_menu_submenu_callback,
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
ibutton);
|
ibutton);
|
||||||
if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) {
|
|
||||||
|
if(features & iButtonProtocolFeatureExtData) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu,
|
submenu,
|
||||||
"Write",
|
"View Data",
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexViewData,
|
||||||
ibutton_scene_read_key_menu_submenu_callback,
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
ibutton);
|
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_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneReadKeyMenu));
|
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneReadKeyMenu));
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(scene_manager, iButtonSceneReadKeyMenu, event.event);
|
||||||
ibutton->scene_manager, iButtonSceneReadKeyMenu, event.event);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
|
||||||
if(event.event == SubmenuIndexSave) {
|
if(event.event == SubmenuIndexSave) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
|
scene_manager_next_scene(scene_manager, iButtonSceneSaveName);
|
||||||
} else if(event.event == SubmenuIndexEmulate) {
|
} else if(event.event == SubmenuIndexEmulate) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
scene_manager_next_scene(scene_manager, iButtonSceneEmulate);
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||||
} else if(event.event == SubmenuIndexWrite) {
|
} else if(event.event == SubmenuIndexViewData) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
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;
|
return consumed;
|
||||||
|
|||||||
@@ -1,71 +0,0 @@
|
|||||||
#include "../ibutton_i.h"
|
|
||||||
#include <one_wire/maxim_crc.h>
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
@@ -1,55 +1,40 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <dolphin/dolphin.h>
|
|
||||||
|
|
||||||
static void ibutton_scene_read_success_dialog_ex_callback(DialogExResult result, void* context) {
|
#include <dolphin/dolphin.h>
|
||||||
iButton* ibutton = context;
|
|
||||||
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ibutton_scene_read_success_on_enter(void* context) {
|
void ibutton_scene_read_success_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
DialogEx* dialog_ex = ibutton->dialog_ex;
|
|
||||||
iButtonKey* key = ibutton->key;
|
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)) {
|
FuriString* tmp = furi_string_alloc();
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog_ex_set_text(dialog_ex, ibutton->text_store, 95, 30, AlignCenter, AlignCenter);
|
const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key);
|
||||||
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);
|
|
||||||
|
|
||||||
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);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn);
|
||||||
|
|
||||||
|
furi_string_free(tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) {
|
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);
|
scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm);
|
||||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == DialogExResultRight) {
|
if(event.event == GuiButtonTypeRight) {
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu);
|
scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu);
|
||||||
} else if(event.event == DialogExResultLeft) {
|
} else if(event.event == GuiButtonTypeLeft) {
|
||||||
scene_manager_next_scene(scene_manager, iButtonSceneRetryConfirm);
|
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) {
|
void ibutton_scene_read_success_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
DialogEx* dialog_ex = ibutton->dialog_ex;
|
|
||||||
|
|
||||||
ibutton_text_store_clear(ibutton);
|
widget_reset(ibutton->widget);
|
||||||
|
|
||||||
dialog_ex_reset(dialog_ex);
|
|
||||||
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <toolbox/path.h>
|
|
||||||
#include <rpc/rpc_app.h>
|
|
||||||
|
|
||||||
void ibutton_scene_rpc_on_enter(void* context) {
|
void ibutton_scene_rpc_on_enter(void* context) {
|
||||||
iButton* ibutton = 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) {
|
bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||||
UNUSED(context);
|
|
||||||
UNUSED(event);
|
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Popup* popup = ibutton->popup;
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
@@ -26,40 +22,32 @@ bool ibutton_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
|||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
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)) {
|
if(event.event == iButtonCustomEventRpcLoad) {
|
||||||
ibutton_text_store_set(
|
bool result = false;
|
||||||
ibutton, "emulating\n%s", furi_string_get_cstr(key_name));
|
const char* file_path = rpc_system_app_get_data(ibutton->rpc);
|
||||||
} else {
|
|
||||||
ibutton_text_store_set(ibutton, "emulating");
|
if(file_path && (furi_string_empty(ibutton->file_path))) {
|
||||||
}
|
furi_string_set(ibutton->file_path, file_path);
|
||||||
popup_set_text(popup, ibutton->text_store, 82, 32, AlignCenter, AlignTop);
|
|
||||||
|
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_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
|
||||||
|
ibutton_worker_emulate_start(ibutton->worker, ibutton->key);
|
||||||
|
|
||||||
furi_string_free(key_name);
|
|
||||||
result = true;
|
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) {
|
} 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);
|
scene_manager_stop(ibutton->scene_manager);
|
||||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
|
|
||||||
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
} else if(event.event == iButtonCustomEventRpcSessionClose) {
|
||||||
scene_manager_stop(ibutton->scene_manager);
|
scene_manager_stop(ibutton->scene_manager);
|
||||||
view_dispatcher_stop(ibutton->view_dispatcher);
|
view_dispatcher_stop(ibutton->view_dispatcher);
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include <lib/toolbox/random_name.h>
|
|
||||||
|
#include <toolbox/random_name.h>
|
||||||
#include <toolbox/path.h>
|
#include <toolbox/path.h>
|
||||||
|
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
static void ibutton_scene_save_name_text_input_callback(void* context) {
|
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;
|
iButton* ibutton = context;
|
||||||
TextInput* text_input = ibutton->text_input;
|
TextInput* text_input = ibutton->text_input;
|
||||||
|
|
||||||
FuriString* key_name;
|
const bool is_new_file = furi_string_empty(ibutton->file_path);
|
||||||
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 key_name_is_empty = furi_string_empty(key_name);
|
if(is_new_file) {
|
||||||
if(key_name_is_empty) {
|
set_random_name(ibutton->key_name, IBUTTON_KEY_NAME_SIZE);
|
||||||
set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE);
|
|
||||||
} else {
|
|
||||||
ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
text_input_set_header_text(text_input, "Name the key");
|
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,
|
text_input,
|
||||||
ibutton_scene_save_name_text_input_callback,
|
ibutton_scene_save_name_text_input_callback,
|
||||||
ibutton,
|
ibutton,
|
||||||
ibutton->text_store,
|
ibutton->key_name,
|
||||||
IBUTTON_KEY_NAME_SIZE,
|
IBUTTON_KEY_NAME_SIZE,
|
||||||
key_name_is_empty);
|
is_new_file);
|
||||||
|
|
||||||
FuriString* folder_path;
|
ValidatorIsFile* validator_is_file =
|
||||||
folder_path = furi_string_alloc();
|
validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, ibutton->key_name);
|
||||||
|
|
||||||
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));
|
|
||||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput);
|
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) {
|
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) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == iButtonCustomEventTextEditResult) {
|
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);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess);
|
||||||
|
|
||||||
if(scene_manager_has_previous_scene(
|
if(scene_manager_has_previous_scene(
|
||||||
ibutton->scene_manager, iButtonSceneSavedKeyMenu)) {
|
ibutton->scene_manager, iButtonSceneSavedKeyMenu)) {
|
||||||
// Nothing, do not count editing as saving
|
// Nothing, do not count editing as saving
|
||||||
@@ -67,6 +62,7 @@ bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
|||||||
} else {
|
} else {
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
const uint32_t possible_scenes[] = {
|
const uint32_t possible_scenes[] = {
|
||||||
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||||
|
|||||||
@@ -3,72 +3,70 @@
|
|||||||
|
|
||||||
enum SubmenuIndex {
|
enum SubmenuIndex {
|
||||||
SubmenuIndexEmulate,
|
SubmenuIndexEmulate,
|
||||||
SubmenuIndexWrite,
|
SubmenuIndexWriteBlank,
|
||||||
|
SubmenuIndexWriteCopy,
|
||||||
SubmenuIndexEdit,
|
SubmenuIndexEdit,
|
||||||
SubmenuIndexDelete,
|
SubmenuIndexDelete,
|
||||||
SubmenuIndexInfo,
|
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) {
|
void ibutton_scene_saved_key_menu_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Submenu* submenu = ibutton->submenu;
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
|
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_add_item(
|
||||||
submenu,
|
submenu, "Write Blank", SubmenuIndexWriteBlank, ibutton_submenu_callback, ibutton);
|
||||||
"Emulate",
|
|
||||||
SubmenuIndexEmulate,
|
|
||||||
ibutton_scene_saved_key_menu_submenu_callback,
|
|
||||||
ibutton);
|
|
||||||
if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) {
|
|
||||||
submenu_add_item(
|
|
||||||
submenu,
|
|
||||||
"Write",
|
|
||||||
SubmenuIndexWrite,
|
|
||||||
ibutton_scene_saved_key_menu_submenu_callback,
|
|
||||||
ibutton);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(features & iButtonProtocolFeatureWriteCopy) {
|
||||||
submenu_add_item(
|
submenu_add_item(
|
||||||
submenu, "Edit", SubmenuIndexEdit, ibutton_scene_saved_key_menu_submenu_callback, ibutton);
|
submenu, "Write Copy", SubmenuIndexWriteCopy, ibutton_submenu_callback, ibutton);
|
||||||
submenu_add_item(
|
}
|
||||||
submenu,
|
|
||||||
"Delete",
|
submenu_add_item(submenu, "Edit", SubmenuIndexEdit, ibutton_submenu_callback, ibutton);
|
||||||
SubmenuIndexDelete,
|
submenu_add_item(submenu, "Delete", SubmenuIndexDelete, ibutton_submenu_callback, ibutton);
|
||||||
ibutton_scene_saved_key_menu_submenu_callback,
|
submenu_add_item(submenu, "Info", SubmenuIndexInfo, ibutton_submenu_callback, ibutton);
|
||||||
ibutton);
|
|
||||||
submenu_add_item(
|
|
||||||
submenu, "Info", SubmenuIndexInfo, ibutton_scene_saved_key_menu_submenu_callback, ibutton);
|
|
||||||
|
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneSavedKeyMenu));
|
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneSavedKeyMenu));
|
||||||
|
|
||||||
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) {
|
bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event.type == SceneManagerEventTypeCustom) {
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
scene_manager_set_scene_state(
|
scene_manager_set_scene_state(scene_manager, iButtonSceneSavedKeyMenu, event.event);
|
||||||
ibutton->scene_manager, iButtonSceneSavedKeyMenu, event.event);
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
if(event.event == SubmenuIndexEmulate) {
|
if(event.event == SubmenuIndexEmulate) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
scene_manager_next_scene(scene_manager, iButtonSceneEmulate);
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||||
} else if(event.event == SubmenuIndexWrite) {
|
} else if(event.event == SubmenuIndexWriteBlank) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
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) {
|
} 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) {
|
} 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) {
|
} 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;
|
return consumed;
|
||||||
|
|||||||
@@ -3,11 +3,11 @@
|
|||||||
void ibutton_scene_select_key_on_enter(void* context) {
|
void ibutton_scene_select_key_on_enter(void* context) {
|
||||||
iButton* ibutton = 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(
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
ibutton->scene_manager, iButtonSceneStart);
|
ibutton->scene_manager, iButtonSceneStart);
|
||||||
} else {
|
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSavedKeyMenu);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,21 +8,15 @@ enum SubmenuIndex {
|
|||||||
SubmenuIndexAdd,
|
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) {
|
void ibutton_scene_start_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
Submenu* submenu = ibutton->submenu;
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
submenu_add_item(
|
ibutton_reset_key(ibutton);
|
||||||
submenu, "Read", SubmenuIndexRead, ibutton_scene_start_submenu_callback, ibutton);
|
|
||||||
submenu_add_item(
|
submenu_add_item(submenu, "Read", SubmenuIndexRead, ibutton_submenu_callback, ibutton);
|
||||||
submenu, "Saved", SubmenuIndexSaved, ibutton_scene_start_submenu_callback, ibutton);
|
submenu_add_item(submenu, "Saved", SubmenuIndexSaved, ibutton_submenu_callback, ibutton);
|
||||||
submenu_add_item(
|
submenu_add_item(submenu, "Add Manually", SubmenuIndexAdd, ibutton_submenu_callback, ibutton);
|
||||||
submenu, "Add Manually", SubmenuIndexAdd, ibutton_scene_start_submenu_callback, ibutton);
|
|
||||||
|
|
||||||
submenu_set_selected_item(
|
submenu_set_selected_item(
|
||||||
submenu, scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneStart));
|
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);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
||||||
} else if(event.event == SubmenuIndexSaved) {
|
} else if(event.event == SubmenuIndexSaved) {
|
||||||
furi_string_set(ibutton->file_path, IBUTTON_APP_FOLDER);
|
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
|
||||||
} else if(event.event == SubmenuIndexAdd) {
|
} else if(event.event == SubmenuIndexAdd) {
|
||||||
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType);
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType);
|
||||||
|
|||||||
26
applications/main/ibutton/scenes/ibutton_scene_view_data.c
Normal file
26
applications/main/ibutton/scenes/ibutton_scene_view_data.c
Normal file
@@ -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);
|
||||||
|
}
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
#include "../ibutton_i.h"
|
#include "../ibutton_i.h"
|
||||||
#include "toolbox/path.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
iButtonSceneWriteStateDefault,
|
iButtonSceneWriteStateDefault,
|
||||||
@@ -13,61 +12,46 @@ static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult
|
|||||||
|
|
||||||
void ibutton_scene_write_on_enter(void* context) {
|
void ibutton_scene_write_on_enter(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
|
furi_assert(ibutton->write_mode != iButtonWriteModeInvalid);
|
||||||
|
|
||||||
iButtonKey* key = ibutton->key;
|
iButtonKey* key = ibutton->key;
|
||||||
|
iButtonWorker* worker = ibutton->worker;
|
||||||
|
const iButtonProtocolId protocol_id = ibutton_key_get_protocol_id(key);
|
||||||
|
|
||||||
Widget* widget = ibutton->widget;
|
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;
|
furi_string_printf(
|
||||||
key_name = furi_string_alloc();
|
tmp,
|
||||||
if(furi_string_end_with(ibutton->file_path, IBUTTON_APP_EXTENSION)) {
|
"%s\n[%s]",
|
||||||
path_extract_filename(ibutton->file_path, key_name, true);
|
ibutton->key_name,
|
||||||
}
|
ibutton_protocols_get_name(ibutton->protocols, protocol_id));
|
||||||
|
|
||||||
// check that stored key has name
|
widget_add_text_box_element(
|
||||||
if(!furi_string_empty(key_name)) {
|
widget, 52, 38, 75, 26, AlignCenter, AlignCenter, furi_string_get_cstr(tmp), true);
|
||||||
ibutton_text_store_set(ibutton, "%s", furi_string_get_cstr(key_name));
|
|
||||||
} else {
|
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
|
||||||
// if not, show key data
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
furi_string_set(tmp, "iButton\nwriting ");
|
||||||
case iButtonKeyDS1990:
|
|
||||||
ibutton_text_store_set(
|
if(ibutton->write_mode == iButtonWriteModeBlank) {
|
||||||
ibutton,
|
furi_string_cat(tmp, "Blank");
|
||||||
"%02X %02X %02X %02X\n%02X %02X %02X %02X",
|
ibutton_worker_write_blank_start(worker, key);
|
||||||
key_data[0],
|
|
||||||
key_data[1],
|
} else if(ibutton->write_mode == iButtonWriteModeCopy) {
|
||||||
key_data[2],
|
furi_string_cat(tmp, "Copy");
|
||||||
key_data[3],
|
ibutton_worker_write_copy_start(worker, key);
|
||||||
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_string_multiline_element(
|
widget_add_string_multiline_element(
|
||||||
widget, 90, 10, AlignCenter, AlignTop, FontPrimary, "iButton\nwriting");
|
widget, 88, 10, AlignCenter, AlignTop, FontPrimary, furi_string_get_cstr(tmp));
|
||||||
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);
|
|
||||||
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulateStart);
|
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) {
|
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) {
|
void ibutton_scene_write_on_exit(void* context) {
|
||||||
iButton* ibutton = context;
|
iButton* ibutton = context;
|
||||||
ibutton_worker_stop(ibutton->key_worker);
|
ibutton->write_mode = iButtonWriteModeInvalid;
|
||||||
|
|
||||||
|
ibutton_worker_stop(ibutton->worker);
|
||||||
widget_reset(ibutton->widget);
|
widget_reset(ibutton->widget);
|
||||||
|
|
||||||
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
ibutton_notification_message(ibutton, iButtonNotificationMessageBlinkStop);
|
||||||
|
|||||||
@@ -54,6 +54,7 @@ typedef enum {
|
|||||||
SubGhzLoadKeyStateOK,
|
SubGhzLoadKeyStateOK,
|
||||||
SubGhzLoadKeyStateParseErr,
|
SubGhzLoadKeyStateParseErr,
|
||||||
SubGhzLoadKeyStateOnlyRx,
|
SubGhzLoadKeyStateOnlyRx,
|
||||||
|
SubGhzLoadKeyStateProtocolDescriptionErr,
|
||||||
} SubGhzLoadKeyState;
|
} SubGhzLoadKeyState;
|
||||||
|
|
||||||
/** SubGhzLock */
|
/** SubGhzLock */
|
||||||
|
|||||||
@@ -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->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||||
subghz->txrx->receiver,
|
subghz->txrx->receiver,
|
||||||
subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
subghz_history_get_protocol_name(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
||||||
|
|
||||||
if(subghz->txrx->decoder_result) {
|
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_protocol_decoder_base_deserialize(
|
||||||
subghz->txrx->decoder_result,
|
subghz->txrx->decoder_result,
|
||||||
subghz_history_get_raw_data(subghz->txrx->history, subghz->txrx->idx_menu_chosen));
|
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,
|
||||||
subghz_history_get_raw_data(
|
subghz_history_get_raw_data(
|
||||||
subghz->txrx->history, subghz->txrx->idx_menu_chosen))) {
|
subghz->txrx->history, subghz->txrx->idx_menu_chosen))) {
|
||||||
scene_manager_next_scene(subghz->scene_manager, SubGhzSceneShowOnlyRx);
|
|
||||||
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
if(subghz->txrx->txrx_state == SubGhzTxRxStateTx) {
|
||||||
subghz_tx_stop(subghz);
|
subghz_tx_stop(subghz);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,8 +36,9 @@ bool subghz_scene_set_type_submenu_gen_data_protocol(
|
|||||||
do {
|
do {
|
||||||
Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data);
|
Stream* fff_data_stream = flipper_format_get_raw_stream(subghz->txrx->fff_data);
|
||||||
stream_clean(fff_data_stream);
|
stream_clean(fff_data_stream);
|
||||||
if(!subghz_protocol_decoder_base_serialize(
|
if(subghz_protocol_decoder_base_serialize(
|
||||||
subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset)) {
|
subghz->txrx->decoder_result, subghz->txrx->fff_data, subghz->txrx->preset) !=
|
||||||
|
SubGhzProtocolStatusOk) {
|
||||||
FURI_LOG_E(TAG, "Unable to serialize");
|
FURI_LOG_E(TAG, "Unable to serialize");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -363,8 +364,7 @@ bool subghz_scene_set_type_on_event(void* context, SceneManagerEvent event) {
|
|||||||
case SubmenuIndexSomfyTelis:
|
case SubmenuIndexSomfyTelis:
|
||||||
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz->txrx->environment, SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME);
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_SOMFY_TELIS_NAME);
|
||||||
subghz_preset_init(
|
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_somfy_telis_create_data(
|
subghz_protocol_somfy_telis_create_data(
|
||||||
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
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:
|
case SubmenuIndexDoorHan_433_92:
|
||||||
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
||||||
subghz_preset_init(
|
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_keeloq_create_data(
|
subghz_protocol_keeloq_create_data(
|
||||||
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
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:
|
case SubmenuIndexNiceFlorS_433_92:
|
||||||
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME);
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME);
|
||||||
subghz_preset_init(
|
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_nice_flor_s_create_data(
|
subghz_protocol_nice_flor_s_create_data(
|
||||||
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
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:
|
case SubmenuIndexNiceOne_433_92:
|
||||||
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME);
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_NICE_FLOR_S_NAME);
|
||||||
subghz_preset_init(
|
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_nice_flor_s_create_data(
|
subghz_protocol_nice_flor_s_create_data(
|
||||||
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
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:
|
case SubmenuIndexNiceSmilo_433_92:
|
||||||
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
subghz->txrx->transmitter = subghz_transmitter_alloc_init(
|
||||||
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
subghz->txrx->environment, SUBGHZ_PROTOCOL_KEELOQ_NAME);
|
||||||
subghz_preset_init(
|
subghz_preset_init(subghz, "AM650", 433920000, NULL, 0);
|
||||||
subghz, "AM650", subghz_setting_get_default_frequency(subghz->setting), NULL, 0);
|
|
||||||
if(subghz->txrx->transmitter) {
|
if(subghz->txrx->transmitter) {
|
||||||
subghz_protocol_keeloq_create_data(
|
subghz_protocol_keeloq_create_data(
|
||||||
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
subghz_transmitter_get_protocol_instance(subghz->txrx->transmitter),
|
||||||
|
|||||||
@@ -14,9 +14,8 @@ void subghz_scene_transmitter_callback(SubGhzCustomEvent event, void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_scene_transmitter_update_data_show(void* context) {
|
bool subghz_scene_transmitter_update_data_show(void* context) {
|
||||||
//ToDo Fix
|
|
||||||
SubGhz* subghz = context;
|
SubGhz* subghz = context;
|
||||||
|
bool ret = false;
|
||||||
if(subghz->txrx->decoder_result) {
|
if(subghz->txrx->decoder_result) {
|
||||||
FuriString* key_str;
|
FuriString* key_str;
|
||||||
FuriString* frequency_str;
|
FuriString* frequency_str;
|
||||||
@@ -27,8 +26,8 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
|
|||||||
modulation_str = furi_string_alloc();
|
modulation_str = furi_string_alloc();
|
||||||
uint8_t show_button = 0;
|
uint8_t show_button = 0;
|
||||||
|
|
||||||
subghz_protocol_decoder_base_deserialize(
|
if(subghz_protocol_decoder_base_deserialize(
|
||||||
subghz->txrx->decoder_result, subghz->txrx->fff_data);
|
subghz->txrx->decoder_result, subghz->txrx->fff_data) == SubGhzProtocolStatusOk) {
|
||||||
subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, key_str);
|
subghz_protocol_decoder_base_get_string(subghz->txrx->decoder_result, key_str);
|
||||||
|
|
||||||
if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
|
if((subghz->txrx->decoder_result->protocol->flag & SubGhzProtocolFlag_Send) ==
|
||||||
@@ -43,14 +42,13 @@ bool subghz_scene_transmitter_update_data_show(void* context) {
|
|||||||
furi_string_get_cstr(frequency_str),
|
furi_string_get_cstr(frequency_str),
|
||||||
furi_string_get_cstr(modulation_str),
|
furi_string_get_cstr(modulation_str),
|
||||||
show_button);
|
show_button);
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
furi_string_free(frequency_str);
|
furi_string_free(frequency_str);
|
||||||
furi_string_free(modulation_str);
|
furi_string_free(modulation_str);
|
||||||
furi_string_free(key_str);
|
furi_string_free(key_str);
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
return false;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
void subghz_scene_transmitter_on_enter(void* context) {
|
void subghz_scene_transmitter_on_enter(void* context) {
|
||||||
|
|||||||
@@ -154,7 +154,6 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
|
|||||||
FURI_LOG_E(TAG, "Missing Protocol");
|
FURI_LOG_E(TAG, "Missing Protocol");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
//ToDo FIX
|
|
||||||
if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
|
if(!flipper_format_insert_or_update_uint32(flipper_format, "Repeat", &repeat, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable Repeat");
|
FURI_LOG_E(TAG, "Unable Repeat");
|
||||||
break;
|
break;
|
||||||
@@ -164,7 +163,8 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
|
|||||||
subghz->txrx->environment, furi_string_get_cstr(temp_str));
|
subghz->txrx->environment, furi_string_get_cstr(temp_str));
|
||||||
|
|
||||||
if(subghz->txrx->transmitter) {
|
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) {
|
if(strcmp(furi_string_get_cstr(subghz->txrx->preset->name), "") != 0) {
|
||||||
subghz_begin(
|
subghz_begin(
|
||||||
subghz,
|
subghz,
|
||||||
@@ -187,7 +187,12 @@ bool subghz_tx_start(SubGhz* subghz, FlipperFormat* flipper_format) {
|
|||||||
//Start TX
|
//Start TX
|
||||||
furi_hal_subghz_start_async_tx(
|
furi_hal_subghz_start_async_tx(
|
||||||
subghz_transmitter_yield, subghz->txrx->transmitter);
|
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) {
|
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->decoder_result = subghz_receiver_search_decoder_base_by_name(
|
||||||
subghz->txrx->receiver, furi_string_get_cstr(temp_str));
|
subghz->txrx->receiver, furi_string_get_cstr(temp_str));
|
||||||
if(subghz->txrx->decoder_result) {
|
if(subghz->txrx->decoder_result) {
|
||||||
if(!subghz_protocol_decoder_base_deserialize(
|
SubGhzProtocolStatus status = subghz_protocol_decoder_base_deserialize(
|
||||||
subghz->txrx->decoder_result, subghz->txrx->fff_data)) {
|
subghz->txrx->decoder_result, subghz->txrx->fff_data);
|
||||||
|
if(status != SubGhzProtocolStatusOk) {
|
||||||
|
load_key_state = SubGhzLoadKeyStateProtocolDescriptionErr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else {
|
} 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");
|
dialog_message_show_storage_error(subghz->dialogs, "Cannot parse\nfile");
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
case SubGhzLoadKeyStateProtocolDescriptionErr:
|
||||||
|
if(show_dialog) {
|
||||||
|
dialog_message_show_storage_error(
|
||||||
|
subghz->dialogs, "Error in protocol\nparameters\ndescription");
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
|
||||||
case SubGhzLoadKeyStateOnlyRx:
|
case SubGhzLoadKeyStateOnlyRx:
|
||||||
if(show_dialog) {
|
if(show_dialog) {
|
||||||
|
|||||||
@@ -376,7 +376,17 @@ int32_t hid_ble_app(void* p) {
|
|||||||
// Wait 2nd core to update nvm storage
|
// Wait 2nd core to update nvm storage
|
||||||
furi_delay_ms(200);
|
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)) {
|
if(!bt_set_profile(app->bt, BtProfileHidKeyboard)) {
|
||||||
FURI_LOG_E(TAG, "Failed to switch to HID profile");
|
FURI_LOG_E(TAG, "Failed to switch to HID profile");
|
||||||
|
|||||||
@@ -23,7 +23,7 @@
|
|||||||
#include "views/hid_mouse_jiggler.h"
|
#include "views/hid_mouse_jiggler.h"
|
||||||
#include "views/hid_tiktok.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 {
|
typedef enum {
|
||||||
HidTransportUsb,
|
HidTransportUsb,
|
||||||
|
|||||||
@@ -78,7 +78,8 @@ typedef struct {
|
|||||||
uint8_t key_index;
|
uint8_t key_index;
|
||||||
iButtonWorker* worker;
|
iButtonWorker* worker;
|
||||||
iButtonKey* key;
|
iButtonKey* key;
|
||||||
iButtonKeyType keytype;
|
iButtonProtocolId keytype;
|
||||||
|
iButtonProtocols* protocols;
|
||||||
bool workr_rund;
|
bool workr_rund;
|
||||||
bool enter_rerun;
|
bool enter_rerun;
|
||||||
bool attack_stop_called;
|
bool attack_stop_called;
|
||||||
|
|||||||
@@ -72,14 +72,15 @@ void ibtnfuzzer_scene_run_attack_on_enter(iBtnFuzzerState* context) {
|
|||||||
context->time_between_cards = 8;
|
context->time_between_cards = 8;
|
||||||
context->attack_step = 0;
|
context->attack_step = 0;
|
||||||
context->attack_stop_called = false;
|
context->attack_stop_called = false;
|
||||||
context->key = ibutton_key_alloc();
|
context->protocols = ibutton_protocols_alloc();
|
||||||
context->worker = ibutton_worker_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) {
|
if(context->proto == Metakom) {
|
||||||
context->keytype = iButtonKeyMetakom;
|
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Metakom");
|
||||||
} else if(context->proto == Cyfral) {
|
} else if(context->proto == Cyfral) {
|
||||||
context->keytype = iButtonKeyCyfral;
|
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "Cyfral");
|
||||||
} else {
|
} else {
|
||||||
context->keytype = iButtonKeyDS1990;
|
context->keytype = ibutton_protocols_get_id_by_name(context->protocols, "DS1990");
|
||||||
}
|
}
|
||||||
context->workr_rund = false;
|
context->workr_rund = false;
|
||||||
}
|
}
|
||||||
@@ -90,8 +91,9 @@ void ibtnfuzzer_scene_run_attack_on_exit(iBtnFuzzerState* context) {
|
|||||||
ibutton_worker_stop_thread(context->worker);
|
ibutton_worker_stop_thread(context->worker);
|
||||||
context->workr_rund = false;
|
context->workr_rund = false;
|
||||||
}
|
}
|
||||||
ibutton_worker_free(context->worker);
|
|
||||||
ibutton_key_free(context->key);
|
ibutton_key_free(context->key);
|
||||||
|
ibutton_worker_free(context->worker);
|
||||||
|
ibutton_protocols_free(context->protocols);
|
||||||
notification_message(context->notify, &sequence_blink_stop);
|
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(context->is_attacking) {
|
||||||
if(1 == counter) {
|
if(1 == counter) {
|
||||||
ibutton_worker_start_thread(context->worker);
|
ibutton_worker_start_thread(context->worker);
|
||||||
ibutton_key_set_type(context->key, context->keytype);
|
ibutton_key_set_protocol_id(context->key, context->keytype);
|
||||||
ibutton_key_set_data(
|
iButtonEditableData data;
|
||||||
context->key, context->payload, ibutton_key_get_size_by_type(context->keytype));
|
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);
|
ibutton_worker_emulate_start(context->worker, context->key);
|
||||||
context->workr_rund = true;
|
context->workr_rund = true;
|
||||||
} else if(0 == counter) {
|
} else if(0 == counter) {
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
#include <lib/toolbox/args.h>
|
#include <lib/toolbox/args.h>
|
||||||
#include <lib/flipper_format/flipper_format.h>
|
#include <lib/flipper_format/flipper_format.h>
|
||||||
|
|
||||||
#define ICLASS_ELITE_DICT_FLIPPER_PATH EXT_PATH("picopass/assets/iclass_elite_dict.txt")
|
#define ICLASS_ELITE_DICT_FLIPPER_NAME APP_DATA_PATH("assets/iclass_elite_dict.txt")
|
||||||
#define ICLASS_ELITE_DICT_USER_PATH EXT_PATH("picopass/assets/iclass_elite_dict_user.txt")
|
#define ICLASS_ELITE_DICT_USER_NAME APP_DATA_PATH("assets/iclass_elite_dict_user.txt")
|
||||||
|
|
||||||
#define TAG "IclassEliteDict"
|
#define TAG "IclassEliteDict"
|
||||||
|
|
||||||
@@ -21,10 +21,10 @@ bool iclass_elite_dict_check_presence(IclassEliteDictType dict_type) {
|
|||||||
|
|
||||||
bool dict_present = false;
|
bool dict_present = false;
|
||||||
if(dict_type == IclassEliteDictTypeFlipper) {
|
if(dict_type == IclassEliteDictTypeFlipper) {
|
||||||
dict_present = storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_PATH, NULL) ==
|
dict_present =
|
||||||
FSE_OK;
|
(storage_common_stat(storage, ICLASS_ELITE_DICT_FLIPPER_NAME, NULL) == FSE_OK);
|
||||||
} else if(dict_type == IclassEliteDictTypeUser) {
|
} 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);
|
furi_record_close(RECORD_STORAGE);
|
||||||
@@ -36,27 +36,26 @@ IclassEliteDict* iclass_elite_dict_alloc(IclassEliteDictType dict_type) {
|
|||||||
IclassEliteDict* dict = malloc(sizeof(IclassEliteDict));
|
IclassEliteDict* dict = malloc(sizeof(IclassEliteDict));
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
dict->stream = buffered_file_stream_alloc(storage);
|
dict->stream = buffered_file_stream_alloc(storage);
|
||||||
furi_record_close(RECORD_STORAGE);
|
|
||||||
FuriString* next_line = furi_string_alloc();
|
FuriString* next_line = furi_string_alloc();
|
||||||
|
|
||||||
bool dict_loaded = false;
|
bool dict_loaded = false;
|
||||||
do {
|
do {
|
||||||
if(dict_type == IclassEliteDictTypeFlipper) {
|
if(dict_type == IclassEliteDictTypeFlipper) {
|
||||||
if(!buffered_file_stream_open(
|
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);
|
buffered_file_stream_close(dict->stream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(dict_type == IclassEliteDictTypeUser) {
|
} else if(dict_type == IclassEliteDictTypeUser) {
|
||||||
if(!buffered_file_stream_open(
|
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);
|
buffered_file_stream_close(dict->stream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Read total amount of keys
|
// Read total amount of keys
|
||||||
while(true) {
|
while(true) { //-V547
|
||||||
if(!stream_read_line(dict->stream, next_line)) break;
|
if(!stream_read_line(dict->stream, next_line)) break;
|
||||||
if(furi_string_get_char(next_line, 0) == '#') continue;
|
if(furi_string_get_char(next_line, 0) == '#') continue;
|
||||||
if(furi_string_size(next_line) != ICLASS_ELITE_KEY_LINE_LEN) 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);
|
FURI_LOG_I(TAG, "Loaded dictionary with %lu keys", dict->total_keys);
|
||||||
} while(false);
|
} while(false);
|
||||||
|
|
||||||
if(!dict_loaded) {
|
if(!dict_loaded) { //-V547
|
||||||
buffered_file_stream_close(dict->stream);
|
buffered_file_stream_close(dict->stream);
|
||||||
free(dict);
|
free(dict);
|
||||||
dict = NULL;
|
dict = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
furi_string_free(next_line);
|
furi_string_free(next_line);
|
||||||
|
|
||||||
return dict;
|
return dict;
|
||||||
|
|||||||
@@ -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 picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) {
|
||||||
bool result = size > 0;
|
bool result = size > 0;
|
||||||
while(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) {
|
int32_t picopass_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
|
picopass_migrate_from_old_folder();
|
||||||
|
|
||||||
Picopass* picopass = picopass_alloc();
|
Picopass* picopass = picopass_alloc();
|
||||||
|
|
||||||
scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart);
|
scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart);
|
||||||
|
|||||||
@@ -48,13 +48,9 @@ static bool picopass_device_save_file(
|
|||||||
if(use_load_path && !furi_string_empty(dev->load_path)) {
|
if(use_load_path && !furi_string_empty(dev->load_path)) {
|
||||||
// Get directory name
|
// Get directory name
|
||||||
path_extract_dirname(furi_string_get_cstr(dev->load_path), temp_str);
|
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
|
// Make path to file to save
|
||||||
furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension);
|
furi_string_cat_printf(temp_str, "/%s%s", dev_name, extension);
|
||||||
} else {
|
} 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
|
// First remove picopass device file if it was saved
|
||||||
furi_string_printf(temp_str, "%s/%s%s", folder, dev_name, extension);
|
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) {
|
bool picopass_device_save(PicopassDevice* dev, const char* dev_name) {
|
||||||
if(dev->format == PicopassDeviceSaveFormatHF) {
|
if(dev->format == PicopassDeviceSaveFormatHF) {
|
||||||
return picopass_device_save_file(
|
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) {
|
} else if(dev->format == PicopassDeviceSaveFormatLF) {
|
||||||
return picopass_device_save_file(dev, dev_name, ANY_PATH("lfrfid"), ".rfid", true);
|
return picopass_device_save_file(dev, dev_name, ANY_PATH("lfrfid"), ".rfid", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -225,13 +222,12 @@ void picopass_device_free(PicopassDevice* picopass_dev) {
|
|||||||
bool picopass_file_select(PicopassDevice* dev) {
|
bool picopass_file_select(PicopassDevice* dev) {
|
||||||
furi_assert(dev);
|
furi_assert(dev);
|
||||||
|
|
||||||
// Input events and views are managed by file_browser
|
|
||||||
FuriString* picopass_app_folder;
|
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;
|
DialogsFileBrowserOptions browser_options;
|
||||||
dialog_file_browser_set_basic_options(&browser_options, PICOPASS_APP_EXTENSION, &I_Nfc_10px);
|
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(
|
bool res = dialog_file_browser_show(
|
||||||
dev->dialogs, dev->load_path, picopass_app_folder, &browser_options);
|
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);
|
furi_string_set(file_path, dev->load_path);
|
||||||
} else {
|
} else {
|
||||||
furi_string_printf(
|
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;
|
if(!storage_simply_remove(dev->storage, furi_string_get_cstr(file_path))) break;
|
||||||
deleted = true;
|
deleted = true;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
#define PICOPASS_AIA_BLOCK_INDEX 5
|
#define PICOPASS_AIA_BLOCK_INDEX 5
|
||||||
#define PICOPASS_PACS_CFG_BLOCK_INDEX 6
|
#define PICOPASS_PACS_CFG_BLOCK_INDEX 6
|
||||||
|
|
||||||
#define PICOPASS_APP_FOLDER ANY_PATH("picopass")
|
|
||||||
#define PICOPASS_APP_EXTENSION ".picopass"
|
#define PICOPASS_APP_EXTENSION ".picopass"
|
||||||
#define PICOPASS_APP_SHADOW_EXTENSION ".pas"
|
#define PICOPASS_APP_SHADOW_EXTENSION ".pas"
|
||||||
|
|
||||||
@@ -81,7 +80,6 @@ typedef struct {
|
|||||||
PicopassDeviceSaveFormat format;
|
PicopassDeviceSaveFormat format;
|
||||||
PicopassLoadingCallback loading_cb;
|
PicopassLoadingCallback loading_cb;
|
||||||
void* loading_cb_ctx;
|
void* loading_cb_ctx;
|
||||||
|
|
||||||
} PicopassDevice;
|
} PicopassDevice;
|
||||||
|
|
||||||
PicopassDevice* picopass_device_alloc();
|
PicopassDevice* picopass_device_alloc();
|
||||||
|
|||||||
@@ -31,12 +31,10 @@ void picopass_scene_save_name_on_enter(void* context) {
|
|||||||
dev_name_empty);
|
dev_name_empty);
|
||||||
|
|
||||||
FuriString* folder_path;
|
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)) {
|
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);
|
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(
|
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||||
|
|||||||
@@ -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);
|
furi_string_set(preset_str, preset_name_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool pcsg_block_generic_serialize(
|
SubGhzProtocolStatus pcsg_block_generic_serialize(
|
||||||
PCSGBlockGeneric* instance,
|
PCSGBlockGeneric* instance,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
bool res = false;
|
SubGhzProtocolStatus res = SubGhzProtocolStatusError;
|
||||||
FuriString* temp_str;
|
FuriString* temp_str;
|
||||||
temp_str = furi_string_alloc();
|
temp_str = furi_string_alloc();
|
||||||
do {
|
do {
|
||||||
@@ -75,15 +75,16 @@ bool pcsg_block_generic_serialize(
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = true;
|
res = SubGhzProtocolStatusOk;
|
||||||
} while(false);
|
} while(false);
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
return res;
|
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);
|
furi_assert(instance);
|
||||||
bool res = false;
|
SubGhzProtocolStatus res = SubGhzProtocolStatusError;
|
||||||
FuriString* temp_data = furi_string_alloc();
|
FuriString* temp_data = furi_string_alloc();
|
||||||
FuriString* temp_data2 = 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);
|
instance->result_msg = furi_string_alloc_set(temp_data);
|
||||||
}
|
}
|
||||||
|
|
||||||
res = true;
|
res = SubGhzProtocolStatusOk;
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
furi_string_free(temp_data);
|
furi_string_free(temp_data);
|
||||||
|
|||||||
@@ -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
|
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
||||||
* @return true On success
|
* @return true On success
|
||||||
*/
|
*/
|
||||||
bool pcsg_block_generic_serialize(
|
SubGhzProtocolStatus pcsg_block_generic_serialize(
|
||||||
PCSGBlockGeneric* instance,
|
PCSGBlockGeneric* instance,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -46,7 +46,8 @@ bool pcsg_block_generic_serialize(
|
|||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @return true On success
|
* @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);
|
float pcsg_block_generic_fahrenheit_to_celsius(float fahrenheit);
|
||||||
|
|
||||||
|
|||||||
@@ -288,7 +288,7 @@ uint8_t subghz_protocol_decoder_pocsag_get_hash_data(void* context) {
|
|||||||
return hash;
|
return hash;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool subghz_protocol_decoder_pocsag_serialize(
|
SubGhzProtocolStatus subghz_protocol_decoder_pocsag_serialize(
|
||||||
void* context,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -296,31 +296,35 @@ bool subghz_protocol_decoder_pocsag_serialize(
|
|||||||
SubGhzProtocolDecoderPocsag* instance = context;
|
SubGhzProtocolDecoderPocsag* instance = context;
|
||||||
uint32_t msg_len;
|
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);
|
msg_len = furi_string_size(instance->done_msg);
|
||||||
if(!flipper_format_write_uint32(flipper_format, "MsgLen", &msg_len, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "MsgLen", &msg_len, 1)) {
|
||||||
FURI_LOG_E(TAG, "Error adding MsgLen");
|
FURI_LOG_E(TAG, "Error adding MsgLen");
|
||||||
return false;
|
return SubGhzProtocolStatusError;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg);
|
uint8_t* s = (uint8_t*)furi_string_get_cstr(instance->done_msg);
|
||||||
if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) {
|
if(!flipper_format_write_hex(flipper_format, "Msg", s, msg_len)) {
|
||||||
FURI_LOG_E(TAG, "Error adding Msg");
|
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);
|
furi_assert(context);
|
||||||
SubGhzProtocolDecoderPocsag* instance = context;
|
SubGhzProtocolDecoderPocsag* instance = context;
|
||||||
bool ret = false;
|
SubGhzProtocolStatus ret = SubGhzProtocolStatusError;
|
||||||
uint32_t msg_len;
|
uint32_t msg_len;
|
||||||
uint8_t* buf;
|
uint8_t* buf;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!pcsg_block_generic_deserialize(&instance->generic, flipper_format)) {
|
if(SubGhzProtocolStatusOk !=
|
||||||
|
pcsg_block_generic_deserialize(&instance->generic, flipper_format)) {
|
||||||
break;
|
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);
|
furi_string_set_strn(instance->done_msg, (const char*)buf, msg_len);
|
||||||
free(buf);
|
free(buf);
|
||||||
|
|
||||||
ret = true;
|
ret = SubGhzProtocolStatusOk;
|
||||||
} while(false);
|
} while(false);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ bool spi_mem_scene_start_on_event(void* context, SceneManagerEvent event) {
|
|||||||
scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect);
|
scene_manager_next_scene(app->scene_manager, SPIMemSceneChipDetect);
|
||||||
success = true;
|
success = true;
|
||||||
} else if(event.event == SPIMemSceneStartSubmenuIndexSaved) {
|
} 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);
|
scene_manager_next_scene(app->scene_manager, SPIMemSceneSelectFile);
|
||||||
success = true;
|
success = true;
|
||||||
} else if(event.event == SPIMemSceneStartSubmenuIndexErase) {
|
} else if(event.event == SPIMemSceneStartSubmenuIndexErase) {
|
||||||
|
|||||||
@@ -16,9 +16,9 @@ static bool spi_mem_back_event_callback(void* context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
SPIMemApp* spi_mem_alloc(void) {
|
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->gui = furi_record_open(RECORD_GUI);
|
||||||
instance->notifications = furi_record_open(RECORD_NOTIFICATION);
|
instance->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||||
instance->view_dispatcher = view_dispatcher_alloc();
|
instance->view_dispatcher = view_dispatcher_alloc();
|
||||||
@@ -37,7 +37,8 @@ SPIMemApp* spi_mem_alloc(void) {
|
|||||||
instance->text_input = text_input_alloc();
|
instance->text_input = text_input_alloc();
|
||||||
instance->mode = SPIMemModeUnknown;
|
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_enable_queue(instance->view_dispatcher);
|
||||||
view_dispatcher_set_event_callback_context(instance->view_dispatcher, instance);
|
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);
|
furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_external);
|
||||||
scene_manager_next_scene(instance->scene_manager, SPIMemSceneStart);
|
scene_manager_next_scene(instance->scene_manager, SPIMemSceneStart);
|
||||||
return instance;
|
return instance;
|
||||||
}
|
} //-V773
|
||||||
|
|
||||||
void spi_mem_free(SPIMemApp* instance) {
|
void spi_mem_free(SPIMemApp* instance) {
|
||||||
view_dispatcher_remove_view(instance->view_dispatcher, SPIMemViewSubmenu);
|
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) {
|
int32_t spi_mem_app(void* p) {
|
||||||
UNUSED(p);
|
UNUSED(p);
|
||||||
SPIMemApp* instance = spi_mem_alloc();
|
SPIMemApp* instance = spi_mem_alloc();
|
||||||
spi_mem_file_create_folder(instance);
|
|
||||||
view_dispatcher_run(instance->view_dispatcher);
|
view_dispatcher_run(instance->view_dispatcher);
|
||||||
spi_mem_free(instance);
|
spi_mem_free(instance);
|
||||||
return 0;
|
return 0;
|
||||||
|
|||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
#define TAG "SPIMem"
|
#define TAG "SPIMem"
|
||||||
#define SPI_MEM_FILE_EXTENSION ".bin"
|
#define SPI_MEM_FILE_EXTENSION ".bin"
|
||||||
#define SPI_MEM_FILE_FOLDER EXT_PATH("spimem")
|
|
||||||
#define SPI_MEM_FILE_NAME_SIZE 100
|
#define SPI_MEM_FILE_NAME_SIZE 100
|
||||||
#define SPI_MEM_TEXT_BUFFER_SIZE 128
|
#define SPI_MEM_TEXT_BUFFER_SIZE 128
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,5 @@
|
|||||||
#include "spi_mem_app_i.h"
|
#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) {
|
bool spi_mem_file_delete(SPIMemApp* app) {
|
||||||
return (storage_simply_remove(app->storage, furi_string_get_cstr(app->file_path)));
|
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) {
|
bool spi_mem_file_select(SPIMemApp* app) {
|
||||||
DialogsFileBrowserOptions browser_options;
|
DialogsFileBrowserOptions browser_options;
|
||||||
dialog_file_browser_set_basic_options(&browser_options, SPI_MEM_FILE_EXTENSION, &I_Dip8_10px);
|
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 =
|
bool success =
|
||||||
dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
|
dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
|
||||||
return success;
|
return success;
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include "spi_mem_app.h"
|
#include "spi_mem_app.h"
|
||||||
|
|
||||||
void spi_mem_file_create_folder(SPIMemApp* app);
|
|
||||||
bool spi_mem_file_select(SPIMemApp* app);
|
bool spi_mem_file_select(SPIMemApp* app);
|
||||||
bool spi_mem_file_create(SPIMemApp* app, const char* file_name);
|
bool spi_mem_file_create(SPIMemApp* app, const char* file_name);
|
||||||
bool spi_mem_file_delete(SPIMemApp* app);
|
bool spi_mem_file_delete(SPIMemApp* app);
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
#include <furi.h>
|
#include <furi.h>
|
||||||
#include <furi_hal.h>
|
#include <furi_hal.h>
|
||||||
|
|
||||||
#define WS_VERSION_APP "0.7"
|
#define WS_VERSION_APP "0.8"
|
||||||
#define WS_DEVELOPED "SkorP"
|
#define WS_DEVELOPED "SkorP"
|
||||||
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
#define WS_GITHUB "https://github.com/flipperdevices/flipperzero-firmware"
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -267,22 +267,14 @@ bool ws_protocol_decoder_acurite_592txr_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderAcurite_592TXR* instance = context;
|
WSProtocolDecoderAcurite_592TXR* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_acurite_592txr_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_acurite_592txr_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderAcurite_592TXR instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_592txr_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderAcurite_592TXR.
|
* Deserialize data WSProtocolDecoderAcurite_592TXR.
|
||||||
* @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance
|
* @param context Pointer to a WSProtocolDecoderAcurite_592TXR instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -208,22 +208,14 @@ bool ws_protocol_decoder_acurite_606tx_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderAcurite_606TX* instance = context;
|
WSProtocolDecoderAcurite_606TX* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_acurite_606tx_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_acurite_606tx_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_606tx_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderAcurite_606TX.
|
* Deserialize data WSProtocolDecoderAcurite_606TX.
|
||||||
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
* @param context Pointer to a WSProtocolDecoderAcurite_606TX instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -208,22 +208,14 @@ bool ws_protocol_decoder_acurite_609txc_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderAcurite_609TXC* instance = context;
|
WSProtocolDecoderAcurite_609TXC* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_acurite_609txc_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_acurite_609txc_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderAcurite_609TXC instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_acurite_609txc_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderAcurite_609TXC.
|
* Deserialize data WSProtocolDecoderAcurite_609TXC.
|
||||||
* @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance
|
* @param context Pointer to a WSProtocolDecoderAcurite_609TXC instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -237,22 +237,14 @@ bool ws_protocol_decoder_ambient_weather_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderAmbient_Weather* instance = context;
|
WSProtocolDecoderAmbient_Weather* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_ambient_weather_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
if(instance->generic.data_count_bit !=
|
|
||||||
ws_protocol_ambient_weather_const.min_count_bit_for_found) {
|
|
||||||
FURI_LOG_E(TAG, "Wrong number of bits in key");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ret = true;
|
|
||||||
} while(false);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_ambient_weather_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_ambient_weather_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderAmbient_Weather.
|
* Deserialize data WSProtocolDecoderAmbient_Weather.
|
||||||
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
* @param context Pointer to a WSProtocolDecoderAmbient_Weather instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -219,22 +219,12 @@ bool ws_protocol_decoder_auriol_th_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderAuriol_TH* instance = context;
|
WSProtocolDecoderAuriol_TH* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_auriol_th_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_auriol_th_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderAuriol_TH instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_auriol_th_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderAuriol_TH.
|
* Deserialize data WSProtocolDecoderAuriol_TH.
|
||||||
* @param context Pointer to a WSProtocolDecoderAuriol_TH instance
|
* @param context Pointer to a WSProtocolDecoderAuriol_TH instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -226,22 +226,12 @@ bool ws_protocol_decoder_gt_wt_02_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderGT_WT02* instance = context;
|
WSProtocolDecoderGT_WT02* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_gt_wt_02_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_gt_wt_02_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderGT_WT02 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_gt_wt_02_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderGT_WT02.
|
* Deserialize data WSProtocolDecoderGT_WT02.
|
||||||
* @param context Pointer to a WSProtocolDecoderGT_WT02 instance
|
* @param context Pointer to a WSProtocolDecoderGT_WT02 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -301,22 +301,12 @@ bool ws_protocol_decoder_gt_wt_03_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderGT_WT03* instance = context;
|
WSProtocolDecoderGT_WT03* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_gt_wt_03_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_gt_wt_03_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderGT_WT03 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_gt_wt_03_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderGT_WT03.
|
* Deserialize data WSProtocolDecoderGT_WT03.
|
||||||
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
|
* @param context Pointer to a WSProtocolDecoderGT_WT03 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context) {
|
|||||||
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_protocol_decoder_infactory_serialize(
|
SubGhzProtocolStatus ws_protocol_decoder_infactory_serialize(
|
||||||
void* context,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -257,22 +257,12 @@ bool ws_protocol_decoder_infactory_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderInfactory* instance = context;
|
WSProtocolDecoderInfactory* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_infactory_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_infactory_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -56,9 +56,9 @@ uint8_t ws_protocol_decoder_infactory_get_hash_data(void* context);
|
|||||||
* @param context Pointer to a WSProtocolDecoderInfactory instance
|
* @param context Pointer to a WSProtocolDecoderInfactory instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_infactory_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderInfactory.
|
* Deserialize data WSProtocolDecoderInfactory.
|
||||||
* @param context Pointer to a WSProtocolDecoderInfactory instance
|
* @param context Pointer to a WSProtocolDecoderInfactory instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -290,22 +290,12 @@ bool ws_protocol_decoder_lacrosse_tx_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderLaCrosse_TX* instance = context;
|
WSProtocolDecoderLaCrosse_TX* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_lacrosse_tx_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_lacrosse_tx_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderLaCrosse_TX instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_lacrosse_tx_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderLaCrosse_TX.
|
* Deserialize data WSProtocolDecoderLaCrosse_TX.
|
||||||
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -256,24 +256,15 @@ bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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,
|
void* context,
|
||||||
FlipperFormat* flipper_format) {
|
FlipperFormat* flipper_format) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
WSProtocolDecoderLaCrosse_TX141THBv2* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_lacrosse_tx141thbv2_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_lacrosse_tx141thbv2_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,9 @@ bool ws_protocol_decoder_lacrosse_tx141thbv2_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderLaCrosse_TX141THBv2.
|
* Deserialize data WSProtocolDecoderLaCrosse_TX141THBv2.
|
||||||
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
* @param context Pointer to a WSProtocolDecoderLaCrosse_TX141THBv2 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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,
|
void* context,
|
||||||
FlipperFormat* flipper_format);
|
FlipperFormat* flipper_format);
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -225,22 +225,12 @@ bool ws_protocol_decoder_nexus_th_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderNexus_TH* instance = context;
|
WSProtocolDecoderNexus_TH* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_nexus_th_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_nexus_th_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderNexus_TH instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_nexus_th_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderNexus_TH.
|
* Deserialize data WSProtocolDecoderNexus_TH.
|
||||||
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
|
* @param context Pointer to a WSProtocolDecoderNexus_TH instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -302,17 +302,19 @@ uint8_t ws_protocol_decoder_oregon2_get_hash_data(void* context) {
|
|||||||
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
&instance->decoder, (instance->decoder.decode_count_bit / 8) + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_protocol_decoder_oregon2_serialize(
|
SubGhzProtocolStatus ws_protocol_decoder_oregon2_serialize(
|
||||||
void* context,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
furi_assert(context);
|
furi_assert(context);
|
||||||
WSProtocolDecoderOregon2* instance = 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;
|
uint32_t temp = instance->var_bits;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "VarBits", &temp, 1)) {
|
||||||
FURI_LOG_E(TAG, "Error adding VarBits");
|
FURI_LOG_E(TAG, "Error adding VarBits");
|
||||||
return false;
|
return SubGhzProtocolStatusErrorParserOthers;
|
||||||
}
|
}
|
||||||
if(!flipper_format_write_hex(
|
if(!flipper_format_write_hex(
|
||||||
flipper_format,
|
flipper_format,
|
||||||
@@ -320,22 +322,25 @@ bool ws_protocol_decoder_oregon2_serialize(
|
|||||||
(const uint8_t*)&instance->var_data,
|
(const uint8_t*)&instance->var_data,
|
||||||
sizeof(instance->var_data))) {
|
sizeof(instance->var_data))) {
|
||||||
FURI_LOG_E(TAG, "Error adding VarData");
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderOregon2* instance = context;
|
WSProtocolDecoderOregon2* instance = context;
|
||||||
bool ret = false;
|
|
||||||
uint32_t temp_data;
|
uint32_t temp_data;
|
||||||
|
SubGhzProtocolStatus ret = SubGhzProtocolStatusError;
|
||||||
do {
|
do {
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
ret = ws_block_generic_deserialize(&instance->generic, flipper_format);
|
||||||
|
if(ret != SubGhzProtocolStatusOk) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "VarBits", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing VarLen");
|
FURI_LOG_E(TAG, "Missing VarLen");
|
||||||
|
ret = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->var_bits = (uint8_t)temp_data;
|
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,
|
(uint8_t*)&instance->var_data,
|
||||||
sizeof(instance->var_data))) { //-V1051
|
sizeof(instance->var_data))) { //-V1051
|
||||||
FURI_LOG_E(TAG, "Missing VarData");
|
FURI_LOG_E(TAG, "Missing VarData");
|
||||||
|
ret = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(instance->generic.data_count_bit != ws_oregon2_const.min_count_bit_for_found) {
|
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);
|
FURI_LOG_E(TAG, "Wrong number of bits in key: %d", instance->generic.data_count_bit);
|
||||||
|
ret = SubGhzProtocolStatusErrorValueBitCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
ret = true;
|
|
||||||
} while(false);
|
} while(false);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -292,22 +292,12 @@ bool ws_protocol_decoder_oregon_v1_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderOregon_V1* instance = context;
|
WSProtocolDecoderOregon_V1* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_oregon_v1_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_oregon_v1_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderOregon_V1 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_oregon_v1_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderOregon_V1.
|
* Deserialize data WSProtocolDecoderOregon_V1.
|
||||||
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
|
* @param context Pointer to a WSProtocolDecoderOregon_V1 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -220,22 +220,14 @@ bool ws_protocol_decoder_thermopro_tx4_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderThermoPRO_TX4* instance = context;
|
WSProtocolDecoderThermoPRO_TX4* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic,
|
||||||
if(!ws_block_generic_deserialize(&instance->generic, flipper_format)) {
|
flipper_format,
|
||||||
break;
|
ws_protocol_thermopro_tx4_const.min_count_bit_for_found);
|
||||||
}
|
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_thermopro_tx4_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_thermopro_tx4_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderThermoPRO_TX4.
|
* Deserialize data WSProtocolDecoderThermoPRO_TX4.
|
||||||
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
|
* @param context Pointer to a WSProtocolDecoderThermoPRO_TX4 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
&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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
@@ -255,21 +255,12 @@ bool ws_protocol_decoder_tx_8300_serialize(
|
|||||||
return ws_block_generic_serialize(&instance->generic, flipper_format, preset);
|
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);
|
furi_assert(context);
|
||||||
WSProtocolDecoderTX_8300* instance = context;
|
WSProtocolDecoderTX_8300* instance = context;
|
||||||
bool ret = false;
|
return ws_block_generic_deserialize_check_count_bit(
|
||||||
do {
|
&instance->generic, flipper_format, ws_protocol_tx_8300_const.min_count_bit_for_found);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) {
|
void ws_protocol_decoder_tx_8300_get_string(void* context, FuriString* output) {
|
||||||
|
|||||||
@@ -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 context Pointer to a WSProtocolDecoderTX_8300 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
void* context,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -67,9 +67,10 @@ bool ws_protocol_decoder_tx_8300_serialize(
|
|||||||
* Deserialize data WSProtocolDecoderTX_8300.
|
* Deserialize data WSProtocolDecoderTX_8300.
|
||||||
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
|
* @param context Pointer to a WSProtocolDecoderTX_8300 instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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.
|
* Getting a textual representation of the received data.
|
||||||
|
|||||||
@@ -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);
|
furi_string_set(preset_str, preset_name_temp);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ws_block_generic_serialize(
|
SubGhzProtocolStatus ws_block_generic_serialize(
|
||||||
WSBlockGeneric* instance,
|
WSBlockGeneric* instance,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset) {
|
SubGhzRadioPreset* preset) {
|
||||||
furi_assert(instance);
|
furi_assert(instance);
|
||||||
bool res = false;
|
SubGhzProtocolStatus res = SubGhzProtocolStatusError;
|
||||||
FuriString* temp_str;
|
FuriString* temp_str;
|
||||||
temp_str = furi_string_alloc();
|
temp_str = furi_string_alloc();
|
||||||
do {
|
do {
|
||||||
@@ -34,11 +34,13 @@ bool ws_block_generic_serialize(
|
|||||||
if(!flipper_format_write_header_cstr(
|
if(!flipper_format_write_header_cstr(
|
||||||
flipper_format, WS_KEY_FILE_TYPE, WS_KEY_FILE_VERSION)) {
|
flipper_format, WS_KEY_FILE_TYPE, WS_KEY_FILE_VERSION)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add header");
|
FURI_LOG_E(TAG, "Unable to add header");
|
||||||
|
res = SubGhzProtocolStatusErrorParserHeader;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Frequency", &preset->frequency, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Frequency");
|
FURI_LOG_E(TAG, "Unable to add Frequency");
|
||||||
|
res = SubGhzProtocolStatusErrorParserFrequency;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -46,34 +48,40 @@ bool ws_block_generic_serialize(
|
|||||||
if(!flipper_format_write_string_cstr(
|
if(!flipper_format_write_string_cstr(
|
||||||
flipper_format, "Preset", furi_string_get_cstr(temp_str))) {
|
flipper_format, "Preset", furi_string_get_cstr(temp_str))) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Preset");
|
FURI_LOG_E(TAG, "Unable to add Preset");
|
||||||
|
res = SubGhzProtocolStatusErrorParserPreset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
|
if(!strcmp(furi_string_get_cstr(temp_str), "FuriHalSubGhzPresetCustom")) {
|
||||||
if(!flipper_format_write_string_cstr(
|
if(!flipper_format_write_string_cstr(
|
||||||
flipper_format, "Custom_preset_module", "CC1101")) {
|
flipper_format, "Custom_preset_module", "CC1101")) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
|
FURI_LOG_E(TAG, "Unable to add Custom_preset_module");
|
||||||
|
res = SubGhzProtocolStatusErrorParserCustomPreset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if(!flipper_format_write_hex(
|
if(!flipper_format_write_hex(
|
||||||
flipper_format, "Custom_preset_data", preset->data, preset->data_size)) {
|
flipper_format, "Custom_preset_data", preset->data, preset->data_size)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
|
FURI_LOG_E(TAG, "Unable to add Custom_preset_data");
|
||||||
|
res = SubGhzProtocolStatusErrorParserCustomPreset;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) {
|
if(!flipper_format_write_string_cstr(flipper_format, "Protocol", instance->protocol_name)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Protocol");
|
FURI_LOG_E(TAG, "Unable to add Protocol");
|
||||||
|
res = SubGhzProtocolStatusErrorParserProtocolName;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint32_t temp_data = instance->id;
|
uint32_t temp_data = instance->id;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Id", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Id", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Id");
|
FURI_LOG_E(TAG, "Unable to add Id");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_data = instance->data_count_bit;
|
temp_data = instance->data_count_bit;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Bit", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Bit", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Bit");
|
FURI_LOG_E(TAG, "Unable to add Bit");
|
||||||
|
res = SubGhzProtocolStatusErrorParserBitCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -84,18 +92,21 @@ bool ws_block_generic_serialize(
|
|||||||
|
|
||||||
if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
|
if(!flipper_format_write_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Data");
|
FURI_LOG_E(TAG, "Unable to add Data");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_data = instance->battery_low;
|
temp_data = instance->battery_low;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Batt", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Batt", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Battery_low");
|
FURI_LOG_E(TAG, "Unable to add Battery_low");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_data = instance->humidity;
|
temp_data = instance->humidity;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Hum", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Hum", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Humidity");
|
FURI_LOG_E(TAG, "Unable to add Humidity");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,52 +118,60 @@ bool ws_block_generic_serialize(
|
|||||||
temp_data = curr_ts;
|
temp_data = curr_ts;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Ts", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add timestamp");
|
FURI_LOG_E(TAG, "Unable to add timestamp");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_data = instance->channel;
|
temp_data = instance->channel;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Ch", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Channel");
|
FURI_LOG_E(TAG, "Unable to add Channel");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
temp_data = instance->btn;
|
temp_data = instance->btn;
|
||||||
if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) {
|
if(!flipper_format_write_uint32(flipper_format, "Btn", &temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Btn");
|
FURI_LOG_E(TAG, "Unable to add Btn");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
float temp = instance->temp;
|
float temp = instance->temp;
|
||||||
if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) {
|
if(!flipper_format_write_float(flipper_format, "Temp", &temp, 1)) {
|
||||||
FURI_LOG_E(TAG, "Unable to add Temperature");
|
FURI_LOG_E(TAG, "Unable to add Temperature");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
res = true;
|
res = SubGhzProtocolStatusOk;
|
||||||
} while(false);
|
} while(false);
|
||||||
furi_string_free(temp_str);
|
furi_string_free(temp_str);
|
||||||
return res;
|
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);
|
furi_assert(instance);
|
||||||
bool res = false;
|
SubGhzProtocolStatus res = SubGhzProtocolStatusError;
|
||||||
uint32_t temp_data = 0;
|
uint32_t temp_data = 0;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
if(!flipper_format_rewind(flipper_format)) {
|
if(!flipper_format_rewind(flipper_format)) {
|
||||||
FURI_LOG_E(TAG, "Rewind error");
|
FURI_LOG_E(TAG, "Rewind error");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Id", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Id", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Id");
|
FURI_LOG_E(TAG, "Missing Id");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->id = (uint32_t)temp_data;
|
instance->id = (uint32_t)temp_data;
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Bit", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Bit");
|
FURI_LOG_E(TAG, "Missing Bit");
|
||||||
|
res = SubGhzProtocolStatusErrorParserBitCount;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->data_count_bit = (uint8_t)temp_data;
|
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};
|
uint8_t key_data[sizeof(uint64_t)] = {0};
|
||||||
if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
|
if(!flipper_format_read_hex(flipper_format, "Data", key_data, sizeof(uint64_t))) {
|
||||||
FURI_LOG_E(TAG, "Missing Data");
|
FURI_LOG_E(TAG, "Missing Data");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
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)) {
|
if(!flipper_format_read_uint32(flipper_format, "Batt", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Battery_low");
|
FURI_LOG_E(TAG, "Missing Battery_low");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->battery_low = (uint8_t)temp_data;
|
instance->battery_low = (uint8_t)temp_data;
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Hum", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Hum", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Humidity");
|
FURI_LOG_E(TAG, "Missing Humidity");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->humidity = (uint8_t)temp_data;
|
instance->humidity = (uint8_t)temp_data;
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Ts", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Ts", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing timestamp");
|
FURI_LOG_E(TAG, "Missing timestamp");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->timestamp = (uint32_t)temp_data;
|
instance->timestamp = (uint32_t)temp_data;
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Ch", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Channel");
|
FURI_LOG_E(TAG, "Missing Channel");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->channel = (uint8_t)temp_data;
|
instance->channel = (uint8_t)temp_data;
|
||||||
|
|
||||||
if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) {
|
if(!flipper_format_read_uint32(flipper_format, "Btn", (uint32_t*)&temp_data, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Btn");
|
FURI_LOG_E(TAG, "Missing Btn");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->btn = (uint8_t)temp_data;
|
instance->btn = (uint8_t)temp_data;
|
||||||
@@ -200,12 +225,32 @@ bool ws_block_generic_deserialize(WSBlockGeneric* instance, FlipperFormat* flipp
|
|||||||
float temp;
|
float temp;
|
||||||
if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) {
|
if(!flipper_format_read_float(flipper_format, "Temp", (float*)&temp, 1)) {
|
||||||
FURI_LOG_E(TAG, "Missing Temperature");
|
FURI_LOG_E(TAG, "Missing Temperature");
|
||||||
|
res = SubGhzProtocolStatusErrorParserOthers;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
instance->temp = temp;
|
instance->temp = temp;
|
||||||
|
|
||||||
res = true;
|
res = SubGhzProtocolStatusOk;
|
||||||
} while(0);
|
} while(0);
|
||||||
|
|
||||||
return res;
|
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;
|
||||||
|
}
|
||||||
@@ -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 instance Pointer to a WSBlockGeneric instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat instance
|
* @param flipper_format Pointer to a FlipperFormat instance
|
||||||
* @param preset The modulation on which the signal was received, SubGhzRadioPreset
|
* @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,
|
WSBlockGeneric* instance,
|
||||||
FlipperFormat* flipper_format,
|
FlipperFormat* flipper_format,
|
||||||
SubGhzRadioPreset* preset);
|
SubGhzRadioPreset* preset);
|
||||||
@@ -59,9 +59,22 @@ bool ws_block_generic_serialize(
|
|||||||
* Deserialize data WSBlockGeneric.
|
* Deserialize data WSBlockGeneric.
|
||||||
* @param instance Pointer to a WSBlockGeneric instance
|
* @param instance Pointer to a WSBlockGeneric instance
|
||||||
* @param flipper_format Pointer to a FlipperFormat 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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ typedef enum {
|
|||||||
typedef struct {
|
typedef struct {
|
||||||
const FuriThreadCallback app;
|
const FuriThreadCallback app;
|
||||||
const char* name;
|
const char* name;
|
||||||
|
const char* appid;
|
||||||
const size_t stack_size;
|
const size_t stack_size;
|
||||||
const Icon* icon;
|
const Icon* icon;
|
||||||
const FlipperApplicationFlag flags;
|
const FlipperApplicationFlag flags;
|
||||||
|
|||||||
@@ -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(bt->keys_storage);
|
||||||
furi_assert(keys_storage_path);
|
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) {
|
void bt_keys_storage_set_default_path(Bt* bt) {
|
||||||
|
|||||||
@@ -382,11 +382,18 @@ void cli_command_ps(Cli* cli, FuriString* args, void* context) {
|
|||||||
FuriThreadId threads_ids[threads_num_max];
|
FuriThreadId threads_ids[threads_num_max];
|
||||||
uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max);
|
uint8_t thread_num = furi_thread_enumerate(threads_ids, threads_num_max);
|
||||||
printf(
|
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++) {
|
for(uint8_t i = 0; i < thread_num; i++) {
|
||||||
TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i];
|
TaskControlBlock* tcb = (TaskControlBlock*)threads_ids[i];
|
||||||
printf(
|
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]),
|
furi_thread_get_name(threads_ids[i]),
|
||||||
(uint32_t)tcb->pxStack,
|
(uint32_t)tcb->pxStack,
|
||||||
memmgr_heap_get_thread_memory(threads_ids[i]),
|
memmgr_heap_get_thread_memory(threads_ids[i]),
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#include "dialogs_i.h"
|
#include "dialogs_i.h"
|
||||||
#include <toolbox/api_lock.h>
|
#include <toolbox/api_lock.h>
|
||||||
#include <assets_icons.h>
|
#include <assets_icons.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
|
||||||
/****************** File browser ******************/
|
/****************** File browser ******************/
|
||||||
|
|
||||||
@@ -13,6 +14,22 @@ bool dialog_file_browser_show(
|
|||||||
FuriApiLock lock = api_lock_alloc_locked();
|
FuriApiLock lock = api_lock_alloc_locked();
|
||||||
furi_check(lock != NULL);
|
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 = {
|
DialogsAppData data = {
|
||||||
.file_browser = {
|
.file_browser = {
|
||||||
.extension = options ? options->extension : "",
|
.extension = options ? options->extension : "",
|
||||||
@@ -24,7 +41,7 @@ bool dialog_file_browser_show(
|
|||||||
.preselected_filename = path,
|
.preselected_filename = path,
|
||||||
.item_callback = options ? options->item_loader_callback : NULL,
|
.item_callback = options ? options->item_loader_callback : NULL,
|
||||||
.item_callback_context = options ? options->item_loader_context : 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;
|
DialogsAppReturn return_data;
|
||||||
@@ -39,6 +56,9 @@ bool dialog_file_browser_show(
|
|||||||
furi_message_queue_put(context->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
furi_message_queue_put(context->message_queue, &message, FuriWaitForever) == FuriStatusOk);
|
||||||
api_lock_wait_unlock_and_free(lock);
|
api_lock_wait_unlock_and_free(lock);
|
||||||
|
|
||||||
|
furi_record_close(RECORD_STORAGE);
|
||||||
|
furi_string_free(base_path);
|
||||||
|
|
||||||
return return_data.bool_value;
|
return return_data.bool_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,7 +60,7 @@ static bool browser_path_is_file(FuriString* path) {
|
|||||||
FileInfo file_info;
|
FileInfo file_info;
|
||||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||||
if(storage_common_stat(storage, furi_string_get_cstr(path), &file_info) == FSE_OK) {
|
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;
|
state = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,7 +119,7 @@ static bool browser_folder_check_and_switch(FuriString* path) {
|
|||||||
while(1) {
|
while(1) {
|
||||||
// Check if folder is existing and navigate back if not
|
// 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(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;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -161,7 +161,7 @@ static bool browser_folder_init(
|
|||||||
if((storage_file_get_error(directory) == FSE_OK) && (name_temp[0] != '\0')) {
|
if((storage_file_get_error(directory) == FSE_OK) && (name_temp[0] != '\0')) {
|
||||||
total_files_cnt++;
|
total_files_cnt++;
|
||||||
furi_string_set(name_str, name_temp);
|
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_empty(filename)) {
|
||||||
if(furi_string_cmp(name_str, filename) == 0) {
|
if(furi_string_cmp(name_str, filename) == 0) {
|
||||||
*file_idx = *item_cnt;
|
*file_idx = *item_cnt;
|
||||||
@@ -218,7 +218,7 @@ static bool browser_folder_load_chunked(
|
|||||||
}
|
}
|
||||||
if(storage_file_get_error(directory) == FSE_OK) {
|
if(storage_file_get_error(directory) == FSE_OK) {
|
||||||
furi_string_set(name_str, name_temp);
|
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++;
|
items_cnt++;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -240,14 +240,14 @@ static bool browser_folder_load_chunked(
|
|||||||
}
|
}
|
||||||
if(storage_file_get_error(directory) == FSE_OK) {
|
if(storage_file_get_error(directory) == FSE_OK) {
|
||||||
furi_string_set(name_str, name_temp);
|
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);
|
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
|
||||||
if(browser->list_item_cb) {
|
if(browser->list_item_cb) {
|
||||||
browser->list_item_cb(
|
browser->list_item_cb(
|
||||||
browser->cb_ctx,
|
browser->cb_ctx,
|
||||||
name_str,
|
name_str,
|
||||||
items_cnt,
|
items_cnt,
|
||||||
(file_info.flags & FSF_DIRECTORY),
|
file_info_is_dir(&file_info),
|
||||||
false);
|
false);
|
||||||
}
|
}
|
||||||
items_cnt++;
|
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) &&
|
while(storage_dir_read(directory, &file_info, name_temp, FILE_NAME_LEN_MAX) &&
|
||||||
storage_file_get_error(directory) == FSE_OK) {
|
storage_file_get_error(directory) == FSE_OK) {
|
||||||
furi_string_set(name_str, name_temp);
|
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);
|
furi_string_printf(name_str, "%s/%s", furi_string_get_cstr(path), name_temp);
|
||||||
if(browser->list_item_cb) {
|
if(browser->list_item_cb) {
|
||||||
browser->list_item_cb(
|
browser->list_item_cb(
|
||||||
browser->cb_ctx,
|
browser->cb_ctx, name_str, items_cnt, file_info_is_dir(&file_info), false);
|
||||||
name_str,
|
|
||||||
items_cnt,
|
|
||||||
(file_info.flags & FSF_DIRECTORY),
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
items_cnt++;
|
items_cnt++;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ void widget_add_text_box_element(
|
|||||||
* @param[in] text Formatted text. Default format: align left, Secondary font.
|
* @param[in] text Formatted text. Default format: align left, Secondary font.
|
||||||
* The following formats are available:
|
* The following formats are available:
|
||||||
* "\e#Bold text" - sets bold font before until next '\n' symbol
|
* "\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
|
* "\ecCenter-aligned text" - sets center horizontal align until the next '\n' symbol
|
||||||
* "\erRight-aligned text" - sets right horizontal align until the next '\n' symbol
|
* "\erRight-aligned text" - sets right horizontal align until the next '\n' symbol
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -37,6 +37,8 @@ static bool
|
|||||||
line->horizontal = AlignRight;
|
line->horizontal = AlignRight;
|
||||||
} else if(ctrl_symbol == '#') {
|
} else if(ctrl_symbol == '#') {
|
||||||
line->font = FontPrimary;
|
line->font = FontPrimary;
|
||||||
|
} else if(ctrl_symbol == '*') {
|
||||||
|
line->font = FontKeyboard;
|
||||||
}
|
}
|
||||||
furi_string_right(text, 2);
|
furi_string_right(text, 2);
|
||||||
processed = true;
|
processed = true;
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ static bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
furi_thread_set_name(loader_instance->application_thread, loader_instance->application->name);
|
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(
|
furi_thread_set_stack_size(
|
||||||
loader_instance->application_thread, loader_instance->application->stack_size);
|
loader_instance->application_thread, loader_instance->application->stack_size);
|
||||||
furi_thread_set_context(
|
furi_thread_set_context(
|
||||||
|
|||||||
@@ -201,7 +201,7 @@ static void rpc_system_storage_stat_process(const PB_Main* request, void* contex
|
|||||||
if(error == FSE_OK) {
|
if(error == FSE_OK) {
|
||||||
response->which_content = PB_Main_storage_stat_response_tag;
|
response->which_content = PB_Main_storage_stat_response_tag;
|
||||||
response->content.storage_stat_response.has_file = true;
|
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_DIR :
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
response->content.storage_stat_response.file.size = fileinfo.size;
|
response->content.storage_stat_response.file.size = fileinfo.size;
|
||||||
@@ -291,8 +291,7 @@ static void rpc_system_storage_list_process(const PB_Main* request, void* contex
|
|||||||
rpc_send_and_release(session, &response);
|
rpc_send_and_release(session, &response);
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
list->file[i].type = (fileinfo.flags & FSF_DIRECTORY) ?
|
list->file[i].type = file_info_is_dir(&fileinfo) ? PB_Storage_File_FileType_DIR :
|
||||||
PB_Storage_File_FileType_DIR :
|
|
||||||
PB_Storage_File_FileType_FILE;
|
PB_Storage_File_FileType_FILE;
|
||||||
list->file[i].size = fileinfo.size;
|
list->file[i].size = fileinfo.size;
|
||||||
list->file[i].data = NULL;
|
list->file[i].data = NULL;
|
||||||
@@ -458,7 +457,7 @@ static bool rpc_system_storage_is_dir_is_empty(Storage* fs_api, const char* path
|
|||||||
FileInfo fileinfo;
|
FileInfo fileinfo;
|
||||||
bool is_dir_is_empty = true;
|
bool is_dir_is_empty = true;
|
||||||
FS_Error error = storage_common_stat(fs_api, path, &fileinfo);
|
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);
|
File* dir = storage_file_alloc(fs_api);
|
||||||
if(storage_dir_open(dir, path)) {
|
if(storage_dir_open(dir, path)) {
|
||||||
char* name = malloc(MAX_NAME_LENGTH);
|
char* name = malloc(MAX_NAME_LENGTH);
|
||||||
|
|||||||
@@ -36,3 +36,7 @@ const char* filesystem_api_error_get_desc(FS_Error error_id) {
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool file_info_is_dir(const FileInfo* file_info) {
|
||||||
|
return (file_info->flags & FSF_DIRECTORY);
|
||||||
|
}
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@@ -55,6 +56,12 @@ typedef struct {
|
|||||||
*/
|
*/
|
||||||
const char* filesystem_api_error_get_desc(FS_Error error_id);
|
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
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,10 +10,12 @@ extern "C" {
|
|||||||
#define STORAGE_INT_PATH_PREFIX "/int"
|
#define STORAGE_INT_PATH_PREFIX "/int"
|
||||||
#define STORAGE_EXT_PATH_PREFIX "/ext"
|
#define STORAGE_EXT_PATH_PREFIX "/ext"
|
||||||
#define STORAGE_ANY_PATH_PREFIX "/any"
|
#define STORAGE_ANY_PATH_PREFIX "/any"
|
||||||
|
#define STORAGE_APP_DATA_PATH_PREFIX "/app"
|
||||||
|
|
||||||
#define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path
|
#define INT_PATH(path) STORAGE_INT_PATH_PREFIX "/" path
|
||||||
#define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path
|
#define EXT_PATH(path) STORAGE_EXT_PATH_PREFIX "/" path
|
||||||
#define ANY_PATH(path) STORAGE_ANY_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"
|
#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);
|
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 *******************/
|
/******************* Common Functions *******************/
|
||||||
|
|
||||||
/** Retrieves unix timestamp of last access
|
/** Retrieves unix timestamp of last access
|
||||||
@@ -246,6 +257,36 @@ FS_Error storage_common_fs_info(
|
|||||||
uint64_t* total_space,
|
uint64_t* total_space,
|
||||||
uint64_t* free_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 *******************/
|
/******************* Error Functions *******************/
|
||||||
|
|
||||||
/** Retrieves the error text from the error id
|
/** Retrieves the error text from the error id
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user