[FL-2753] RFID app port to plain C (#1710)
* LF RFID: port to plain C * LFRFID debug port to C, new reading screen * LFRFID debug: fix pvs-studio warnings * RFID read view: remove unused input callback * RFID read view: animation update
This commit is contained in:
parent
e9ab581771
commit
0f6f9ad52e
@ -42,7 +42,9 @@ ValidatorIsFile* validator_is_file_alloc_init(
|
||||
|
||||
instance->app_path_folder = strdup(app_path_folder);
|
||||
instance->app_extension = app_extension;
|
||||
instance->current_name = strdup(current_name);
|
||||
if(current_name != NULL) {
|
||||
instance->current_name = strdup(current_name);
|
||||
}
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
316
applications/lfrfid/lfrfid.c
Normal file
316
applications/lfrfid/lfrfid.c
Normal file
@ -0,0 +1,316 @@
|
||||
#include "lfrfid_i.h"
|
||||
|
||||
static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
LfRfid* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool lfrfid_debug_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
LfRfid* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
||||
furi_assert(context);
|
||||
LfRfid* app = (LfRfid*)context;
|
||||
|
||||
if(rpc_event == RpcAppEventSessionClose) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcSessionClose);
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
} else if(rpc_event == RpcAppEventAppExit) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventExit);
|
||||
} else if(rpc_event == RpcAppEventLoadFile) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcLoadFile);
|
||||
} else {
|
||||
rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
|
||||
}
|
||||
}
|
||||
|
||||
static LfRfid* lfrfid_alloc() {
|
||||
LfRfid* lfrfid = malloc(sizeof(LfRfid));
|
||||
|
||||
lfrfid->storage = furi_record_open(RECORD_STORAGE);
|
||||
lfrfid->dialogs = furi_record_open(RECORD_DIALOGS);
|
||||
|
||||
string_init(lfrfid->file_name);
|
||||
string_init(lfrfid->raw_file_name);
|
||||
string_init_set_str(lfrfid->file_path, LFRFID_APP_FOLDER);
|
||||
|
||||
lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
|
||||
size_t size = protocol_dict_get_max_data_size(lfrfid->dict);
|
||||
lfrfid->new_key_data = (uint8_t*)malloc(size);
|
||||
lfrfid->old_key_data = (uint8_t*)malloc(size);
|
||||
|
||||
lfrfid->lfworker = lfrfid_worker_alloc(lfrfid->dict);
|
||||
|
||||
lfrfid->view_dispatcher = view_dispatcher_alloc();
|
||||
lfrfid->scene_manager = scene_manager_alloc(&lfrfid_scene_handlers, lfrfid);
|
||||
view_dispatcher_enable_queue(lfrfid->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(lfrfid->view_dispatcher, lfrfid);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
lfrfid->view_dispatcher, lfrfid_debug_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
lfrfid->view_dispatcher, lfrfid_debug_back_event_callback);
|
||||
|
||||
// Open GUI record
|
||||
lfrfid->gui = furi_record_open(RECORD_GUI);
|
||||
|
||||
// Open Notification record
|
||||
lfrfid->notifications = furi_record_open(RECORD_NOTIFICATION);
|
||||
|
||||
// Submenu
|
||||
lfrfid->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewSubmenu, submenu_get_view(lfrfid->submenu));
|
||||
|
||||
// Dialog
|
||||
lfrfid->dialog_ex = dialog_ex_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewDialogEx, dialog_ex_get_view(lfrfid->dialog_ex));
|
||||
|
||||
// Popup
|
||||
lfrfid->popup = popup_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewPopup, popup_get_view(lfrfid->popup));
|
||||
|
||||
// Widget
|
||||
lfrfid->widget = widget_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewWidget, widget_get_view(lfrfid->widget));
|
||||
|
||||
// Text Input
|
||||
lfrfid->text_input = text_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewTextInput, text_input_get_view(lfrfid->text_input));
|
||||
|
||||
// Byte Input
|
||||
lfrfid->byte_input = byte_input_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewByteInput, byte_input_get_view(lfrfid->byte_input));
|
||||
|
||||
// Read custom view
|
||||
lfrfid->read_view = lfrfid_view_read_alloc();
|
||||
view_dispatcher_add_view(
|
||||
lfrfid->view_dispatcher, LfRfidViewRead, lfrfid_view_read_get_view(lfrfid->read_view));
|
||||
|
||||
return lfrfid;
|
||||
}
|
||||
|
||||
static void lfrfid_free(LfRfid* lfrfid) {
|
||||
furi_assert(lfrfid);
|
||||
|
||||
string_clear(lfrfid->raw_file_name);
|
||||
string_clear(lfrfid->file_name);
|
||||
string_clear(lfrfid->file_path);
|
||||
protocol_dict_free(lfrfid->dict);
|
||||
|
||||
lfrfid_worker_free(lfrfid->lfworker);
|
||||
|
||||
if(lfrfid->rpc_ctx) {
|
||||
rpc_system_app_set_callback(lfrfid->rpc_ctx, NULL, NULL);
|
||||
rpc_system_app_send_exited(lfrfid->rpc_ctx);
|
||||
}
|
||||
|
||||
free(lfrfid->new_key_data);
|
||||
free(lfrfid->old_key_data);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewSubmenu);
|
||||
submenu_free(lfrfid->submenu);
|
||||
|
||||
// DialogEx
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewDialogEx);
|
||||
dialog_ex_free(lfrfid->dialog_ex);
|
||||
|
||||
// Popup
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewPopup);
|
||||
popup_free(lfrfid->popup);
|
||||
|
||||
// Widget
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewWidget);
|
||||
widget_free(lfrfid->widget);
|
||||
|
||||
// TextInput
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewTextInput);
|
||||
text_input_free(lfrfid->text_input);
|
||||
|
||||
// ByteInput
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewByteInput);
|
||||
byte_input_free(lfrfid->byte_input);
|
||||
|
||||
// Read custom view
|
||||
view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewRead);
|
||||
lfrfid_view_read_free(lfrfid->read_view);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(lfrfid->view_dispatcher);
|
||||
|
||||
// Scene Manager
|
||||
scene_manager_free(lfrfid->scene_manager);
|
||||
|
||||
// GUI
|
||||
furi_record_close(RECORD_GUI);
|
||||
lfrfid->gui = NULL;
|
||||
|
||||
// Notifications
|
||||
furi_record_close(RECORD_NOTIFICATION);
|
||||
lfrfid->notifications = NULL;
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
furi_record_close(RECORD_DIALOGS);
|
||||
|
||||
free(lfrfid);
|
||||
}
|
||||
|
||||
int32_t lfrfid_app(void* p) {
|
||||
LfRfid* app = lfrfid_alloc();
|
||||
char* args = p;
|
||||
|
||||
lfrfid_make_app_folder(app);
|
||||
|
||||
if(args && strlen(args)) {
|
||||
uint32_t rpc_ctx_ptr = 0;
|
||||
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
|
||||
app->rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
||||
rpc_system_app_set_callback(app->rpc_ctx, rpc_command_callback, app);
|
||||
rpc_system_app_send_started(app->rpc_ctx);
|
||||
view_dispatcher_attach_to_gui(
|
||||
app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc);
|
||||
} else {
|
||||
string_set_str(app->file_path, args);
|
||||
lfrfid_load_key_data(app, app->file_path, true);
|
||||
view_dispatcher_attach_to_gui(
|
||||
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
}
|
||||
|
||||
} else {
|
||||
view_dispatcher_attach_to_gui(
|
||||
app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneStart);
|
||||
}
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
lfrfid_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool lfrfid_save_key(LfRfid* app) {
|
||||
furi_assert(app);
|
||||
|
||||
bool result = false;
|
||||
|
||||
lfrfid_make_app_folder(app);
|
||||
|
||||
if(string_end_with_str_p(app->file_path, LFRFID_APP_EXTENSION)) {
|
||||
size_t filename_start = string_search_rchar(app->file_path, '/');
|
||||
string_left(app->file_path, filename_start);
|
||||
}
|
||||
|
||||
string_cat_printf(
|
||||
app->file_path, "/%s%s", string_get_cstr(app->file_name), LFRFID_APP_EXTENSION);
|
||||
|
||||
result = lfrfid_save_key_data(app, app->file_path);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool lfrfid_load_key_from_file_select(LfRfid* app) {
|
||||
furi_assert(app);
|
||||
|
||||
bool result = dialog_file_browser_show(
|
||||
app->dialogs,
|
||||
app->file_path,
|
||||
app->file_path,
|
||||
LFRFID_APP_EXTENSION,
|
||||
true,
|
||||
&I_125_10px,
|
||||
true);
|
||||
|
||||
if(result) {
|
||||
result = lfrfid_load_key_data(app, app->file_path, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool lfrfid_delete_key(LfRfid* app) {
|
||||
furi_assert(app);
|
||||
|
||||
return storage_simply_remove(app->storage, string_get_cstr(app->file_path));
|
||||
}
|
||||
|
||||
bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog) {
|
||||
bool result = false;
|
||||
|
||||
do {
|
||||
app->protocol_id = lfrfid_dict_file_load(app->dict, string_get_cstr(path));
|
||||
if(app->protocol_id == PROTOCOL_NO) break;
|
||||
|
||||
path_extract_filename(path, app->file_name, true);
|
||||
result = true;
|
||||
} while(0);
|
||||
|
||||
if((!result) && (show_dialog)) {
|
||||
dialog_message_show_storage_error(app->dialogs, "Cannot load\nkey file");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool lfrfid_save_key_data(LfRfid* app, string_t path) {
|
||||
bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, string_get_cstr(path));
|
||||
|
||||
if(!result) {
|
||||
dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void lfrfid_make_app_folder(LfRfid* app) {
|
||||
furi_assert(app);
|
||||
|
||||
if(!storage_simply_mkdir(app->storage, LFRFID_APP_FOLDER)) {
|
||||
dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder");
|
||||
}
|
||||
}
|
||||
|
||||
void lfrfid_text_store_set(LfRfid* app, const char* text, ...) {
|
||||
furi_assert(app);
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
|
||||
vsnprintf(app->text_store, LFRFID_TEXT_STORE_SIZE, text, args);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
void lfrfid_text_store_clear(LfRfid* app) {
|
||||
furi_assert(app);
|
||||
memset(app->text_store, 0, sizeof(app->text_store));
|
||||
}
|
||||
|
||||
void lfrfid_popup_timeout_callback(void* context) {
|
||||
LfRfid* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventPopupClosed);
|
||||
}
|
||||
|
||||
void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context) {
|
||||
LfRfid* app = context;
|
||||
if(type == InputTypeShort) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, result);
|
||||
}
|
||||
}
|
||||
|
||||
void lfrfid_text_input_callback(void* context) {
|
||||
LfRfid* app = context;
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext);
|
||||
}
|
@ -1,218 +0,0 @@
|
||||
#include "lfrfid_app.h"
|
||||
#include "assets_icons.h"
|
||||
#include <core/common_defines.h>
|
||||
#include "m-string.h"
|
||||
#include "scene/lfrfid_app_scene_start.h"
|
||||
#include "scene/lfrfid_app_scene_read.h"
|
||||
#include "scene/lfrfid_app_scene_read_success.h"
|
||||
#include "scene/lfrfid_app_scene_retry_confirm.h"
|
||||
#include "scene/lfrfid_app_scene_exit_confirm.h"
|
||||
#include "scene/lfrfid_app_scene_read_menu.h"
|
||||
#include "scene/lfrfid_app_scene_write.h"
|
||||
#include "scene/lfrfid_app_scene_write_success.h"
|
||||
#include "scene/lfrfid_app_scene_emulate.h"
|
||||
#include "scene/lfrfid_app_scene_save_name.h"
|
||||
#include "scene/lfrfid_app_scene_save_success.h"
|
||||
#include "scene/lfrfid_app_scene_select_key.h"
|
||||
#include "scene/lfrfid_app_scene_saved_key_menu.h"
|
||||
#include "scene/lfrfid_app_scene_save_data.h"
|
||||
#include "scene/lfrfid_app_scene_save_type.h"
|
||||
#include "scene/lfrfid_app_scene_saved_info.h"
|
||||
#include "scene/lfrfid_app_scene_delete_confirm.h"
|
||||
#include "scene/lfrfid_app_scene_delete_success.h"
|
||||
#include "scene/lfrfid_app_scene_rpc.h"
|
||||
#include "scene/lfrfid_app_scene_extra_actions.h"
|
||||
#include "scene/lfrfid_app_scene_raw_info.h"
|
||||
#include "scene/lfrfid_app_scene_raw_name.h"
|
||||
#include "scene/lfrfid_app_scene_raw_read.h"
|
||||
#include "scene/lfrfid_app_scene_raw_success.h"
|
||||
|
||||
#include <toolbox/path.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
const char* LfRfidApp::app_folder = ANY_PATH("lfrfid");
|
||||
const char* LfRfidApp::app_sd_folder = EXT_PATH("lfrfid");
|
||||
const char* LfRfidApp::app_extension = ".rfid";
|
||||
const char* LfRfidApp::app_filetype = "Flipper RFID key";
|
||||
|
||||
LfRfidApp::LfRfidApp()
|
||||
: scene_controller{this}
|
||||
, notification{RECORD_NOTIFICATION}
|
||||
, storage{RECORD_STORAGE}
|
||||
, dialogs{RECORD_DIALOGS}
|
||||
, text_store(40) {
|
||||
string_init(file_name);
|
||||
string_init(raw_file_name);
|
||||
string_init_set_str(file_path, app_folder);
|
||||
|
||||
dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
|
||||
size_t size = protocol_dict_get_max_data_size(dict);
|
||||
new_key_data = (uint8_t*)malloc(size);
|
||||
old_key_data = (uint8_t*)malloc(size);
|
||||
|
||||
lfworker = lfrfid_worker_alloc(dict);
|
||||
}
|
||||
|
||||
LfRfidApp::~LfRfidApp() {
|
||||
string_clear(raw_file_name);
|
||||
string_clear(file_name);
|
||||
string_clear(file_path);
|
||||
protocol_dict_free(dict);
|
||||
|
||||
lfrfid_worker_free(lfworker);
|
||||
|
||||
if(rpc_ctx) {
|
||||
rpc_system_app_set_callback(rpc_ctx, NULL, NULL);
|
||||
rpc_system_app_send_exited(rpc_ctx);
|
||||
}
|
||||
|
||||
free(new_key_data);
|
||||
free(old_key_data);
|
||||
}
|
||||
|
||||
static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
|
||||
furi_assert(context);
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
|
||||
if(rpc_event == RpcAppEventSessionClose) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::RpcSessionClose;
|
||||
app->view_controller.send_event(&event);
|
||||
// Detach RPC
|
||||
rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
|
||||
app->rpc_ctx = NULL;
|
||||
} else if(rpc_event == RpcAppEventAppExit) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Exit;
|
||||
app->view_controller.send_event(&event);
|
||||
} else if(rpc_event == RpcAppEventLoadFile) {
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::RpcLoadFile;
|
||||
app->view_controller.send_event(&event);
|
||||
} else {
|
||||
rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
|
||||
}
|
||||
}
|
||||
|
||||
void LfRfidApp::run(void* _args) {
|
||||
const char* args = reinterpret_cast<const char*>(_args);
|
||||
|
||||
make_app_folder();
|
||||
|
||||
if(args && strlen(args)) {
|
||||
uint32_t rpc_ctx_ptr = 0;
|
||||
if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
|
||||
rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
|
||||
rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
|
||||
rpc_system_app_send_started(rpc_ctx);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeDesktop);
|
||||
scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
|
||||
scene_controller.process(100, SceneType::Rpc);
|
||||
} else {
|
||||
string_set_str(file_path, args);
|
||||
load_key_data(file_path, true);
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||
scene_controller.process(100, SceneType::Emulate);
|
||||
}
|
||||
|
||||
} else {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
|
||||
scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
|
||||
scene_controller.add_scene(SceneType::ExitConfirm, new LfRfidAppSceneExitConfirm());
|
||||
scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess());
|
||||
scene_controller.add_scene(SceneType::ReadKeyMenu, new LfRfidAppSceneReadKeyMenu());
|
||||
scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite());
|
||||
scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
|
||||
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
|
||||
scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName());
|
||||
scene_controller.add_scene(SceneType::SaveSuccess, new LfRfidAppSceneSaveSuccess());
|
||||
scene_controller.add_scene(SceneType::SelectKey, new LfRfidAppSceneSelectKey());
|
||||
scene_controller.add_scene(SceneType::SavedKeyMenu, new LfRfidAppSceneSavedKeyMenu());
|
||||
scene_controller.add_scene(SceneType::SaveData, new LfRfidAppSceneSaveData());
|
||||
scene_controller.add_scene(SceneType::SaveType, new LfRfidAppSceneSaveType());
|
||||
scene_controller.add_scene(SceneType::SavedInfo, new LfRfidAppSceneSavedInfo());
|
||||
scene_controller.add_scene(SceneType::DeleteConfirm, new LfRfidAppSceneDeleteConfirm());
|
||||
scene_controller.add_scene(SceneType::DeleteSuccess, new LfRfidAppSceneDeleteSuccess());
|
||||
scene_controller.add_scene(SceneType::ExtraActions, new LfRfidAppSceneExtraActions());
|
||||
scene_controller.add_scene(SceneType::RawInfo, new LfRfidAppSceneRawInfo());
|
||||
scene_controller.add_scene(SceneType::RawName, new LfRfidAppSceneRawName());
|
||||
scene_controller.add_scene(SceneType::RawRead, new LfRfidAppSceneRawRead());
|
||||
scene_controller.add_scene(SceneType::RawSuccess, new LfRfidAppSceneRawSuccess());
|
||||
scene_controller.process(100);
|
||||
}
|
||||
}
|
||||
|
||||
bool LfRfidApp::save_key() {
|
||||
bool result = false;
|
||||
|
||||
make_app_folder();
|
||||
|
||||
if(string_end_with_str_p(file_path, app_extension)) {
|
||||
size_t filename_start = string_search_rchar(file_path, '/');
|
||||
string_left(file_path, filename_start);
|
||||
}
|
||||
|
||||
string_cat_printf(file_path, "/%s%s", string_get_cstr(file_name), app_extension);
|
||||
|
||||
result = save_key_data(file_path);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LfRfidApp::load_key_from_file_select(bool need_restore) {
|
||||
if(!need_restore) {
|
||||
string_set_str(file_path, app_folder);
|
||||
}
|
||||
|
||||
bool result = dialog_file_browser_show(
|
||||
dialogs, file_path, file_path, app_extension, true, &I_125_10px, true);
|
||||
|
||||
if(result) {
|
||||
result = load_key_data(file_path, true);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LfRfidApp::delete_key() {
|
||||
return storage_simply_remove(storage, string_get_cstr(file_path));
|
||||
}
|
||||
|
||||
bool LfRfidApp::load_key_data(string_t path, bool show_dialog) {
|
||||
bool result = false;
|
||||
|
||||
do {
|
||||
protocol_id = lfrfid_dict_file_load(dict, string_get_cstr(path));
|
||||
if(protocol_id == PROTOCOL_NO) break;
|
||||
|
||||
path_extract_filename(path, file_name, true);
|
||||
result = true;
|
||||
} while(0);
|
||||
|
||||
if((!result) && (show_dialog)) {
|
||||
dialog_message_show_storage_error(dialogs, "Cannot load\nkey file");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool LfRfidApp::save_key_data(string_t path) {
|
||||
bool result = lfrfid_dict_file_save(dict, protocol_id, string_get_cstr(path));
|
||||
|
||||
if(!result) {
|
||||
dialog_message_show_storage_error(dialogs, "Cannot save\nkey file");
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void LfRfidApp::make_app_folder() {
|
||||
if(!storage_simply_mkdir(storage, app_folder)) {
|
||||
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
||||
}
|
||||
}
|
@ -1,137 +0,0 @@
|
||||
#pragma once
|
||||
#include "m-string.h"
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <generic_scene.hpp>
|
||||
#include <scene_controller.hpp>
|
||||
#include <view_controller.hpp>
|
||||
#include <record_controller.hpp>
|
||||
#include <text_store.h>
|
||||
|
||||
#include <view_modules/submenu_vm.h>
|
||||
#include <view_modules/popup_vm.h>
|
||||
#include <view_modules/dialog_ex_vm.h>
|
||||
#include <view_modules/text_input_vm.h>
|
||||
#include <view_modules/byte_input_vm.h>
|
||||
#include "view/container_vm.h"
|
||||
|
||||
#include <notification/notification_messages.h>
|
||||
#include <storage/storage.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
|
||||
#include "rpc/rpc_app.h"
|
||||
|
||||
#include <toolbox/protocols/protocol_dict.h>
|
||||
#include <lfrfid/lfrfid_dict_file.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
#include <lfrfid/lfrfid_worker.h>
|
||||
|
||||
#define LFRFID_KEY_NAME_SIZE 22
|
||||
|
||||
class LfRfidApp {
|
||||
public:
|
||||
enum class EventType : uint8_t {
|
||||
GENERIC_EVENT_ENUM_VALUES,
|
||||
Next,
|
||||
MenuSelected,
|
||||
Stay,
|
||||
Retry,
|
||||
Exit,
|
||||
ReadEventSenseStart,
|
||||
ReadEventSenseEnd,
|
||||
ReadEventSenseCardStart,
|
||||
ReadEventSenseCardEnd,
|
||||
ReadEventStartASK,
|
||||
ReadEventStartPSK,
|
||||
ReadEventDone,
|
||||
ReadEventOverrun,
|
||||
ReadEventError,
|
||||
WriteEventOK,
|
||||
WriteEventProtocolCannotBeWritten,
|
||||
WriteEventFobCannotBeWritten,
|
||||
WriteEventTooLongToWrite,
|
||||
RpcLoadFile,
|
||||
RpcSessionClose,
|
||||
};
|
||||
|
||||
enum class SceneType : uint8_t {
|
||||
GENERIC_SCENE_ENUM_VALUES,
|
||||
Read,
|
||||
ReadSuccess,
|
||||
RetryConfirm,
|
||||
ExitConfirm,
|
||||
ReadKeyMenu,
|
||||
Write,
|
||||
WriteSuccess,
|
||||
Emulate,
|
||||
SaveName,
|
||||
SaveSuccess,
|
||||
SelectKey,
|
||||
SavedKeyMenu,
|
||||
SaveData,
|
||||
SaveType,
|
||||
SavedInfo,
|
||||
DeleteConfirm,
|
||||
DeleteSuccess,
|
||||
Rpc,
|
||||
ExtraActions,
|
||||
RawInfo,
|
||||
RawName,
|
||||
RawRead,
|
||||
RawSuccess,
|
||||
};
|
||||
|
||||
class Event {
|
||||
public:
|
||||
union {
|
||||
int32_t signed_int;
|
||||
} payload;
|
||||
|
||||
EventType type;
|
||||
};
|
||||
|
||||
SceneController<GenericScene<LfRfidApp>, LfRfidApp> scene_controller;
|
||||
ViewController<LfRfidApp, SubmenuVM, PopupVM, DialogExVM, TextInputVM, ByteInputVM, ContainerVM>
|
||||
view_controller;
|
||||
|
||||
~LfRfidApp();
|
||||
LfRfidApp();
|
||||
|
||||
RecordController<NotificationApp> notification;
|
||||
RecordController<Storage> storage;
|
||||
RecordController<DialogsApp> dialogs;
|
||||
|
||||
TextStore text_store;
|
||||
|
||||
string_t file_path;
|
||||
|
||||
RpcAppSystem* rpc_ctx;
|
||||
|
||||
void run(void* args);
|
||||
|
||||
static const char* app_folder;
|
||||
static const char* app_sd_folder;
|
||||
static const char* app_extension;
|
||||
static const char* app_filetype;
|
||||
|
||||
bool save_key();
|
||||
bool load_key_from_file_select(bool need_restore);
|
||||
bool delete_key();
|
||||
|
||||
bool load_key_data(string_t path, bool show_dialog);
|
||||
bool save_key_data(string_t path);
|
||||
|
||||
void make_app_folder();
|
||||
|
||||
ProtocolDict* dict;
|
||||
LFRFIDWorker* lfworker;
|
||||
string_t file_name;
|
||||
ProtocolId protocol_id;
|
||||
LFRFIDWorkerReadType read_type;
|
||||
|
||||
uint8_t* old_key_data;
|
||||
uint8_t* new_key_data;
|
||||
|
||||
string_t raw_file_name;
|
||||
};
|
@ -1,10 +0,0 @@
|
||||
#include "lfrfid_app.h"
|
||||
|
||||
// app enter function
|
||||
extern "C" int32_t lfrfid_app(void* args) {
|
||||
LfRfidApp* app = new LfRfidApp();
|
||||
app->run(args);
|
||||
delete app;
|
||||
|
||||
return 0;
|
||||
}
|
@ -114,7 +114,7 @@ static void lfrfid_cli_read(Cli* cli, string_t args) {
|
||||
string_t info;
|
||||
string_init(info);
|
||||
protocol_dict_render_data(dict, info, context.protocol);
|
||||
if(string_size(info) > 0) {
|
||||
if(!string_empty_p(info)) {
|
||||
printf("%s\r\n", string_get_cstr(info));
|
||||
}
|
||||
string_clear(info);
|
||||
|
145
applications/lfrfid/lfrfid_i.h
Normal file
145
applications/lfrfid/lfrfid_i.h
Normal file
@ -0,0 +1,145 @@
|
||||
#pragma once
|
||||
|
||||
#include "m-string.h"
|
||||
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
#include <cli/cli.h>
|
||||
#include <notification/notification_messages.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
#include <gui/modules/dialog_ex.h>
|
||||
#include <gui/modules/popup.h>
|
||||
#include <gui/modules/text_input.h>
|
||||
#include <gui/modules/byte_input.h>
|
||||
#include <gui/modules/widget.h>
|
||||
|
||||
#include <lfrfid/views/lfrfid_view_read.h>
|
||||
|
||||
#include <notification/notification_messages.h>
|
||||
#include <dialogs/dialogs.h>
|
||||
#include <storage/storage.h>
|
||||
#include <flipper_format/flipper_format.h>
|
||||
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
#include <toolbox/protocols/protocol_dict.h>
|
||||
#include <toolbox/path.h>
|
||||
#include <lfrfid/lfrfid_dict_file.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
#include <lfrfid/lfrfid_worker.h>
|
||||
|
||||
#include <lfrfid/scenes/lfrfid_scene.h>
|
||||
|
||||
#define LFRFID_KEY_NAME_SIZE 22
|
||||
#define LFRFID_TEXT_STORE_SIZE 40
|
||||
|
||||
#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
|
||||
#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
|
||||
#define LFRFID_APP_EXTENSION ".rfid"
|
||||
#define LFRFID_APP_SHADOW_EXTENSION ".shd"
|
||||
|
||||
#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw"
|
||||
#define LFRFID_APP_RAW_PSK_EXTENSION ".psk.raw"
|
||||
|
||||
enum LfRfidCustomEvent {
|
||||
LfRfidEventNext = 100,
|
||||
LfRfidEventExit,
|
||||
LfRfidEventPopupClosed,
|
||||
LfRfidEventReadSenseStart,
|
||||
LfRfidEventReadSenseEnd,
|
||||
LfRfidEventReadSenseCardStart,
|
||||
LfRfidEventReadSenseCardEnd,
|
||||
LfRfidEventReadStartASK,
|
||||
LfRfidEventReadStartPSK,
|
||||
LfRfidEventReadDone,
|
||||
LfRfidEventReadOverrun,
|
||||
LfRfidEventReadError,
|
||||
LfRfidEventWriteOK,
|
||||
LfRfidEventWriteProtocolCannotBeWritten,
|
||||
LfRfidEventWriteFobCannotBeWritten,
|
||||
LfRfidEventWriteTooLongToWrite,
|
||||
LfRfidEventRpcLoadFile,
|
||||
LfRfidEventRpcSessionClose,
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LfRfidRpcStateIdle,
|
||||
LfRfidRpcStateEmulating,
|
||||
} LfRfidRpcState;
|
||||
|
||||
typedef struct LfRfid LfRfid;
|
||||
|
||||
struct LfRfid {
|
||||
LFRFIDWorker* lfworker;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
Gui* gui;
|
||||
NotificationApp* notifications;
|
||||
SceneManager* scene_manager;
|
||||
Storage* storage;
|
||||
DialogsApp* dialogs;
|
||||
Widget* widget;
|
||||
|
||||
char text_store[LFRFID_TEXT_STORE_SIZE + 1];
|
||||
string_t file_path;
|
||||
string_t file_name;
|
||||
string_t raw_file_name;
|
||||
|
||||
ProtocolDict* dict;
|
||||
ProtocolId protocol_id;
|
||||
ProtocolId protocol_id_next;
|
||||
LFRFIDWorkerReadType read_type;
|
||||
|
||||
uint8_t* old_key_data;
|
||||
uint8_t* new_key_data;
|
||||
|
||||
RpcAppSystem* rpc_ctx;
|
||||
LfRfidRpcState rpc_state;
|
||||
|
||||
// Common Views
|
||||
Submenu* submenu;
|
||||
DialogEx* dialog_ex;
|
||||
Popup* popup;
|
||||
TextInput* text_input;
|
||||
ByteInput* byte_input;
|
||||
|
||||
// Custom views
|
||||
LfRfidReadView* read_view;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LfRfidViewSubmenu,
|
||||
LfRfidViewDialogEx,
|
||||
LfRfidViewPopup,
|
||||
LfRfidViewWidget,
|
||||
LfRfidViewTextInput,
|
||||
LfRfidViewByteInput,
|
||||
LfRfidViewRead,
|
||||
} LfRfidView;
|
||||
|
||||
bool lfrfid_save_key(LfRfid* app);
|
||||
|
||||
bool lfrfid_load_key_from_file_select(LfRfid* app);
|
||||
|
||||
bool lfrfid_delete_key(LfRfid* app);
|
||||
|
||||
bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog);
|
||||
|
||||
bool lfrfid_save_key_data(LfRfid* app, string_t path);
|
||||
|
||||
void lfrfid_make_app_folder(LfRfid* app);
|
||||
|
||||
void lfrfid_text_store_set(LfRfid* app, const char* text, ...);
|
||||
|
||||
void lfrfid_text_store_clear(LfRfid* app);
|
||||
|
||||
void lfrfid_popup_timeout_callback(void* context);
|
||||
|
||||
void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context);
|
||||
|
||||
void lfrfid_text_input_callback(void* context);
|
@ -1,88 +0,0 @@
|
||||
#include "lfrfid_app_scene_delete_confirm.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_data);
|
||||
string_init(string_header);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Back");
|
||||
button->set_callback(app, LfRfidAppSceneDeleteConfirm::back_callback);
|
||||
|
||||
button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Right, "Delete");
|
||||
button->set_callback(app, LfRfidAppSceneDeleteConfirm::delete_callback);
|
||||
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
auto line_3 = container->add<StringElement>();
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_data, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(string_data, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_printf(string_header, "Delete %s?", string_get_cstr(app->file_name));
|
||||
line_1->set_text(
|
||||
string_get_cstr(string_header), 64, 0, 128 - 2, AlignCenter, AlignTop, FontPrimary);
|
||||
line_2->set_text(
|
||||
string_get_cstr(string_data), 64, 19, 0, AlignCenter, AlignTop, FontSecondary);
|
||||
line_3->set_text(
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
64,
|
||||
49,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->delete_key();
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Stay) {
|
||||
app->scene_controller.switch_to_previous_scene();
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_data);
|
||||
string_clear(string_header);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneDeleteConfirm::back_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Stay;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneDeleteConfirm::delete_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneDeleteConfirm : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void back_callback(void* context);
|
||||
static void delete_callback(void* context);
|
||||
|
||||
string_t string_header;
|
||||
string_t string_data;
|
||||
};
|
@ -1,38 +0,0 @@
|
||||
#include "lfrfid_app_scene_delete_success.h"
|
||||
|
||||
void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_icon(0, 2, &I_DolphinMafia_115x62);
|
||||
popup->set_header("Deleted", 83, 19, AlignLeft, AlignBottom);
|
||||
popup->set_context(app);
|
||||
popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback);
|
||||
popup->set_timeout(1500);
|
||||
popup->enable_timeout();
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneDeleteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::SelectKey});
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneDeleteSuccess::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneDeleteSuccess::timeout_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneDeleteSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void timeout_callback(void* context);
|
||||
};
|
@ -1,36 +0,0 @@
|
||||
#include "lfrfid_app_scene_emulate.h"
|
||||
#include <core/common_defines.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("Emulating", 89, 30, AlignCenter, AlignTop);
|
||||
if(string_size(app->file_name)) {
|
||||
popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_text(
|
||||
protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
|
||||
}
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
UNUSED(app);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneEmulate : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
};
|
@ -1,59 +0,0 @@
|
||||
#include "lfrfid_app_scene_exit_confirm.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Exit");
|
||||
button->set_callback(app, LfRfidAppSceneExitConfirm::exit_callback);
|
||||
|
||||
button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Right, "Stay");
|
||||
button->set_callback(app, LfRfidAppSceneExitConfirm::stay_callback);
|
||||
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
|
||||
line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_2->set_text(
|
||||
"All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneExitConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Stay) {
|
||||
app->scene_controller.switch_to_previous_scene();
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExitConfirm::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExitConfirm::exit_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExitConfirm::stay_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Stay;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneExitConfirm : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void exit_callback(void* context);
|
||||
static void stay_callback(void* context);
|
||||
};
|
@ -1,63 +0,0 @@
|
||||
#include "lfrfid_app_scene_extra_actions.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuASK,
|
||||
SubmenuPSK,
|
||||
SubmenuRAW,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneExtraActions::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
submenu->add_item("Read ASK (Animal, Ordinary Card)", SubmenuASK, submenu_callback, app);
|
||||
submenu->add_item("Read PSK (Indala)", SubmenuPSK, submenu_callback, app);
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
submenu->add_item("Read RAW RFID data", SubmenuRAW, submenu_callback, app);
|
||||
}
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneExtraActions::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuASK:
|
||||
app->read_type = LFRFIDWorkerReadTypeASKOnly;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
case SubmenuPSK:
|
||||
app->read_type = LFRFIDWorkerReadTypePSKOnly;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
case SubmenuRAW:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawName);
|
||||
break;
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExtraActions::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExtraActions::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneExtraActions : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
};
|
@ -1,77 +0,0 @@
|
||||
#include "lfrfid_app_scene_raw_info.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
static void ok_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
static void back_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawInfo::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
|
||||
if(!sd_exist) {
|
||||
auto icon = container->add<IconElement>();
|
||||
icon->set_icon(0, 0, &I_SDQuestion_35x43);
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(
|
||||
"No SD card found.\nThis function will not\nwork without\nSD card.",
|
||||
81,
|
||||
4,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Back");
|
||||
button->set_callback(app, back_callback);
|
||||
} else {
|
||||
string_printf(
|
||||
string_info,
|
||||
"RAW RFID data reader\r\n"
|
||||
"1) Put the Flipper on your card\r\n"
|
||||
"2) Press OK\r\n"
|
||||
"3) Wait until data is read");
|
||||
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Center, "OK");
|
||||
button->set_callback(app, ok_callback);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawInfo::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.switch_to_scene({LfRfidApp::SceneType::RawRead});
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ExtraActions});
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawInfo::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawInfo : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_info;
|
||||
};
|
@ -1,46 +0,0 @@
|
||||
|
||||
#include "lfrfid_app_scene_raw_name.h"
|
||||
#include "m-string.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
void LfRfidAppSceneRawName::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
const char* key_name = string_get_cstr(app->raw_file_name);
|
||||
|
||||
bool key_name_empty = (string_size(app->raw_file_name) == 0);
|
||||
if(key_name_empty) {
|
||||
app->text_store.set("RfidRecord");
|
||||
} else {
|
||||
app->text_store.set("%s", key_name);
|
||||
}
|
||||
|
||||
auto text_input = app->view_controller.get<TextInputVM>();
|
||||
text_input->set_header_text("Name the raw file");
|
||||
|
||||
text_input->set_result_callback(
|
||||
save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty);
|
||||
|
||||
app->view_controller.switch_to<TextInputVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
string_set_str(app->raw_file_name, app->text_store.text);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawInfo);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawName::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<TextInputVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawName::save_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawName : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void save_callback(void* context);
|
||||
};
|
@ -1,107 +0,0 @@
|
||||
#include "lfrfid_app_scene_raw_read.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define RAW_READ_TIME 5000
|
||||
|
||||
static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
switch(result) {
|
||||
case LFRFIDWorkerReadRawFileError:
|
||||
event.type = LfRfidApp::EventType::ReadEventError;
|
||||
break;
|
||||
case LFRFIDWorkerReadRawOverrun:
|
||||
event.type = LfRfidApp::EventType::ReadEventOverrun;
|
||||
break;
|
||||
}
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
static void timer_callback(void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::ReadEventDone;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawRead::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_file_name);
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
app->make_app_folder();
|
||||
|
||||
timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app);
|
||||
furi_timer_start(timer, RAW_READ_TIME);
|
||||
string_printf(
|
||||
string_file_name, "%s/%s.ask.raw", app->app_sd_folder, string_get_cstr(app->raw_file_name));
|
||||
popup->set_header("Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(string_file_name),
|
||||
LFRFIDWorkerReadTypeASKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
|
||||
is_psk = false;
|
||||
error = false;
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
UNUSED(app);
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::ReadEventError:
|
||||
error = true;
|
||||
popup->set_header("Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_red);
|
||||
furi_timer_stop(timer);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventDone:
|
||||
if(!error) {
|
||||
if(is_psk) {
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawSuccess);
|
||||
} else {
|
||||
popup->set_header("Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
string_printf(
|
||||
string_file_name,
|
||||
"%s/%s.psk.raw",
|
||||
app->app_sd_folder,
|
||||
string_get_cstr(app->raw_file_name));
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(string_file_name),
|
||||
LFRFIDWorkerReadTypePSKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
furi_timer_start(timer, RAW_READ_TIME);
|
||||
is_psk = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawRead::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
furi_timer_free(timer);
|
||||
string_clear(string_file_name);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawRead : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_file_name;
|
||||
FuriTimer* timer;
|
||||
bool is_psk;
|
||||
bool error;
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
#include "lfrfid_app_scene_raw_success.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneRawSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
|
||||
string_printf(string_info, "RAW RFID read success!\r\n");
|
||||
string_cat_printf(string_info, "Now you can analyze files\r\n");
|
||||
string_cat_printf(string_info, "Or send them to developers");
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Center, "OK");
|
||||
button->set_callback(app, LfRfidAppSceneRawSuccess::ok_callback);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ExtraActions});
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawSuccess::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawSuccess::ok_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_info;
|
||||
static void ok_callback(void* context);
|
||||
};
|
@ -1,100 +0,0 @@
|
||||
#include "lfrfid_app_scene_read.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static void lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
switch(result) {
|
||||
case LFRFIDWorkerReadSenseStart:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseStart;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseEnd:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseEnd;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseCardStart:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseCardStart;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseCardEnd:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseCardEnd;
|
||||
break;
|
||||
case LFRFIDWorkerReadDone:
|
||||
event.type = LfRfidApp::EventType::ReadEventDone;
|
||||
break;
|
||||
case LFRFIDWorkerReadStartASK:
|
||||
event.type = LfRfidApp::EventType::ReadEventStartASK;
|
||||
break;
|
||||
case LFRFIDWorkerReadStartPSK:
|
||||
event.type = LfRfidApp::EventType::ReadEventStartPSK;
|
||||
break;
|
||||
}
|
||||
|
||||
event.payload.signed_int = protocol;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||
popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
}
|
||||
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::ReadEventSenseStart:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventSenseCardStart:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_green);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventSenseEnd:
|
||||
case LfRfidApp::EventType::ReadEventSenseCardEnd:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventDone:
|
||||
app->protocol_id = event->payload.signed_int;
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
notification_message(app->notification, &sequence_success);
|
||||
string_reset(app->file_name);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventStartPSK:
|
||||
popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventStartASK:
|
||||
popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRead::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRead : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
};
|
@ -1,60 +0,0 @@
|
||||
#include "lfrfid_app_scene_read_menu.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuSave,
|
||||
SubmenuEmulate,
|
||||
SubmenuWrite,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneReadKeyMenu::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
submenu->add_item("Save", SubmenuSave, submenu_callback, app);
|
||||
submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
|
||||
submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneReadKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuWrite:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
|
||||
break;
|
||||
case SubmenuSave:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
|
||||
break;
|
||||
case SubmenuEmulate:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.switch_to_previous_scene();
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadKeyMenu::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadKeyMenu::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneReadKeyMenu : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
};
|
@ -1,96 +0,0 @@
|
||||
#include "lfrfid_app_scene_read_success.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
string_init(string_header);
|
||||
|
||||
string_init_printf(
|
||||
string_header,
|
||||
"%s[%s]",
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
protocol_dict_get_manufacturer(app->dict, app->protocol_id));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_info, " ");
|
||||
}
|
||||
|
||||
if(i >= 9) {
|
||||
string_cat_printf(string_info, "...");
|
||||
break;
|
||||
} else {
|
||||
string_cat_printf(string_info, "%02X", data[i]);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Retry");
|
||||
button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback);
|
||||
|
||||
button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Right, "More");
|
||||
button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback);
|
||||
|
||||
auto header = container->add<StringElement>();
|
||||
header->set_text(string_get_cstr(string_header), 0, 2, 0, AlignLeft, AlignTop, FontPrimary);
|
||||
|
||||
auto text = container->add<StringElement>();
|
||||
text->set_text(string_get_cstr(string_info), 0, 16, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
|
||||
notification_message_block(app->notification, &sequence_set_green_255);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadKeyMenu);
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Retry) {
|
||||
app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::RetryConfirm});
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::ExitConfirm});
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
|
||||
notification_message_block(app->notification, &sequence_reset_green);
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
string_clear(string_header);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Retry;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadSuccess::more_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,16 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneReadSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void back_callback(void* context);
|
||||
static void more_callback(void* context);
|
||||
|
||||
string_t string_header;
|
||||
string_t string_info;
|
||||
};
|
@ -1,59 +0,0 @@
|
||||
#include "lfrfid_app_scene_retry_confirm.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Exit");
|
||||
button->set_callback(app, LfRfidAppSceneRetryConfirm::exit_callback);
|
||||
|
||||
button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Right, "Stay");
|
||||
button->set_callback(app, LfRfidAppSceneRetryConfirm::stay_callback);
|
||||
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
|
||||
line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
line_2->set_text(
|
||||
"All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRetryConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Read});
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Stay) {
|
||||
app->scene_controller.switch_to_previous_scene();
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRetryConfirm::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRetryConfirm::exit_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRetryConfirm::stay_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Stay;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRetryConfirm : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void exit_callback(void* context);
|
||||
static void stay_callback(void* context);
|
||||
};
|
@ -1,66 +0,0 @@
|
||||
#include "lfrfid_app_scene_rpc.h"
|
||||
#include <core/common_defines.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <rpc/rpc_app.h>
|
||||
|
||||
void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom);
|
||||
popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
|
||||
notification_message(app->notification, &sequence_display_backlight_on);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
UNUSED(app);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Exit) {
|
||||
consumed = true;
|
||||
LfRfidApp::Event view_event;
|
||||
view_event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&view_event);
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
|
||||
consumed = true;
|
||||
LfRfidApp::Event view_event;
|
||||
view_event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&view_event);
|
||||
} else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
|
||||
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||
consumed = true;
|
||||
bool result = false;
|
||||
if(arg && !emulating) {
|
||||
string_set_str(app->file_path, arg);
|
||||
if(app->load_key_data(app->file_path, false)) {
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
emulating = true;
|
||||
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
app->text_store.set("emulating\n%s", string_get_cstr(app->file_name));
|
||||
popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRpc::on_exit(LfRfidApp* app) {
|
||||
if(emulating) {
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
}
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRpc : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
bool emulating = false;
|
||||
};
|
@ -1,45 +0,0 @@
|
||||
#include "lfrfid_app_scene_save_data.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto byte_input = app->view_controller.get<ByteInputVM>();
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
|
||||
if(need_restore) {
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
} else {
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
}
|
||||
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
|
||||
byte_input->set_header_text("Enter the data in hex");
|
||||
|
||||
byte_input->set_result_callback(save_callback, NULL, app, app->new_key_data, size);
|
||||
|
||||
app->view_controller.switch_to<ByteInputVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveData::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
DOLPHIN_DEED(DolphinDeedRfidAdd);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveData::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ByteInputVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveData::save_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSaveData : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void save_callback(void* context);
|
||||
};
|
@ -1,72 +0,0 @@
|
||||
#include "lfrfid_app_scene_save_name.h"
|
||||
#include "m-string.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
const char* key_name = string_get_cstr(app->file_name);
|
||||
|
||||
bool key_name_empty = (string_size(app->file_name) == 0);
|
||||
if(key_name_empty) {
|
||||
string_set_str(app->file_path, app->app_folder);
|
||||
set_random_name(app->text_store.text, app->text_store.text_size);
|
||||
} else {
|
||||
app->text_store.set("%s", key_name);
|
||||
}
|
||||
|
||||
auto text_input = app->view_controller.get<TextInputVM>();
|
||||
text_input->set_header_text("Name the card");
|
||||
|
||||
text_input->set_result_callback(
|
||||
save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty);
|
||||
|
||||
string_t folder_path;
|
||||
string_init(folder_path);
|
||||
|
||||
path_extract_dirname(string_get_cstr(app->file_path), folder_path);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name);
|
||||
text_input->set_validator(validator_is_file_callback, validator_is_file);
|
||||
|
||||
string_clear(folder_path);
|
||||
|
||||
app->view_controller.switch_to<TextInputVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
if(string_size(app->file_name) > 0) {
|
||||
app->delete_key();
|
||||
}
|
||||
|
||||
string_set_str(app->file_name, app->text_store.text);
|
||||
|
||||
if(app->save_key()) {
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
|
||||
} else {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ReadKeyMenu});
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveName::on_exit(LfRfidApp* app) {
|
||||
void* validator_context =
|
||||
app->view_controller.get<TextInputVM>()->get_validator_callback_context();
|
||||
app->view_controller.get<TextInputVM>()->set_validator(NULL, NULL);
|
||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
|
||||
app->view_controller.get<TextInputVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveName::save_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSaveName : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void save_callback(void* context);
|
||||
};
|
@ -1,50 +0,0 @@
|
||||
#include "lfrfid_app_scene_save_success.h"
|
||||
#include <gui/scene_manager.h>
|
||||
#include <dolphin/dolphin.h>
|
||||
#include <stdint.h>
|
||||
|
||||
void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidSave);
|
||||
popup->set_icon(32, 5, &I_DolphinNice_96x59);
|
||||
popup->set_header("Saved!", 5, 7, AlignLeft, AlignTop);
|
||||
popup->set_context(app);
|
||||
popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback);
|
||||
popup->set_timeout(1500);
|
||||
popup->enable_timeout();
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Back) {
|
||||
bool result = app->scene_controller.has_previous_scene(
|
||||
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||
|
||||
if(result) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||
} else {
|
||||
app->scene_controller.search_and_switch_to_another_scene(
|
||||
{LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey);
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveSuccess::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveSuccess::timeout_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSaveSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void timeout_callback(void* context);
|
||||
};
|
@ -1,53 +0,0 @@
|
||||
#include "lfrfid_app_scene_save_type.h"
|
||||
|
||||
void LfRfidAppSceneSaveType::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
for(uint8_t i = 0; i < keys_count; i++) {
|
||||
string_init_printf(
|
||||
submenu_name[i],
|
||||
"%s %s",
|
||||
protocol_dict_get_manufacturer(app->dict, i),
|
||||
protocol_dict_get_name(app->dict, i));
|
||||
submenu->add_item(string_get_cstr(submenu_name[i]), i, submenu_callback, app);
|
||||
}
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
|
||||
// clear key name
|
||||
string_reset(app->file_name);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveType::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
app->protocol_id = event->payload.signed_int;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveType::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
for(uint8_t i = 0; i < keys_count; i++) {
|
||||
string_clear(submenu_name[i]);
|
||||
}
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSaveType::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,15 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSaveType : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
static const uint8_t keys_count = static_cast<uint8_t>(LFRFIDProtocol::LFRFIDProtocolMax);
|
||||
string_t submenu_name[keys_count];
|
||||
};
|
@ -1,48 +0,0 @@
|
||||
#include "lfrfid_app_scene_saved_info.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
|
||||
string_printf(
|
||||
string_info,
|
||||
"%s [%s]\r\n",
|
||||
string_get_cstr(app->file_name),
|
||||
protocol_dict_get_name(app->dict, app->protocol_id));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_info, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(string_info, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto line_1 = container->add<StringElement>();
|
||||
line_1->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSavedInfo::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSavedInfo : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_info;
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
#include "lfrfid_app_scene_saved_key_menu.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuEmulate,
|
||||
SubmenuWrite,
|
||||
SubmenuEdit,
|
||||
SubmenuDelete,
|
||||
SubmenuInfo,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneSavedKeyMenu::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
|
||||
submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
|
||||
submenu->add_item("Edit", SubmenuEdit, submenu_callback, app);
|
||||
submenu->add_item("Delete", SubmenuDelete, submenu_callback, app);
|
||||
submenu->add_item("Info", SubmenuInfo, submenu_callback, app);
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSavedKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuEmulate:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
|
||||
break;
|
||||
case SubmenuWrite:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
|
||||
break;
|
||||
case SubmenuEdit:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData);
|
||||
break;
|
||||
case SubmenuDelete:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteConfirm);
|
||||
break;
|
||||
case SubmenuInfo:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedInfo);
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSavedKeyMenu::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSavedKeyMenu : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
#include "lfrfid_app_scene_select_key.h"
|
||||
|
||||
void LfRfidAppSceneSelectKey::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
if(app->load_key_from_file_select(need_restore)) {
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedKeyMenu);
|
||||
} else {
|
||||
app->scene_controller.switch_to_previous_scene();
|
||||
}
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSelectKey::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSelectKey::on_exit(LfRfidApp* /* app */) {
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneSelectKey : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
};
|
@ -1,67 +0,0 @@
|
||||
#include "lfrfid_app_scene_start.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuRead,
|
||||
SubmenuSaved,
|
||||
SubmenuAddManually,
|
||||
SubmenuExtraActions,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
submenu->add_item("Read", SubmenuRead, submenu_callback, app);
|
||||
submenu->add_item("Saved", SubmenuSaved, submenu_callback, app);
|
||||
submenu->add_item("Add Manually", SubmenuAddManually, submenu_callback, app);
|
||||
submenu->add_item("Extra Actions", SubmenuExtraActions, submenu_callback, app);
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
|
||||
// clear key
|
||||
string_reset(app->file_name);
|
||||
app->protocol_id = PROTOCOL_NO;
|
||||
app->read_type = LFRFIDWorkerReadTypeAuto;
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneStart::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuRead:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
case SubmenuSaved:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SelectKey);
|
||||
break;
|
||||
case SubmenuAddManually:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveType);
|
||||
break;
|
||||
case SubmenuExtraActions:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ExtraActions);
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneStart::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneStart::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneStart : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
};
|
@ -1,88 +0,0 @@
|
||||
#include "lfrfid_app_scene_write.h"
|
||||
|
||||
static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
switch(result) {
|
||||
case LFRFIDWorkerWriteOK:
|
||||
event.type = LfRfidApp::EventType::WriteEventOK;
|
||||
break;
|
||||
case LFRFIDWorkerWriteProtocolCannotBeWritten:
|
||||
event.type = LfRfidApp::EventType::WriteEventProtocolCannotBeWritten;
|
||||
break;
|
||||
case LFRFIDWorkerWriteFobCannotBeWritten:
|
||||
event.type = LfRfidApp::EventType::WriteEventFobCannotBeWritten;
|
||||
break;
|
||||
case LFRFIDWorkerWriteTooLongToWrite:
|
||||
event.type = LfRfidApp::EventType::WriteEventTooLongToWrite;
|
||||
break;
|
||||
}
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("Writing", 89, 30, AlignCenter, AlignTop);
|
||||
if(string_size(app->file_name)) {
|
||||
popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_text(
|
||||
protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
|
||||
}
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
app->old_key_data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_write_start(
|
||||
app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app);
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::WriteEventOK:
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::WriteSuccess);
|
||||
break;
|
||||
case LfRfidApp::EventType::WriteEventProtocolCannotBeWritten:
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Error", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text("This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_red);
|
||||
break;
|
||||
case LfRfidApp::EventType::WriteEventFobCannotBeWritten:
|
||||
case LfRfidApp::EventType::WriteEventTooLongToWrite:
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
"Make sure this\ncard is writable\nand not\nprotected.", 3, 17, AlignLeft, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWrite::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
free(app->old_key_data);
|
||||
}
|
@ -1,9 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneWrite : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
};
|
@ -1,38 +0,0 @@
|
||||
#include "lfrfid_app_scene_write_success.h"
|
||||
|
||||
void LfRfidAppSceneWriteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
popup->set_header("Successfully\nwritten!", 94, 3, AlignCenter, AlignTop);
|
||||
popup->set_icon(0, 6, &I_RFIDDolphinSuccess_108x57);
|
||||
popup->set_context(app);
|
||||
popup->set_callback(LfRfidAppSceneWriteSuccess::timeout_callback);
|
||||
popup->set_timeout(1500);
|
||||
popup->enable_timeout();
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
notification_message_block(app->notification, &sequence_set_green_255);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneWriteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWriteSuccess::on_exit(LfRfidApp* app) {
|
||||
notification_message_block(app->notification, &sequence_reset_green);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWriteSuccess::timeout_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneWriteSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void timeout_callback(void* context);
|
||||
};
|
30
applications/lfrfid/scenes/lfrfid_scene.c
Normal file
30
applications/lfrfid/scenes/lfrfid_scene.c
Normal file
@ -0,0 +1,30 @@
|
||||
#include "lfrfid_scene.h"
|
||||
|
||||
// Generate scene on_enter handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||
void (*const lfrfid_on_enter_handlers[])(void*) = {
|
||||
#include "lfrfid_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||
bool (*const lfrfid_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||
#include "lfrfid_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers array
|
||||
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||
void (*const lfrfid_on_exit_handlers[])(void* context) = {
|
||||
#include "lfrfid_scene_config.h"
|
||||
};
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Initialize scene handlers configuration structure
|
||||
const SceneManagerHandlers lfrfid_scene_handlers = {
|
||||
.on_enter_handlers = lfrfid_on_enter_handlers,
|
||||
.on_event_handlers = lfrfid_on_event_handlers,
|
||||
.on_exit_handlers = lfrfid_on_exit_handlers,
|
||||
.scene_num = LfRfidSceneNum,
|
||||
};
|
29
applications/lfrfid/scenes/lfrfid_scene.h
Normal file
29
applications/lfrfid/scenes/lfrfid_scene.h
Normal file
@ -0,0 +1,29 @@
|
||||
#pragma once
|
||||
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
// Generate scene id and total number
|
||||
#define ADD_SCENE(prefix, name, id) LfRfidScene##id,
|
||||
typedef enum {
|
||||
#include "lfrfid_scene_config.h"
|
||||
LfRfidSceneNum,
|
||||
} LfRfidScene;
|
||||
#undef ADD_SCENE
|
||||
|
||||
extern const SceneManagerHandlers lfrfid_scene_handlers;
|
||||
|
||||
// Generate scene on_enter handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||
#include "lfrfid_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_event handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) \
|
||||
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||
#include "lfrfid_scene_config.h"
|
||||
#undef ADD_SCENE
|
||||
|
||||
// Generate scene on_exit handlers declaration
|
||||
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||
#include "lfrfid_scene_config.h"
|
||||
#undef ADD_SCENE
|
24
applications/lfrfid/scenes/lfrfid_scene_config.h
Normal file
24
applications/lfrfid/scenes/lfrfid_scene_config.h
Normal file
@ -0,0 +1,24 @@
|
||||
ADD_SCENE(lfrfid, start, Start)
|
||||
ADD_SCENE(lfrfid, read, Read)
|
||||
ADD_SCENE(lfrfid, read_success, ReadSuccess)
|
||||
ADD_SCENE(lfrfid, retry_confirm, RetryConfirm)
|
||||
ADD_SCENE(lfrfid, exit_confirm, ExitConfirm)
|
||||
ADD_SCENE(lfrfid, delete_confirm, DeleteConfirm)
|
||||
ADD_SCENE(lfrfid, read_key_menu, ReadKeyMenu)
|
||||
ADD_SCENE(lfrfid, write, Write)
|
||||
ADD_SCENE(lfrfid, write_success, WriteSuccess)
|
||||
ADD_SCENE(lfrfid, emulate, Emulate)
|
||||
ADD_SCENE(lfrfid, save_name, SaveName)
|
||||
ADD_SCENE(lfrfid, save_success, SaveSuccess)
|
||||
ADD_SCENE(lfrfid, select_key, SelectKey)
|
||||
ADD_SCENE(lfrfid, saved_key_menu, SavedKeyMenu)
|
||||
ADD_SCENE(lfrfid, save_data, SaveData)
|
||||
ADD_SCENE(lfrfid, save_type, SaveType)
|
||||
ADD_SCENE(lfrfid, saved_info, SavedInfo)
|
||||
ADD_SCENE(lfrfid, delete_success, DeleteSuccess)
|
||||
ADD_SCENE(lfrfid, extra_actions, ExtraActions)
|
||||
ADD_SCENE(lfrfid, raw_info, RawInfo)
|
||||
ADD_SCENE(lfrfid, raw_name, RawName)
|
||||
ADD_SCENE(lfrfid, raw_read, RawRead)
|
||||
ADD_SCENE(lfrfid, raw_success, RawSuccess)
|
||||
ADD_SCENE(lfrfid, rpc, Rpc)
|
68
applications/lfrfid/scenes/lfrfid_scene_delete_confirm.c
Normal file
68
applications/lfrfid/scenes/lfrfid_scene_delete_confirm.c
Normal file
@ -0,0 +1,68 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_delete_confirm_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
string_t tmp_string;
|
||||
string_init(tmp_string);
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app);
|
||||
widget_add_button_element(widget, GuiButtonTypeRight, "Delete", lfrfid_widget_callback, app);
|
||||
|
||||
string_printf(tmp_string, "Delete %s?", string_get_cstr(app->file_name));
|
||||
widget_add_string_element(
|
||||
widget, 64, 0, AlignCenter, AlignTop, FontPrimary, string_get_cstr(tmp_string));
|
||||
|
||||
string_reset(tmp_string);
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(tmp_string, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(tmp_string, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 64, 19, AlignCenter, AlignTop, FontSecondary, string_get_cstr(tmp_string));
|
||||
widget_add_string_element(
|
||||
widget,
|
||||
64,
|
||||
49,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
FontSecondary,
|
||||
protocol_dict_get_name(app->dict, app->protocol_id));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
string_clear(tmp_string);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true; // Ignore Back button presses
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
lfrfid_delete_key(app);
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneDeleteSuccess);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_delete_confirm_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
35
applications/lfrfid/scenes/lfrfid_scene_delete_success.c
Normal file
35
applications/lfrfid/scenes/lfrfid_scene_delete_success.c
Normal file
@ -0,0 +1,35 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_delete_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
||||
popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
|
||||
popup_set_context(popup, app);
|
||||
popup_set_callback(popup, lfrfid_popup_timeout_callback);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if((event.type == SceneManagerEventTypeBack) ||
|
||||
((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
app->scene_manager, LfRfidSceneSelectKey);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_delete_success_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
popup_reset(app->popup);
|
||||
}
|
44
applications/lfrfid/scenes/lfrfid_scene_emulate.c
Normal file
44
applications/lfrfid/scenes/lfrfid_scene_emulate.c
Normal file
@ -0,0 +1,44 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_emulate_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
|
||||
popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop);
|
||||
if(!string_empty_p(app->file_name)) {
|
||||
popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup_set_text(
|
||||
popup,
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
89,
|
||||
43,
|
||||
AlignCenter,
|
||||
AlignTop);
|
||||
}
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_emulate_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
popup_reset(app->popup);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
}
|
39
applications/lfrfid/scenes/lfrfid_scene_exit_confirm.c
Normal file
39
applications/lfrfid/scenes/lfrfid_scene_exit_confirm.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_exit_confirm_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app);
|
||||
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app);
|
||||
widget_add_string_element(
|
||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to RFID Menu?");
|
||||
widget_add_string_element(
|
||||
widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true; // Ignore Back button presses
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneStart);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_exit_confirm_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
79
applications/lfrfid/scenes/lfrfid_scene_extra_actions.c
Normal file
79
applications/lfrfid/scenes/lfrfid_scene_extra_actions.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexASK,
|
||||
SubmenuIndexPSK,
|
||||
SubmenuIndexRAW,
|
||||
} SubmenuIndex;
|
||||
|
||||
static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void lfrfid_scene_extra_actions_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read ASK (Animal, Ordinary Card)",
|
||||
SubmenuIndexASK,
|
||||
lfrfid_scene_extra_actions_submenu_callback,
|
||||
app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read PSK (Indala)",
|
||||
SubmenuIndexPSK,
|
||||
lfrfid_scene_extra_actions_submenu_callback,
|
||||
app);
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Read RAW RFID data",
|
||||
SubmenuIndexRAW,
|
||||
lfrfid_scene_extra_actions_submenu_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
|
||||
|
||||
// clear key
|
||||
string_reset(app->file_name);
|
||||
app->protocol_id = PROTOCOL_NO;
|
||||
app->read_type = LFRFIDWorkerReadTypeAuto;
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexASK) {
|
||||
app->read_type = LFRFIDWorkerReadTypeASKOnly;
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexPSK) {
|
||||
app->read_type = LFRFIDWorkerReadTypePSKOnly;
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexRAW) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_extra_actions_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
}
|
64
applications/lfrfid/scenes/lfrfid_scene_raw_info.c
Normal file
64
applications/lfrfid/scenes/lfrfid_scene_raw_info.c
Normal file
@ -0,0 +1,64 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_raw_info_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
// string_t tmp_string;
|
||||
// string_init(tmp_string);
|
||||
|
||||
bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
|
||||
if(!sd_exist) {
|
||||
widget_add_icon_element(widget, 0, 0, &I_SDQuestion_35x43);
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
81,
|
||||
4,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"No SD card found.\nThis function will not\nwork without\nSD card.");
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app);
|
||||
} else {
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
0,
|
||||
1,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"RAW RFID data reader\n1) Put the Flipper on your card\n2) Press OK\n3) Wait until data is read");
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app);
|
||||
}
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
//string_clear(tmp_string);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_raw_info_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true;
|
||||
scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneExtraActions);
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeCenter) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneRawRead);
|
||||
} else if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, LfRfidSceneExtraActions);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_raw_info_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
58
applications/lfrfid/scenes/lfrfid_scene_raw_name.c
Normal file
58
applications/lfrfid/scenes/lfrfid_scene_raw_name.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_raw_name_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
|
||||
const char* key_name = string_get_cstr(app->raw_file_name);
|
||||
|
||||
bool key_name_is_empty = string_empty_p(app->file_name);
|
||||
if(key_name_is_empty) {
|
||||
lfrfid_text_store_set(app, "RfidRecord");
|
||||
} else {
|
||||
lfrfid_text_store_set(app, "%s", key_name);
|
||||
}
|
||||
|
||||
text_input_set_header_text(text_input, "Name the raw file");
|
||||
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
lfrfid_text_input_callback,
|
||||
app,
|
||||
app->text_store,
|
||||
LFRFID_KEY_NAME_SIZE,
|
||||
key_name_is_empty);
|
||||
|
||||
ValidatorIsFile* validator_is_file =
|
||||
validator_is_file_alloc_init(LFRFID_SD_FOLDER, LFRFID_APP_RAW_ASK_EXTENSION, NULL);
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_raw_name_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventNext) {
|
||||
consumed = true;
|
||||
string_set_str(app->raw_file_name, app->text_store);
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneRawInfo);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_raw_name_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
|
||||
void* validator_context = text_input_get_validator_callback_context(text_input);
|
||||
text_input_set_validator(text_input, NULL, NULL);
|
||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
|
||||
text_input_reset(text_input);
|
||||
}
|
126
applications/lfrfid/scenes/lfrfid_scene_raw_read.c
Normal file
126
applications/lfrfid/scenes/lfrfid_scene_raw_read.c
Normal file
@ -0,0 +1,126 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
#define RAW_READ_TIME 5000
|
||||
|
||||
typedef struct {
|
||||
string_t string_file_name;
|
||||
FuriTimer* timer;
|
||||
bool is_psk;
|
||||
bool error;
|
||||
} LfRfidReadRawState;
|
||||
|
||||
static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
if(result == LFRFIDWorkerReadRawFileError) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError);
|
||||
} else if(result == LFRFIDWorkerReadRawOverrun) {
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun);
|
||||
}
|
||||
}
|
||||
|
||||
static void timer_callback(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadDone);
|
||||
}
|
||||
|
||||
void lfrfid_scene_raw_read_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState));
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state);
|
||||
string_init(state->string_file_name);
|
||||
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_make_app_folder(app);
|
||||
|
||||
state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app);
|
||||
furi_timer_start(state->timer, RAW_READ_TIME);
|
||||
string_printf(
|
||||
state->string_file_name,
|
||||
"%s/%s%s",
|
||||
LFRFID_SD_FOLDER,
|
||||
string_get_cstr(app->raw_file_name),
|
||||
LFRFID_APP_RAW_ASK_EXTENSION);
|
||||
popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(state->string_file_name),
|
||||
LFRFIDWorkerReadTypeASKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_start_cyan);
|
||||
|
||||
state->is_psk = false;
|
||||
state->error = false;
|
||||
}
|
||||
|
||||
bool lfrfid_scene_raw_read_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
LfRfidReadRawState* state =
|
||||
(LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead);
|
||||
bool consumed = false;
|
||||
|
||||
furi_assert(state);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventReadError) {
|
||||
consumed = true;
|
||||
state->error = true;
|
||||
popup_set_header(
|
||||
popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notifications, &sequence_blink_start_red);
|
||||
furi_timer_stop(state->timer);
|
||||
} else if(event.event == LfRfidEventReadDone) {
|
||||
consumed = true;
|
||||
if(!state->error) {
|
||||
if(state->is_psk) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRawSuccess);
|
||||
} else {
|
||||
popup_set_header(
|
||||
popup, "Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notifications, &sequence_blink_start_yellow);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
string_printf(
|
||||
state->string_file_name,
|
||||
"%s/%s%s",
|
||||
LFRFID_SD_FOLDER,
|
||||
string_get_cstr(app->raw_file_name),
|
||||
LFRFID_APP_RAW_PSK_EXTENSION);
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(state->string_file_name),
|
||||
LFRFIDWorkerReadTypePSKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
furi_timer_start(state->timer, RAW_READ_TIME);
|
||||
state->is_psk = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_raw_read_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
LfRfidReadRawState* state =
|
||||
(LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
popup_reset(app->popup);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
furi_timer_free(state->timer);
|
||||
|
||||
string_clear(state->string_file_name);
|
||||
free(state);
|
||||
}
|
39
applications/lfrfid/scenes/lfrfid_scene_raw_success.c
Normal file
39
applications/lfrfid/scenes/lfrfid_scene_raw_success.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_raw_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app);
|
||||
|
||||
widget_add_string_multiline_element(
|
||||
widget,
|
||||
0,
|
||||
1,
|
||||
AlignLeft,
|
||||
AlignTop,
|
||||
FontSecondary,
|
||||
"RAW RFID read success!\nNow you can analyze files\nOr send them to developers");
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_raw_success_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeCenter) {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, LfRfidSceneExtraActions);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_raw_success_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
109
applications/lfrfid/scenes/lfrfid_scene_read.c
Normal file
109
applications/lfrfid/scenes/lfrfid_scene_read.c
Normal file
@ -0,0 +1,109 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static const NotificationSequence sequence_blink_set_yellow = {
|
||||
&message_blink_set_color_yellow,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_set_green = {
|
||||
&message_blink_set_color_green,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static const NotificationSequence sequence_blink_set_cyan = {
|
||||
&message_blink_set_color_cyan,
|
||||
NULL,
|
||||
};
|
||||
|
||||
static void
|
||||
lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* context) {
|
||||
LfRfid* app = context;
|
||||
uint32_t event = 0;
|
||||
|
||||
if(result == LFRFIDWorkerReadSenseStart) {
|
||||
event = LfRfidEventReadSenseStart;
|
||||
} else if(result == LFRFIDWorkerReadSenseEnd) {
|
||||
event = LfRfidEventReadSenseEnd;
|
||||
} else if(result == LFRFIDWorkerReadSenseCardStart) {
|
||||
event = LfRfidEventReadSenseCardStart;
|
||||
} else if(result == LFRFIDWorkerReadSenseCardEnd) {
|
||||
event = LfRfidEventReadSenseCardEnd;
|
||||
} else if(result == LFRFIDWorkerReadDone) {
|
||||
event = LfRfidEventReadDone;
|
||||
app->protocol_id_next = protocol;
|
||||
} else if(result == LFRFIDWorkerReadStartASK) {
|
||||
event = LfRfidEventReadStartASK;
|
||||
} else if(result == LFRFIDWorkerReadStartPSK) {
|
||||
event = LfRfidEventReadStartPSK;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void lfrfid_scene_read_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
|
||||
} else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
|
||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAskOnly);
|
||||
}
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_start_cyan);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewRead);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventReadSenseStart) {
|
||||
notification_message(app->notifications, &sequence_blink_set_yellow);
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadSenseCardStart) {
|
||||
notification_message(app->notifications, &sequence_blink_set_green);
|
||||
consumed = true;
|
||||
} else if(
|
||||
(event.event == LfRfidEventReadSenseEnd) ||
|
||||
(event.event == LfRfidEventReadSenseCardEnd)) {
|
||||
notification_message(app->notifications, &sequence_blink_set_cyan);
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadDone) {
|
||||
app->protocol_id = app->protocol_id_next;
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
string_reset(app->file_name);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadStartPSK) {
|
||||
if(app->read_type == LFRFIDWorkerReadTypeAuto) {
|
||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPsk);
|
||||
}
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventReadStartASK) {
|
||||
if(app->read_type == LFRFIDWorkerReadTypeAuto) {
|
||||
lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAsk);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_read_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
popup_reset(app->popup);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
}
|
58
applications/lfrfid/scenes/lfrfid_scene_read_key_menu.c
Normal file
58
applications/lfrfid/scenes/lfrfid_scene_read_key_menu.c
Normal file
@ -0,0 +1,58 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexSave,
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexWrite,
|
||||
} SubmenuIndex;
|
||||
|
||||
void lfrfid_scene_read_key_menu_submenu_callback(void* context, uint32_t index) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void lfrfid_scene_read_key_menu_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "Save", SubmenuIndexSave, lfrfid_scene_read_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_read_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, lfrfid_scene_read_key_menu_submenu_callback, app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSave) {
|
||||
string_reset(app->file_name);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_read_key_menu_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
}
|
79
applications/lfrfid/scenes/lfrfid_scene_read_success.c
Normal file
79
applications/lfrfid/scenes/lfrfid_scene_read_success.c
Normal file
@ -0,0 +1,79 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_read_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
string_t tmp_string;
|
||||
string_init(tmp_string);
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app);
|
||||
widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app);
|
||||
|
||||
string_printf(
|
||||
tmp_string,
|
||||
"%s[%s]",
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
protocol_dict_get_manufacturer(app->dict, app->protocol_id));
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 2, AlignLeft, AlignTop, FontPrimary, string_get_cstr(tmp_string));
|
||||
|
||||
string_reset(tmp_string);
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(tmp_string, " ");
|
||||
}
|
||||
|
||||
if(i >= 9) {
|
||||
string_cat_printf(tmp_string, "...");
|
||||
break;
|
||||
} else {
|
||||
string_cat_printf(tmp_string, "%02X", data[i]);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
widget_add_string_element(
|
||||
widget, 0, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string));
|
||||
|
||||
notification_message_block(app->notifications, &sequence_set_green_255);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
string_clear(tmp_string);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneExitConfirm);
|
||||
consumed = true;
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneRetryConfirm);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneReadKeyMenu);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_read_success_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message_block(app->notifications, &sequence_reset_green);
|
||||
widget_reset(app->widget);
|
||||
}
|
39
applications/lfrfid/scenes/lfrfid_scene_retry_confirm.c
Normal file
39
applications/lfrfid/scenes/lfrfid_scene_retry_confirm.c
Normal file
@ -0,0 +1,39 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_retry_confirm_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app);
|
||||
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app);
|
||||
widget_add_string_element(
|
||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
|
||||
widget_add_string_element(
|
||||
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeBack) {
|
||||
consumed = true; // Ignore Back button presses
|
||||
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == GuiButtonTypeLeft) {
|
||||
scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneRead);
|
||||
} else if(event.event == GuiButtonTypeRight) {
|
||||
scene_manager_previous_scene(scene_manager);
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_retry_confirm_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
67
applications/lfrfid/scenes/lfrfid_scene_rpc.c
Normal file
67
applications/lfrfid/scenes/lfrfid_scene_rpc.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_rpc_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_set_header(popup, "LF RFID", 89, 42, AlignCenter, AlignBottom);
|
||||
popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
|
||||
notification_message(app->notifications, &sequence_display_backlight_on);
|
||||
|
||||
app->rpc_state = LfRfidRpcStateIdle;
|
||||
}
|
||||
|
||||
bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
consumed = true;
|
||||
if(event.event == LfRfidEventExit) {
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
} else if(event.event == LfRfidEventRpcSessionClose) {
|
||||
scene_manager_stop(app->scene_manager);
|
||||
view_dispatcher_stop(app->view_dispatcher);
|
||||
} else if(event.event == LfRfidEventRpcLoadFile) {
|
||||
const char* arg = rpc_system_app_get_data(app->rpc_ctx);
|
||||
bool result = false;
|
||||
if(arg && (app->rpc_state == LfRfidRpcStateIdle)) {
|
||||
string_set_str(app->file_path, arg);
|
||||
if(lfrfid_load_key_data(app, app->file_path, false)) {
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
app->rpc_state = LfRfidRpcStateEmulating;
|
||||
|
||||
lfrfid_text_store_set(app, "emulating\n%s", string_get_cstr(app->file_name));
|
||||
popup_set_text(popup, app->text_store, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
|
||||
}
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_rpc_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
if(app->rpc_state == LfRfidRpcStateEmulating) {
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
}
|
||||
|
||||
popup_reset(popup);
|
||||
}
|
51
applications/lfrfid/scenes/lfrfid_scene_save_data.c
Normal file
51
applications/lfrfid/scenes/lfrfid_scene_save_data.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_save_data_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
ByteInput* byte_input = app->byte_input;
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
|
||||
bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData);
|
||||
|
||||
if(need_restore) {
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
} else {
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
}
|
||||
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
|
||||
byte_input_set_header_text(byte_input, "Enter the data in hex");
|
||||
|
||||
byte_input_set_result_callback(
|
||||
byte_input, lfrfid_text_input_callback, NULL, app, app->new_key_data, size);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewByteInput);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventNext) {
|
||||
consumed = true;
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
DOLPHIN_DEED(DolphinDeedRfidAdd);
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1);
|
||||
}
|
||||
} else if(event.type == SceneManagerEventTypeBack) {
|
||||
scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_save_data_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
76
applications/lfrfid/scenes/lfrfid_scene_save_name.c
Normal file
76
applications/lfrfid/scenes/lfrfid_scene_save_name.c
Normal file
@ -0,0 +1,76 @@
|
||||
#include "m-string.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_save_name_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
string_t folder_path;
|
||||
string_init(folder_path);
|
||||
|
||||
bool key_name_is_empty = string_empty_p(app->file_name);
|
||||
if(key_name_is_empty) {
|
||||
string_set_str(app->file_path, LFRFID_APP_FOLDER);
|
||||
set_random_name(app->text_store, LFRFID_TEXT_STORE_SIZE);
|
||||
string_set_str(folder_path, LFRFID_APP_FOLDER);
|
||||
} else {
|
||||
lfrfid_text_store_set(app, "%s", string_get_cstr(app->file_name));
|
||||
path_extract_dirname(string_get_cstr(app->file_path), folder_path);
|
||||
}
|
||||
|
||||
text_input_set_header_text(text_input, "Name the card");
|
||||
text_input_set_result_callback(
|
||||
text_input,
|
||||
lfrfid_text_input_callback,
|
||||
app,
|
||||
app->text_store,
|
||||
LFRFID_KEY_NAME_SIZE,
|
||||
key_name_is_empty);
|
||||
|
||||
FURI_LOG_I("", "%s %s", string_get_cstr(folder_path), app->text_store);
|
||||
|
||||
ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
|
||||
string_get_cstr(folder_path), LFRFID_APP_EXTENSION, string_get_cstr(app->file_name));
|
||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||
|
||||
string_clear(folder_path);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
SceneManager* scene_manager = app->scene_manager;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventNext) {
|
||||
consumed = true;
|
||||
if(!string_empty_p(app->file_name)) {
|
||||
lfrfid_delete_key(app);
|
||||
}
|
||||
|
||||
string_set_str(app->file_name, app->text_store);
|
||||
|
||||
if(lfrfid_save_key(app)) {
|
||||
scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess);
|
||||
} else {
|
||||
scene_manager_search_and_switch_to_previous_scene(
|
||||
scene_manager, LfRfidSceneReadKeyMenu);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_save_name_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
TextInput* text_input = app->text_input;
|
||||
|
||||
void* validator_context = text_input_get_validator_callback_context(text_input);
|
||||
text_input_set_validator(text_input, NULL, NULL);
|
||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||
|
||||
text_input_reset(text_input);
|
||||
}
|
43
applications/lfrfid/scenes/lfrfid_scene_save_success.c
Normal file
43
applications/lfrfid/scenes/lfrfid_scene_save_success.c
Normal file
@ -0,0 +1,43 @@
|
||||
#include "../lfrfid_i.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void lfrfid_scene_save_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidSave);
|
||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||
popup_set_context(popup, app);
|
||||
popup_set_callback(popup, lfrfid_popup_timeout_callback);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey};
|
||||
|
||||
if((event.type == SceneManagerEventTypeBack) ||
|
||||
((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
|
||||
bool result = scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
app->scene_manager, prev_scenes, COUNT_OF(prev_scenes));
|
||||
if(!result) {
|
||||
scene_manager_search_and_switch_to_another_scene(
|
||||
app->scene_manager, LfRfidSceneSelectKey);
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_save_success_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
popup_reset(app->popup);
|
||||
}
|
86
applications/lfrfid/scenes/lfrfid_scene_save_type.c
Normal file
86
applications/lfrfid/scenes/lfrfid_scene_save_type.c
Normal file
@ -0,0 +1,86 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
typedef struct {
|
||||
string_t menu_item_name[LFRFIDProtocolMax];
|
||||
uint32_t line_sel;
|
||||
} SaveTypeCtx;
|
||||
|
||||
static void lfrfid_scene_save_type_submenu_callback(void* context, uint32_t index) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void lfrfid_scene_save_type_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
SaveTypeCtx* state = malloc(sizeof(SaveTypeCtx));
|
||||
for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
|
||||
if(strcmp(
|
||||
protocol_dict_get_manufacturer(app->dict, i),
|
||||
protocol_dict_get_name(app->dict, i)) != 0) {
|
||||
string_init_printf(
|
||||
state->menu_item_name[i],
|
||||
"%s %s",
|
||||
protocol_dict_get_manufacturer(app->dict, i),
|
||||
protocol_dict_get_name(app->dict, i));
|
||||
} else {
|
||||
string_init_printf(
|
||||
state->menu_item_name[i], "%s", protocol_dict_get_name(app->dict, i));
|
||||
}
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
string_get_cstr(state->menu_item_name[i]),
|
||||
i,
|
||||
lfrfid_scene_save_type_submenu_callback,
|
||||
app);
|
||||
}
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType));
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, (uint32_t)state);
|
||||
|
||||
// clear key name
|
||||
string_reset(app->file_name);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_save_type_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
SaveTypeCtx* state =
|
||||
(SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType);
|
||||
furi_check(state);
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
app->protocol_id = event.event;
|
||||
state->line_sel = event.event;
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_save_type_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
SaveTypeCtx* state =
|
||||
(SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType);
|
||||
furi_check(state);
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
|
||||
for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
|
||||
string_clear(state->menu_item_name[i]);
|
||||
}
|
||||
|
||||
uint32_t line_sel = state->line_sel;
|
||||
|
||||
free(state);
|
||||
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, line_sel);
|
||||
}
|
51
applications/lfrfid/scenes/lfrfid_scene_saved_info.c
Normal file
51
applications/lfrfid/scenes/lfrfid_scene_saved_info.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_saved_info_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Widget* widget = app->widget;
|
||||
|
||||
string_t tmp_string;
|
||||
string_init(tmp_string);
|
||||
|
||||
string_printf(
|
||||
tmp_string,
|
||||
"%s [%s]\r\n",
|
||||
string_get_cstr(app->file_name),
|
||||
protocol_dict_get_name(app->dict, app->protocol_id));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(tmp_string, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(tmp_string, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
widget_add_string_multiline_element(
|
||||
widget, 0, 1, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
|
||||
string_clear(tmp_string);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_saved_info_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_saved_info_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
widget_reset(app->widget);
|
||||
}
|
69
applications/lfrfid/scenes/lfrfid_scene_saved_key_menu.c
Normal file
69
applications/lfrfid/scenes/lfrfid_scene_saved_key_menu.c
Normal file
@ -0,0 +1,69 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexEmulate,
|
||||
SubmenuIndexWrite,
|
||||
SubmenuIndexEdit,
|
||||
SubmenuIndexDelete,
|
||||
SubmenuIndexInfo,
|
||||
} SubmenuIndex;
|
||||
|
||||
static void lfrfid_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void lfrfid_scene_saved_key_menu_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(
|
||||
submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Write", SubmenuIndexWrite, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Edit", SubmenuIndexEdit, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Info", SubmenuIndexInfo, lfrfid_scene_saved_key_menu_submenu_callback, app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu));
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexEmulate) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexWrite) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexEdit) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexDelete) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexInfo) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedInfo);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_saved_key_menu_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
}
|
22
applications/lfrfid/scenes/lfrfid_scene_select_key.c
Normal file
22
applications/lfrfid/scenes/lfrfid_scene_select_key.c
Normal file
@ -0,0 +1,22 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_select_key_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
if(lfrfid_load_key_from_file_select(app)) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedKeyMenu);
|
||||
} else {
|
||||
scene_manager_previous_scene(app->scene_manager);
|
||||
}
|
||||
}
|
||||
|
||||
bool lfrfid_scene_select_key_on_event(void* context, SceneManagerEvent event) {
|
||||
UNUSED(context);
|
||||
UNUSED(event);
|
||||
bool consumed = false;
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_select_key_on_exit(void* context) {
|
||||
UNUSED(context);
|
||||
}
|
72
applications/lfrfid/scenes/lfrfid_scene_start.c
Normal file
72
applications/lfrfid/scenes/lfrfid_scene_start.c
Normal file
@ -0,0 +1,72 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuIndexRead,
|
||||
SubmenuIndexSaved,
|
||||
SubmenuIndexAddManually,
|
||||
SubmenuIndexExtraActions,
|
||||
} SubmenuIndex;
|
||||
|
||||
static void lfrfid_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||
LfRfid* app = context;
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, index);
|
||||
}
|
||||
|
||||
void lfrfid_scene_start_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Submenu* submenu = app->submenu;
|
||||
|
||||
submenu_add_item(submenu, "Read", SubmenuIndexRead, lfrfid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Saved", SubmenuIndexSaved, lfrfid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu, "Add Manually", SubmenuIndexAddManually, lfrfid_scene_start_submenu_callback, app);
|
||||
submenu_add_item(
|
||||
submenu,
|
||||
"Extra Actions",
|
||||
SubmenuIndexExtraActions,
|
||||
lfrfid_scene_start_submenu_callback,
|
||||
app);
|
||||
|
||||
submenu_set_selected_item(
|
||||
submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneStart));
|
||||
|
||||
// clear key
|
||||
string_reset(app->file_name);
|
||||
app->protocol_id = PROTOCOL_NO;
|
||||
app->read_type = LFRFIDWorkerReadTypeAuto;
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == SubmenuIndexRead) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexSaved) {
|
||||
string_set_str(app->file_path, LFRFID_APP_FOLDER);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexAddManually) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
|
||||
consumed = true;
|
||||
} else if(event.event == SubmenuIndexExtraActions) {
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
|
||||
consumed = true;
|
||||
}
|
||||
scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_start_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
|
||||
submenu_reset(app->submenu);
|
||||
}
|
96
applications/lfrfid/scenes/lfrfid_scene_write.c
Normal file
96
applications/lfrfid/scenes/lfrfid_scene_write.c
Normal file
@ -0,0 +1,96 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* context) {
|
||||
LfRfid* app = context;
|
||||
uint32_t event = 0;
|
||||
|
||||
if(result == LFRFIDWorkerWriteOK) {
|
||||
event = LfRfidEventWriteOK;
|
||||
} else if(result == LFRFIDWorkerWriteProtocolCannotBeWritten) {
|
||||
event = LfRfidEventWriteProtocolCannotBeWritten;
|
||||
} else if(result == LFRFIDWorkerWriteFobCannotBeWritten) {
|
||||
event = LfRfidEventWriteFobCannotBeWritten;
|
||||
} else if(result == LFRFIDWorkerWriteTooLongToWrite) {
|
||||
event = LfRfidEventWriteTooLongToWrite;
|
||||
}
|
||||
|
||||
view_dispatcher_send_custom_event(app->view_dispatcher, event);
|
||||
}
|
||||
|
||||
void lfrfid_scene_write_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_set_header(popup, "Writing", 89, 30, AlignCenter, AlignTop);
|
||||
if(!string_empty_p(app->file_name)) {
|
||||
popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup_set_text(
|
||||
popup,
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
89,
|
||||
43,
|
||||
AlignCenter,
|
||||
AlignTop);
|
||||
}
|
||||
popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
app->old_key_data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_write_start(
|
||||
app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app);
|
||||
notification_message(app->notifications, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_write_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
bool consumed = false;
|
||||
|
||||
if(event.type == SceneManagerEventTypeCustom) {
|
||||
if(event.event == LfRfidEventWriteOK) {
|
||||
notification_message(app->notifications, &sequence_success);
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidSceneWriteSuccess);
|
||||
consumed = true;
|
||||
} else if(event.event == LfRfidEventWriteProtocolCannotBeWritten) {
|
||||
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
popup_set_header(popup, "Error", 64, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(popup, "This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop);
|
||||
notification_message(app->notifications, &sequence_blink_start_red);
|
||||
consumed = true;
|
||||
} else if(
|
||||
(event.event == LfRfidEventWriteFobCannotBeWritten) ||
|
||||
(event.event == LfRfidEventWriteTooLongToWrite)) {
|
||||
popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
|
||||
popup_set_header(popup, "Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||
popup_set_text(
|
||||
popup,
|
||||
"Make sure this\ncard is writable\nand not\nprotected.",
|
||||
3,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
notification_message(app->notifications, &sequence_blink_start_yellow);
|
||||
consumed = true;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_write_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message(app->notifications, &sequence_blink_stop);
|
||||
popup_reset(app->popup);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
free(app->old_key_data);
|
||||
}
|
38
applications/lfrfid/scenes/lfrfid_scene_write_success.c
Normal file
38
applications/lfrfid/scenes/lfrfid_scene_write_success.c
Normal file
@ -0,0 +1,38 @@
|
||||
#include "../lfrfid_i.h"
|
||||
|
||||
void lfrfid_scene_write_success_on_enter(void* context) {
|
||||
LfRfid* app = context;
|
||||
Popup* popup = app->popup;
|
||||
|
||||
popup_set_header(popup, "Successfully\nwritten!", 94, 3, AlignCenter, AlignTop);
|
||||
popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57);
|
||||
popup_set_context(popup, app);
|
||||
popup_set_callback(popup, lfrfid_popup_timeout_callback);
|
||||
popup_set_timeout(popup, 1500);
|
||||
popup_enable_timeout(popup);
|
||||
|
||||
view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
|
||||
notification_message_block(app->notifications, &sequence_set_green_255);
|
||||
}
|
||||
|
||||
bool lfrfid_scene_write_success_on_event(void* context, SceneManagerEvent event) {
|
||||
LfRfid* app = context;
|
||||
bool consumed = false;
|
||||
|
||||
const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey};
|
||||
|
||||
if((event.type == SceneManagerEventTypeBack) ||
|
||||
((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
|
||||
scene_manager_search_and_switch_to_previous_scene_one_of(
|
||||
app->scene_manager, prev_scenes, COUNT_OF(prev_scenes));
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void lfrfid_scene_write_success_on_exit(void* context) {
|
||||
LfRfid* app = context;
|
||||
notification_message_block(app->notifications, &sequence_reset_green);
|
||||
popup_reset(app->popup);
|
||||
}
|
@ -1,115 +0,0 @@
|
||||
#include "container_vm.h"
|
||||
#include "elements/generic_element.h"
|
||||
#include "elements/string_element.h"
|
||||
#include "elements/icon_element.h"
|
||||
#include "elements/button_element.h"
|
||||
#include <list>
|
||||
|
||||
class ContainerVMData {
|
||||
public:
|
||||
ContainerVMData(){};
|
||||
|
||||
~ContainerVMData() {
|
||||
for(auto& it : elements) delete it;
|
||||
};
|
||||
|
||||
std::list<GenericElement*> elements;
|
||||
|
||||
template <typename T> T add(const T element, View* view) {
|
||||
elements.push_back(element);
|
||||
element->set_parent_view(view);
|
||||
return element;
|
||||
}
|
||||
|
||||
void clean() {
|
||||
for(auto& it : elements) delete it;
|
||||
elements.clear();
|
||||
}
|
||||
};
|
||||
|
||||
struct ContainerVMModel {
|
||||
ContainerVMData* data;
|
||||
};
|
||||
|
||||
ContainerVM::ContainerVM() {
|
||||
view = view_alloc();
|
||||
view_set_context(view, this);
|
||||
view_allocate_model(view, ViewModelTypeLocking, sizeof(ContainerVMModel));
|
||||
|
||||
with_view_model_cpp(view, ContainerVMModel, model, {
|
||||
model->data = new ContainerVMData();
|
||||
return true;
|
||||
});
|
||||
|
||||
view_set_draw_callback(view, view_draw_callback);
|
||||
view_set_input_callback(view, view_input_callback);
|
||||
}
|
||||
|
||||
ContainerVM::~ContainerVM() {
|
||||
with_view_model_cpp(view, ContainerVMModel, model, {
|
||||
delete model->data;
|
||||
model->data = NULL;
|
||||
return false;
|
||||
});
|
||||
|
||||
view_free(view);
|
||||
}
|
||||
|
||||
View* ContainerVM::get_view() {
|
||||
return view;
|
||||
}
|
||||
|
||||
void ContainerVM::clean() {
|
||||
with_view_model_cpp(view, ContainerVMModel, model, {
|
||||
model->data->clean();
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T> T* ContainerVM::add() {
|
||||
T* element = new T();
|
||||
|
||||
with_view_model_cpp(view, ContainerVMModel, model, {
|
||||
model->data->add(element, view);
|
||||
return true;
|
||||
});
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
void ContainerVM::view_draw_callback(Canvas* canvas, void* model) {
|
||||
ContainerVMData* data = static_cast<ContainerVMModel*>(model)->data;
|
||||
|
||||
canvas_clear(canvas);
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
for(const auto& element : data->elements) {
|
||||
element->draw(canvas);
|
||||
}
|
||||
}
|
||||
|
||||
bool ContainerVM::view_input_callback(InputEvent* event, void* context) {
|
||||
bool consumed = false;
|
||||
View* view = static_cast<ContainerVM*>(context)->view;
|
||||
|
||||
with_view_model_cpp(view, ContainerVMModel, model, {
|
||||
for(const auto& element : model->data->elements) {
|
||||
if(element->input(event)) {
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
if(consumed) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
});
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
template StringElement* ContainerVM::add<StringElement>();
|
||||
template IconElement* ContainerVM::add<IconElement>();
|
||||
template ButtonElement* ContainerVM::add<ButtonElement>();
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include <view_modules/generic_view_module.h>
|
||||
|
||||
class ContainerVM : public GenericViewModule {
|
||||
public:
|
||||
ContainerVM();
|
||||
~ContainerVM() final;
|
||||
View* get_view() final;
|
||||
void clean() final;
|
||||
|
||||
template <typename T> T* add();
|
||||
|
||||
private:
|
||||
View* view;
|
||||
static void view_draw_callback(Canvas* canvas, void* model);
|
||||
static bool view_input_callback(InputEvent* event, void* context);
|
||||
};
|
@ -1,65 +0,0 @@
|
||||
#include "button_element.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
ButtonElement::ButtonElement() {
|
||||
}
|
||||
|
||||
ButtonElement::~ButtonElement() {
|
||||
}
|
||||
|
||||
void ButtonElement::draw(Canvas* canvas) {
|
||||
if(text != nullptr) {
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
switch(type) {
|
||||
case Type::Left:
|
||||
elements_button_left(canvas, text);
|
||||
break;
|
||||
case Type::Center:
|
||||
elements_button_center(canvas, text);
|
||||
break;
|
||||
case Type::Right:
|
||||
elements_button_right(canvas, text);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ButtonElement::input(InputEvent* event) {
|
||||
bool consumed = false;
|
||||
if(event->type == InputTypeShort && callback != nullptr) {
|
||||
switch(type) {
|
||||
case Type::Left:
|
||||
if(event->key == InputKeyLeft) {
|
||||
callback(context);
|
||||
consumed = true;
|
||||
}
|
||||
break;
|
||||
case Type::Center:
|
||||
if(event->key == InputKeyOk) {
|
||||
callback(context);
|
||||
consumed = true;
|
||||
}
|
||||
break;
|
||||
case Type::Right:
|
||||
if(event->key == InputKeyRight) {
|
||||
callback(context);
|
||||
consumed = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void ButtonElement::set_type(Type _type, const char* _text) {
|
||||
lock_model();
|
||||
type = _type;
|
||||
text = _text;
|
||||
unlock_model(true);
|
||||
}
|
||||
|
||||
void ButtonElement::set_callback(void* _context, ButtonElementCallback _callback) {
|
||||
context = _context;
|
||||
callback = _callback;
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include "generic_element.h"
|
||||
|
||||
typedef void (*ButtonElementCallback)(void* context);
|
||||
|
||||
class ButtonElement : public GenericElement {
|
||||
public:
|
||||
ButtonElement();
|
||||
~ButtonElement() final;
|
||||
void draw(Canvas* canvas) final;
|
||||
bool input(InputEvent* event) final;
|
||||
|
||||
enum class Type : uint8_t {
|
||||
Left,
|
||||
Center,
|
||||
Right,
|
||||
};
|
||||
|
||||
void set_type(Type type, const char* text);
|
||||
void set_callback(void* context, ButtonElementCallback callback);
|
||||
|
||||
private:
|
||||
Type type = Type::Left;
|
||||
const char* text = nullptr;
|
||||
|
||||
void* context = nullptr;
|
||||
ButtonElementCallback callback = nullptr;
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
#include "generic_element.h"
|
||||
|
||||
void GenericElement::lock_model() {
|
||||
furi_assert(view != nullptr);
|
||||
view_get_model(view);
|
||||
}
|
||||
|
||||
void GenericElement::unlock_model(bool need_redraw) {
|
||||
furi_assert(view != nullptr);
|
||||
view_commit_model(view, need_redraw);
|
||||
}
|
||||
|
||||
void GenericElement::set_parent_view(View* _view) {
|
||||
view = _view;
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
#pragma once
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
|
||||
class GenericElement {
|
||||
public:
|
||||
GenericElement(){};
|
||||
virtual ~GenericElement(){};
|
||||
virtual void draw(Canvas* canvas) = 0;
|
||||
virtual bool input(InputEvent* event) = 0;
|
||||
|
||||
// TODO that must be accessible only to ContainerVMData
|
||||
void set_parent_view(View* view);
|
||||
|
||||
// TODO that must be accessible only to inheritors
|
||||
void lock_model();
|
||||
void unlock_model(bool need_redraw);
|
||||
|
||||
private:
|
||||
View* view = nullptr;
|
||||
};
|
@ -1,25 +0,0 @@
|
||||
#include "icon_element.h"
|
||||
|
||||
IconElement::IconElement() {
|
||||
}
|
||||
|
||||
IconElement::~IconElement() {
|
||||
}
|
||||
|
||||
void IconElement::draw(Canvas* canvas) {
|
||||
if(icon != NULL) {
|
||||
canvas_draw_icon(canvas, x, y, icon);
|
||||
}
|
||||
}
|
||||
|
||||
bool IconElement::input(InputEvent* /* event */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void IconElement::set_icon(uint8_t _x, uint8_t _y, const Icon* _icon) {
|
||||
lock_model();
|
||||
icon = _icon;
|
||||
x = _x;
|
||||
y = _y;
|
||||
unlock_model(true);
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#pragma once
|
||||
#include "generic_element.h"
|
||||
|
||||
class IconElement : public GenericElement {
|
||||
public:
|
||||
IconElement();
|
||||
~IconElement() final;
|
||||
void draw(Canvas* canvas) final;
|
||||
bool input(InputEvent* event) final;
|
||||
|
||||
void set_icon(uint8_t x = 0, uint8_t y = 0, const Icon* icon = NULL);
|
||||
|
||||
private:
|
||||
const Icon* icon = NULL;
|
||||
uint8_t x = 0;
|
||||
uint8_t y = 0;
|
||||
};
|
@ -1,47 +0,0 @@
|
||||
#include "string_element.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
StringElement::StringElement() {
|
||||
}
|
||||
|
||||
StringElement::~StringElement() {
|
||||
}
|
||||
|
||||
void StringElement::draw(Canvas* canvas) {
|
||||
if(text) {
|
||||
string_t line;
|
||||
string_init(line);
|
||||
string_set_str(line, text);
|
||||
|
||||
canvas_set_font(canvas, font);
|
||||
if(fit_width != 0) {
|
||||
elements_string_fit_width(canvas, line, fit_width);
|
||||
}
|
||||
elements_multiline_text_aligned(canvas, x, y, horizontal, vertical, string_get_cstr(line));
|
||||
|
||||
string_clear(line);
|
||||
}
|
||||
}
|
||||
|
||||
bool StringElement::input(InputEvent* /* event */) {
|
||||
return false;
|
||||
}
|
||||
|
||||
void StringElement::set_text(
|
||||
const char* _text,
|
||||
uint8_t _x,
|
||||
uint8_t _y,
|
||||
uint8_t _fit_w,
|
||||
Align _horizontal,
|
||||
Align _vertical,
|
||||
Font _font) {
|
||||
lock_model();
|
||||
text = _text;
|
||||
x = _x;
|
||||
y = _y;
|
||||
fit_width = _fit_w;
|
||||
horizontal = _horizontal;
|
||||
vertical = _vertical;
|
||||
font = _font;
|
||||
unlock_model(true);
|
||||
}
|
@ -1,28 +0,0 @@
|
||||
#pragma once
|
||||
#include "generic_element.h"
|
||||
|
||||
class StringElement : public GenericElement {
|
||||
public:
|
||||
StringElement();
|
||||
~StringElement() final;
|
||||
void draw(Canvas* canvas) final;
|
||||
bool input(InputEvent* event) final;
|
||||
|
||||
void set_text(
|
||||
const char* text = NULL,
|
||||
uint8_t x = 0,
|
||||
uint8_t y = 0,
|
||||
uint8_t fit_width = 0,
|
||||
Align horizontal = AlignLeft,
|
||||
Align vertical = AlignTop,
|
||||
Font font = FontPrimary);
|
||||
|
||||
private:
|
||||
const char* text = NULL;
|
||||
uint8_t x = 0;
|
||||
uint8_t y = 0;
|
||||
uint8_t fit_width = 0;
|
||||
Align horizontal = AlignLeft;
|
||||
Align vertical = AlignTop;
|
||||
Font font = FontPrimary;
|
||||
};
|
117
applications/lfrfid/views/lfrfid_view_read.c
Normal file
117
applications/lfrfid/views/lfrfid_view_read.c
Normal file
@ -0,0 +1,117 @@
|
||||
#include "lfrfid_view_read.h"
|
||||
#include <gui/elements.h>
|
||||
|
||||
#define TEMP_STR_LEN 128
|
||||
|
||||
struct LfRfidReadView {
|
||||
View* view;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
IconAnimation* icon;
|
||||
LfRfidReadViewMode read_mode;
|
||||
} LfRfidReadViewModel;
|
||||
|
||||
static void lfrfid_view_read_draw_callback(Canvas* canvas, void* _model) {
|
||||
LfRfidReadViewModel* model = _model;
|
||||
canvas_set_color(canvas, ColorBlack);
|
||||
|
||||
canvas_draw_icon(canvas, 0, 8, &I_NFC_manual);
|
||||
|
||||
canvas_set_font(canvas, FontPrimary);
|
||||
|
||||
if(model->read_mode == LfRfidReadAsk) {
|
||||
canvas_draw_str(canvas, 70, 16, "Reading 1/2");
|
||||
|
||||
canvas_draw_str(canvas, 77, 29, "ASK");
|
||||
canvas_draw_icon(canvas, 70, 22, &I_ButtonRight_4x7);
|
||||
canvas_draw_icon_animation(canvas, 102, 21, model->icon);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 77, 43, "PSK");
|
||||
} else if(model->read_mode == LfRfidReadPsk) {
|
||||
canvas_draw_str(canvas, 70, 16, "Reading 2/2");
|
||||
|
||||
canvas_draw_str(canvas, 77, 43, "PSK");
|
||||
canvas_draw_icon(canvas, 70, 36, &I_ButtonRight_4x7);
|
||||
canvas_draw_icon_animation(canvas, 102, 35, model->icon);
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 77, 29, "ASK");
|
||||
} else {
|
||||
canvas_draw_str(canvas, 72, 16, "Reading");
|
||||
|
||||
if(model->read_mode == LfRfidReadAskOnly) {
|
||||
canvas_draw_str(canvas, 77, 35, "ASK");
|
||||
} else {
|
||||
canvas_draw_str(canvas, 77, 35, "PSK");
|
||||
}
|
||||
canvas_draw_icon_animation(canvas, 102, 27, model->icon);
|
||||
}
|
||||
|
||||
canvas_set_font(canvas, FontSecondary);
|
||||
canvas_draw_str(canvas, 61, 56, "Don't move card");
|
||||
}
|
||||
|
||||
void lfrfid_view_read_enter(void* context) {
|
||||
LfRfidReadView* read_view = context;
|
||||
with_view_model(
|
||||
read_view->view, (LfRfidReadViewModel * model) {
|
||||
icon_animation_start(model->icon);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
void lfrfid_view_read_exit(void* context) {
|
||||
LfRfidReadView* read_view = context;
|
||||
with_view_model(
|
||||
read_view->view, (LfRfidReadViewModel * model) {
|
||||
icon_animation_stop(model->icon);
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
LfRfidReadView* lfrfid_view_read_alloc() {
|
||||
LfRfidReadView* read_view = malloc(sizeof(LfRfidReadView));
|
||||
read_view->view = view_alloc();
|
||||
view_set_context(read_view->view, read_view);
|
||||
view_allocate_model(read_view->view, ViewModelTypeLocking, sizeof(LfRfidReadViewModel));
|
||||
|
||||
with_view_model(
|
||||
read_view->view, (LfRfidReadViewModel * model) {
|
||||
model->icon = icon_animation_alloc(&A_Round_loader_8x8);
|
||||
view_tie_icon_animation(read_view->view, model->icon);
|
||||
return false;
|
||||
});
|
||||
|
||||
view_set_draw_callback(read_view->view, lfrfid_view_read_draw_callback);
|
||||
view_set_enter_callback(read_view->view, lfrfid_view_read_enter);
|
||||
view_set_exit_callback(read_view->view, lfrfid_view_read_exit);
|
||||
|
||||
return read_view;
|
||||
}
|
||||
|
||||
void lfrfid_view_read_free(LfRfidReadView* read_view) {
|
||||
with_view_model(
|
||||
read_view->view, (LfRfidReadViewModel * model) {
|
||||
icon_animation_free(model->icon);
|
||||
return false;
|
||||
});
|
||||
|
||||
view_free(read_view->view);
|
||||
free(read_view);
|
||||
}
|
||||
|
||||
View* lfrfid_view_read_get_view(LfRfidReadView* read_view) {
|
||||
return read_view->view;
|
||||
}
|
||||
|
||||
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode) {
|
||||
with_view_model(
|
||||
read_view->view, (LfRfidReadViewModel * model) {
|
||||
icon_animation_stop(model->icon);
|
||||
icon_animation_start(model->icon);
|
||||
model->read_mode = mode;
|
||||
return true;
|
||||
});
|
||||
}
|
19
applications/lfrfid/views/lfrfid_view_read.h
Normal file
19
applications/lfrfid/views/lfrfid_view_read.h
Normal file
@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
#include <gui/view.h>
|
||||
|
||||
typedef enum {
|
||||
LfRfidReadAsk,
|
||||
LfRfidReadPsk,
|
||||
LfRfidReadAskOnly,
|
||||
LfRfidReadPskOnly
|
||||
} LfRfidReadViewMode;
|
||||
|
||||
typedef struct LfRfidReadView LfRfidReadView;
|
||||
|
||||
LfRfidReadView* lfrfid_view_read_alloc();
|
||||
|
||||
void lfrfid_view_read_free(LfRfidReadView* read_view);
|
||||
|
||||
View* lfrfid_view_read_get_view(LfRfidReadView* read_view);
|
||||
|
||||
void lfrfid_view_read_set_read_mode(LfRfidReadView* read_view, LfRfidReadViewMode mode);
|
81
applications/lfrfid_debug/lfrfid_debug.c
Normal file
81
applications/lfrfid_debug/lfrfid_debug.c
Normal file
@ -0,0 +1,81 @@
|
||||
#include "lfrfid_debug_i.h"
|
||||
|
||||
static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
|
||||
furi_assert(context);
|
||||
LfRfidDebug* app = context;
|
||||
return scene_manager_handle_custom_event(app->scene_manager, event);
|
||||
}
|
||||
|
||||
static bool lfrfid_debug_back_event_callback(void* context) {
|
||||
furi_assert(context);
|
||||
LfRfidDebug* app = context;
|
||||
return scene_manager_handle_back_event(app->scene_manager);
|
||||
}
|
||||
|
||||
static LfRfidDebug* lfrfid_debug_alloc() {
|
||||
LfRfidDebug* app = malloc(sizeof(LfRfidDebug));
|
||||
|
||||
app->view_dispatcher = view_dispatcher_alloc();
|
||||
app->scene_manager = scene_manager_alloc(&lfrfid_debug_scene_handlers, app);
|
||||
view_dispatcher_enable_queue(app->view_dispatcher);
|
||||
view_dispatcher_set_event_callback_context(app->view_dispatcher, app);
|
||||
view_dispatcher_set_custom_event_callback(
|
||||
app->view_dispatcher, lfrfid_debug_custom_event_callback);
|
||||
view_dispatcher_set_navigation_event_callback(
|
||||
app->view_dispatcher, lfrfid_debug_back_event_callback);
|
||||
|
||||
// Open GUI record
|
||||
app->gui = furi_record_open(RECORD_GUI);
|
||||
view_dispatcher_attach_to_gui(app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
|
||||
|
||||
// Submenu
|
||||
app->submenu = submenu_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher, LfRfidDebugViewSubmenu, submenu_get_view(app->submenu));
|
||||
|
||||
// Tune view
|
||||
app->tune_view = lfrfid_debug_view_tune_alloc();
|
||||
view_dispatcher_add_view(
|
||||
app->view_dispatcher,
|
||||
LfRfidDebugViewTune,
|
||||
lfrfid_debug_view_tune_get_view(app->tune_view));
|
||||
|
||||
return app;
|
||||
}
|
||||
|
||||
static void lfrfid_debug_free(LfRfidDebug* app) {
|
||||
furi_assert(app);
|
||||
|
||||
// Submenu
|
||||
view_dispatcher_remove_view(app->view_dispatcher, LfRfidDebugViewSubmenu);
|
||||
submenu_free(app->submenu);
|
||||
|
||||
// Tune view
|
||||
view_dispatcher_remove_view(app->view_dispatcher, LfRfidDebugViewTune);
|
||||
lfrfid_debug_view_tune_free(app->tune_view);
|
||||
|
||||
// View Dispatcher
|
||||
view_dispatcher_free(app->view_dispatcher);
|
||||
|
||||
// Scene Manager
|
||||
scene_manager_free(app->scene_manager);
|
||||
|
||||
// GUI
|
||||
furi_record_close(RECORD_GUI);
|
||||
app->gui = NULL;
|
||||
|
||||
free(app);
|
||||
}
|
||||
|
||||
int32_t lfrfid_debug_app(void* p) {
|
||||
UNUSED(p);
|
||||
LfRfidDebug* app = lfrfid_debug_alloc();
|
||||
|
||||
scene_manager_next_scene(app->scene_manager, LfRfidDebugSceneStart);
|
||||
|
||||
view_dispatcher_run(app->view_dispatcher);
|
||||
|
||||
lfrfid_debug_free(app);
|
||||
|
||||
return 0;
|
||||
}
|
@ -1,17 +0,0 @@
|
||||
#include "lfrfid_debug_app.h"
|
||||
#include "scene/lfrfid_debug_app_scene_start.h"
|
||||
#include "scene/lfrfid_debug_app_scene_tune.h"
|
||||
|
||||
LfRfidDebugApp::LfRfidDebugApp()
|
||||
: scene_controller{this} {
|
||||
}
|
||||
|
||||
LfRfidDebugApp::~LfRfidDebugApp() {
|
||||
}
|
||||
|
||||
void LfRfidDebugApp::run() {
|
||||
view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
|
||||
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
|
||||
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
|
||||
scene_controller.process(100);
|
||||
}
|
@ -1,40 +0,0 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <generic_scene.hpp>
|
||||
#include <scene_controller.hpp>
|
||||
#include <view_controller.hpp>
|
||||
|
||||
#include <view_modules/submenu_vm.h>
|
||||
#include "view_modules/lfrfid_view_tune_vm.h"
|
||||
|
||||
class LfRfidDebugApp {
|
||||
public:
|
||||
enum class EventType : uint8_t {
|
||||
GENERIC_EVENT_ENUM_VALUES,
|
||||
MenuSelected,
|
||||
};
|
||||
|
||||
enum class SceneType : uint8_t {
|
||||
GENERIC_SCENE_ENUM_VALUES,
|
||||
TuneScene,
|
||||
};
|
||||
|
||||
class Event {
|
||||
public:
|
||||
union {
|
||||
int32_t menu_index;
|
||||
} payload;
|
||||
|
||||
EventType type;
|
||||
};
|
||||
|
||||
SceneController<GenericScene<LfRfidDebugApp>, LfRfidDebugApp> scene_controller;
|
||||
ViewController<LfRfidDebugApp, SubmenuVM, LfRfidViewTuneVM> view_controller;
|
||||
|
||||
~LfRfidDebugApp();
|
||||
LfRfidDebugApp();
|
||||
|
||||
void run();
|
||||
};
|
@ -1,11 +0,0 @@
|
||||
#include "lfrfid_debug_app.h"
|
||||
|
||||
// app enter function
|
||||
extern "C" int32_t lfrfid_debug_app(void* p) {
|
||||
UNUSED(p);
|
||||
LfRfidDebugApp* app = new LfRfidDebugApp();
|
||||
app->run();
|
||||
delete app;
|
||||
|
||||
return 0;
|
||||
}
|
31
applications/lfrfid_debug/lfrfid_debug_i.h
Normal file
31
applications/lfrfid_debug/lfrfid_debug_i.h
Normal file
@ -0,0 +1,31 @@
|
||||
#pragma once
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
|
||||
#include <gui/gui.h>
|
||||
#include <gui/view.h>
|
||||
#include <gui/view_dispatcher.h>
|
||||
#include <gui/scene_manager.h>
|
||||
|
||||
#include <gui/modules/submenu.h>
|
||||
|
||||
#include <lfrfid_debug/views/lfrfid_debug_view_tune.h>
|
||||
|
||||
#include <lfrfid_debug/scenes/lfrfid_debug_scene.h>
|
||||
|
||||
typedef struct LfRfidDebug LfRfidDebug;
|
||||
|
||||
struct LfRfidDebug {
|
||||
Gui* gui;
|
||||
ViewDispatcher* view_dispatcher;
|
||||
SceneManager* scene_manager;
|
||||
|
||||
// Common Views
|
||||
Submenu* submenu;
|
||||
LfRfidTuneView* tune_view;
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
LfRfidDebugViewSubmenu,
|
||||
LfRfidDebugViewTune,
|
||||
} LfRfidDebugView;
|
@ -1,47 +0,0 @@
|
||||
#include "lfrfid_debug_app_scene_start.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuTune,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidDebugAppSceneStart::on_enter(LfRfidDebugApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
auto callback = cbc::obtain_connector(this, &LfRfidDebugAppSceneStart::submenu_callback);
|
||||
|
||||
submenu->add_item("Tune", SubmenuTune, callback, app);
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
}
|
||||
|
||||
bool LfRfidDebugAppSceneStart::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidDebugApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.menu_index;
|
||||
switch(event->payload.menu_index) {
|
||||
case SubmenuTune:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidDebugApp::SceneType::TuneScene);
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidDebugAppSceneStart::on_exit(LfRfidDebugApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidDebugAppSceneStart::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidDebugApp* app = static_cast<LfRfidDebugApp*>(context);
|
||||
LfRfidDebugApp::Event event;
|
||||
|
||||
event.type = LfRfidDebugApp::EventType::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user