[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_path_folder = strdup(app_path_folder);
|
||||||
instance->app_extension = app_extension;
|
instance->app_extension = app_extension;
|
||||||
|
if(current_name != NULL) {
|
||||||
instance->current_name = strdup(current_name);
|
instance->current_name = strdup(current_name);
|
||||||
|
}
|
||||||
|
|
||||||
return instance;
|
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_t info;
|
||||||
string_init(info);
|
string_init(info);
|
||||||
protocol_dict_render_data(dict, info, context.protocol);
|
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));
|
printf("%s\r\n", string_get_cstr(info));
|
||||||
}
|
}
|
||||||
string_clear(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…
x
Reference in New Issue
Block a user