[FL-2627] Flipper applications: SDK, build and debug system (#1387)
* Added support for running applications from SD card (FAPs - Flipper Application Packages) * Added plugin_dist target for fbt to build FAPs * All apps of type FlipperAppType.EXTERNAL and FlipperAppType.PLUGIN are built as FAPs by default * Updated VSCode configuration for new fbt features - re-deploy stock configuration to use them * Added debugging support for FAPs with fbt debug & VSCode * Added public firmware API with automated versioning Co-authored-by: hedger <hedger@users.noreply.github.com> Co-authored-by: SG <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
25
applications/main/lfrfid/application.fam
Normal file
25
applications/main/lfrfid/application.fam
Normal file
@@ -0,0 +1,25 @@
|
||||
App(
|
||||
appid="lfrfid",
|
||||
name="125 kHz RFID",
|
||||
apptype=FlipperAppType.APP,
|
||||
entry_point="lfrfid_app",
|
||||
cdefines=["APP_LF_RFID"],
|
||||
requires=[
|
||||
"gui",
|
||||
"dialogs",
|
||||
],
|
||||
provides=[
|
||||
"lfrfid_start",
|
||||
],
|
||||
icon="A_125khz_14",
|
||||
stack_size=2 * 1024,
|
||||
order=20,
|
||||
)
|
||||
|
||||
App(
|
||||
appid="lfrfid_start",
|
||||
apptype=FlipperAppType.STARTUP,
|
||||
entry_point="lfrfid_on_system_start",
|
||||
requires=["lfrfid"],
|
||||
order=50,
|
||||
)
|
314
applications/main/lfrfid/lfrfid.c
Normal file
314
applications/main/lfrfid/lfrfid.c
Normal file
@@ -0,0 +1,314 @@
|
||||
#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);
|
||||
|
||||
DialogsFileBrowserOptions browser_options;
|
||||
dialog_file_browser_set_basic_options(&browser_options, LFRFID_APP_EXTENSION, &I_125_10px);
|
||||
|
||||
// Input events and views are managed by file_browser
|
||||
bool result =
|
||||
dialog_file_browser_show(app->dialogs, app->file_path, app->file_path, &browser_options);
|
||||
|
||||
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);
|
||||
}
|
575
applications/main/lfrfid/lfrfid_cli.c
Normal file
575
applications/main/lfrfid/lfrfid_cli.c
Normal file
@@ -0,0 +1,575 @@
|
||||
#include <furi.h>
|
||||
#include <furi_hal.h>
|
||||
#include <stdarg.h>
|
||||
#include <cli/cli.h>
|
||||
#include <lib/toolbox/args.h>
|
||||
#include <lib/lfrfid/lfrfid_worker.h>
|
||||
#include <storage/storage.h>
|
||||
#include <toolbox/stream/file_stream.h>
|
||||
|
||||
#include <toolbox/varint.h>
|
||||
|
||||
#include <toolbox/protocols/protocol_dict.h>
|
||||
#include <lfrfid/protocols/lfrfid_protocols.h>
|
||||
#include <lfrfid/lfrfid_raw_file.h>
|
||||
#include <toolbox/pulse_protocols/pulse_glue.h>
|
||||
|
||||
static void lfrfid_cli(Cli* cli, string_t args, void* context);
|
||||
|
||||
// app cli function
|
||||
void lfrfid_on_system_start() {
|
||||
Cli* cli = furi_record_open(RECORD_CLI);
|
||||
cli_add_command(cli, "rfid", CliCommandFlagDefault, lfrfid_cli, NULL);
|
||||
furi_record_close(RECORD_CLI);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_print_usage() {
|
||||
printf("Usage:\r\n");
|
||||
printf("rfid read <optional: normal | indala>\r\n");
|
||||
printf("rfid <write | emulate> <key_type> <key_data>\r\n");
|
||||
printf("rfid raw_read <ask | psk> <filename>\r\n");
|
||||
printf("rfid raw_emulate <filename>\r\n");
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
ProtocolId protocol;
|
||||
FuriEventFlag* event;
|
||||
} LFRFIDCliReadContext;
|
||||
|
||||
static void lfrfid_cli_read_callback(LFRFIDWorkerReadResult result, ProtocolId proto, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
LFRFIDCliReadContext* context = ctx;
|
||||
if(result == LFRFIDWorkerReadDone) {
|
||||
context->protocol = proto;
|
||||
FURI_SW_MEMBARRIER();
|
||||
}
|
||||
furi_event_flag_set(context->event, 1 << result);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_read(Cli* cli, string_t args) {
|
||||
string_t type_string;
|
||||
string_init(type_string);
|
||||
LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto;
|
||||
|
||||
if(args_read_string_and_trim(args, type_string)) {
|
||||
if(string_cmp_str(type_string, "normal") == 0 || string_cmp_str(type_string, "ask") == 0) {
|
||||
// ask
|
||||
type = LFRFIDWorkerReadTypeASKOnly;
|
||||
} else if(
|
||||
string_cmp_str(type_string, "indala") == 0 ||
|
||||
string_cmp_str(type_string, "psk") == 0) {
|
||||
// psk
|
||||
type = LFRFIDWorkerReadTypePSKOnly;
|
||||
} else {
|
||||
lfrfid_cli_print_usage();
|
||||
string_clear(type_string);
|
||||
return;
|
||||
}
|
||||
}
|
||||
string_clear(type_string);
|
||||
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
|
||||
LFRFIDCliReadContext context;
|
||||
context.protocol = PROTOCOL_NO;
|
||||
context.event = furi_event_flag_alloc();
|
||||
|
||||
lfrfid_worker_start_thread(worker);
|
||||
|
||||
printf("Reading RFID...\r\nPress Ctrl+C to abort\r\n");
|
||||
|
||||
const uint32_t available_flags = (1 << LFRFIDWorkerReadDone);
|
||||
|
||||
lfrfid_worker_read_start(worker, type, lfrfid_cli_read_callback, &context);
|
||||
|
||||
while(true) {
|
||||
uint32_t flags =
|
||||
furi_event_flag_wait(context.event, available_flags, FuriFlagWaitAny, 100);
|
||||
|
||||
if(flags != FuriFlagErrorTimeout) {
|
||||
if(FURI_BIT(flags, LFRFIDWorkerReadDone)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(cli_cmd_interrupt_received(cli)) break;
|
||||
}
|
||||
|
||||
lfrfid_worker_stop(worker);
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
lfrfid_worker_free(worker);
|
||||
|
||||
if(context.protocol != PROTOCOL_NO) {
|
||||
printf("%s ", protocol_dict_get_name(dict, context.protocol));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(dict, context.protocol);
|
||||
uint8_t* data = malloc(size);
|
||||
protocol_dict_get_data(dict, context.protocol, data, size);
|
||||
for(size_t i = 0; i < size; i++) {
|
||||
printf("%02X", data[i]);
|
||||
}
|
||||
printf("\r\n");
|
||||
free(data);
|
||||
|
||||
string_t info;
|
||||
string_init(info);
|
||||
protocol_dict_render_data(dict, info, context.protocol);
|
||||
if(!string_empty_p(info)) {
|
||||
printf("%s\r\n", string_get_cstr(info));
|
||||
}
|
||||
string_clear(info);
|
||||
}
|
||||
|
||||
printf("Reading stopped\r\n");
|
||||
protocol_dict_free(dict);
|
||||
|
||||
furi_event_flag_free(context.event);
|
||||
}
|
||||
|
||||
static bool lfrfid_cli_parse_args(string_t args, ProtocolDict* dict, ProtocolId* protocol) {
|
||||
bool result = false;
|
||||
string_t protocol_name, data_text;
|
||||
string_init(protocol_name);
|
||||
string_init(data_text);
|
||||
size_t data_size = protocol_dict_get_max_data_size(dict);
|
||||
uint8_t* data = malloc(data_size);
|
||||
|
||||
do {
|
||||
// load args
|
||||
if(!args_read_string_and_trim(args, protocol_name) ||
|
||||
!args_read_string_and_trim(args, data_text)) {
|
||||
lfrfid_cli_print_usage();
|
||||
break;
|
||||
}
|
||||
|
||||
// check protocol arg
|
||||
*protocol = protocol_dict_get_protocol_by_name(dict, string_get_cstr(protocol_name));
|
||||
if(*protocol == PROTOCOL_NO) {
|
||||
printf(
|
||||
"Unknown protocol: %s\r\n"
|
||||
"Available protocols:\r\n",
|
||||
string_get_cstr(protocol_name));
|
||||
|
||||
for(ProtocolId i = 0; i < LFRFIDProtocolMax; i++) {
|
||||
printf(
|
||||
"\t%s, %d bytes long\r\n",
|
||||
protocol_dict_get_name(dict, i),
|
||||
protocol_dict_get_data_size(dict, i));
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
data_size = protocol_dict_get_data_size(dict, *protocol);
|
||||
|
||||
// check data arg
|
||||
if(!args_read_hex_bytes(data_text, data, data_size)) {
|
||||
printf(
|
||||
"%s data needs to be %d bytes long\r\n",
|
||||
protocol_dict_get_name(dict, *protocol),
|
||||
data_size);
|
||||
break;
|
||||
}
|
||||
|
||||
// load data to protocol
|
||||
protocol_dict_set_data(dict, *protocol, data, data_size);
|
||||
|
||||
result = true;
|
||||
} while(false);
|
||||
|
||||
free(data);
|
||||
string_clear(protocol_name);
|
||||
string_clear(data_text);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void lfrfid_cli_write_callback(LFRFIDWorkerWriteResult result, void* ctx) {
|
||||
furi_assert(ctx);
|
||||
FuriEventFlag* events = ctx;
|
||||
furi_event_flag_set(events, 1 << result);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_write(Cli* cli, string_t args) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
ProtocolId protocol;
|
||||
|
||||
if(!lfrfid_cli_parse_args(args, dict, &protocol)) {
|
||||
protocol_dict_free(dict);
|
||||
return;
|
||||
}
|
||||
|
||||
LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
|
||||
FuriEventFlag* event = furi_event_flag_alloc();
|
||||
|
||||
lfrfid_worker_start_thread(worker);
|
||||
lfrfid_worker_write_start(worker, protocol, lfrfid_cli_write_callback, event);
|
||||
|
||||
printf("Writing RFID...\r\nPress Ctrl+C to abort\r\n");
|
||||
const uint32_t available_flags = (1 << LFRFIDWorkerWriteOK) |
|
||||
(1 << LFRFIDWorkerWriteProtocolCannotBeWritten) |
|
||||
(1 << LFRFIDWorkerWriteFobCannotBeWritten);
|
||||
|
||||
while(!cli_cmd_interrupt_received(cli)) {
|
||||
uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100);
|
||||
if(flags != FuriFlagErrorTimeout) {
|
||||
if(FURI_BIT(flags, LFRFIDWorkerWriteOK)) {
|
||||
printf("Written!\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(FURI_BIT(flags, LFRFIDWorkerWriteProtocolCannotBeWritten)) {
|
||||
printf("This protocol cannot be written.\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(FURI_BIT(flags, LFRFIDWorkerWriteFobCannotBeWritten)) {
|
||||
printf("Seems this fob cannot be written.\r\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
printf("Writing stopped\r\n");
|
||||
|
||||
lfrfid_worker_stop(worker);
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
lfrfid_worker_free(worker);
|
||||
protocol_dict_free(dict);
|
||||
furi_event_flag_free(event);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_emulate(Cli* cli, string_t args) {
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
ProtocolId protocol;
|
||||
|
||||
if(!lfrfid_cli_parse_args(args, dict, &protocol)) {
|
||||
protocol_dict_free(dict);
|
||||
return;
|
||||
}
|
||||
|
||||
LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
|
||||
|
||||
lfrfid_worker_start_thread(worker);
|
||||
lfrfid_worker_emulate_start(worker, protocol);
|
||||
|
||||
printf("Emulating RFID...\r\nPress Ctrl+C to abort\r\n");
|
||||
while(!cli_cmd_interrupt_received(cli)) {
|
||||
furi_delay_ms(100);
|
||||
}
|
||||
printf("Emulation stopped\r\n");
|
||||
|
||||
lfrfid_worker_stop(worker);
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
lfrfid_worker_free(worker);
|
||||
protocol_dict_free(dict);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_raw_analyze(Cli* cli, string_t args) {
|
||||
UNUSED(cli);
|
||||
string_t filepath, info_string;
|
||||
string_init(filepath);
|
||||
string_init(info_string);
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
LFRFIDRawFile* file = lfrfid_raw_file_alloc(storage);
|
||||
|
||||
do {
|
||||
float frequency = 0;
|
||||
float duty_cycle = 0;
|
||||
|
||||
if(!args_read_probably_quoted_string_and_trim(args, filepath)) {
|
||||
lfrfid_cli_print_usage();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!lfrfid_raw_file_open_read(file, string_get_cstr(filepath))) {
|
||||
printf("Failed to open file\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(!lfrfid_raw_file_read_header(file, &frequency, &duty_cycle)) {
|
||||
printf("Invalid header\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
bool file_end = false;
|
||||
uint32_t total_warns = 0;
|
||||
uint32_t total_duration = 0;
|
||||
uint32_t total_pulse = 0;
|
||||
ProtocolId total_protocol = PROTOCOL_NO;
|
||||
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
protocol_dict_decoders_start(dict);
|
||||
|
||||
while(!file_end) {
|
||||
uint32_t pulse = 0;
|
||||
uint32_t duration = 0;
|
||||
if(lfrfid_raw_file_read_pair(file, &duration, &pulse, &file_end)) {
|
||||
bool warn = false;
|
||||
|
||||
if(pulse > duration || pulse <= 0 || duration <= 0) {
|
||||
total_warns += 1;
|
||||
warn = true;
|
||||
}
|
||||
|
||||
string_printf(info_string, "[%ld %ld]", pulse, duration);
|
||||
printf("%-16s", string_get_cstr(info_string));
|
||||
string_printf(info_string, "[%ld %ld]", pulse, duration - pulse);
|
||||
printf("%-16s", string_get_cstr(info_string));
|
||||
|
||||
if(warn) {
|
||||
printf(" <<----");
|
||||
}
|
||||
|
||||
if(total_protocol == PROTOCOL_NO) {
|
||||
total_protocol = protocol_dict_decoders_feed(dict, true, pulse);
|
||||
if(total_protocol == PROTOCOL_NO) {
|
||||
total_protocol =
|
||||
protocol_dict_decoders_feed(dict, false, duration - pulse);
|
||||
}
|
||||
|
||||
if(total_protocol != PROTOCOL_NO) {
|
||||
printf(" <FOUND %s>", protocol_dict_get_name(dict, total_protocol));
|
||||
}
|
||||
}
|
||||
|
||||
printf("\r\n");
|
||||
|
||||
total_pulse += pulse;
|
||||
total_duration += duration;
|
||||
|
||||
if(total_protocol != PROTOCOL_NO) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
printf("Failed to read pair\r\n");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
printf(" Frequency: %f\r\n", (double)frequency);
|
||||
printf(" Duty Cycle: %f\r\n", (double)duty_cycle);
|
||||
printf(" Warns: %ld\r\n", total_warns);
|
||||
printf(" Pulse sum: %ld\r\n", total_pulse);
|
||||
printf("Duration sum: %ld\r\n", total_duration);
|
||||
printf(" Average: %f\r\n", (double)((float)total_pulse / (float)total_duration));
|
||||
printf(" Protocol: ");
|
||||
|
||||
if(total_protocol != PROTOCOL_NO) {
|
||||
size_t data_size = protocol_dict_get_data_size(dict, total_protocol);
|
||||
uint8_t* data = malloc(data_size);
|
||||
protocol_dict_get_data(dict, total_protocol, data, data_size);
|
||||
|
||||
printf("%s [", protocol_dict_get_name(dict, total_protocol));
|
||||
for(size_t i = 0; i < data_size; i++) {
|
||||
printf("%02X", data[i]);
|
||||
if(i < data_size - 1) {
|
||||
printf(" ");
|
||||
}
|
||||
}
|
||||
printf("]\r\n");
|
||||
|
||||
protocol_dict_render_data(dict, info_string, total_protocol);
|
||||
printf("%s\r\n", string_get_cstr(info_string));
|
||||
|
||||
free(data);
|
||||
} else {
|
||||
printf("not found\r\n");
|
||||
}
|
||||
|
||||
protocol_dict_free(dict);
|
||||
} while(false);
|
||||
|
||||
string_clear(filepath);
|
||||
string_clear(info_string);
|
||||
lfrfid_raw_file_free(file);
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_raw_read_callback(LFRFIDWorkerReadRawResult result, void* context) {
|
||||
furi_assert(context);
|
||||
FuriEventFlag* event = context;
|
||||
furi_event_flag_set(event, 1 << result);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_raw_read(Cli* cli, string_t args) {
|
||||
UNUSED(cli);
|
||||
|
||||
string_t filepath, type_string;
|
||||
string_init(filepath);
|
||||
string_init(type_string);
|
||||
LFRFIDWorkerReadType type = LFRFIDWorkerReadTypeAuto;
|
||||
|
||||
do {
|
||||
if(args_read_string_and_trim(args, type_string)) {
|
||||
if(string_cmp_str(type_string, "normal") == 0 ||
|
||||
string_cmp_str(type_string, "ask") == 0) {
|
||||
// ask
|
||||
type = LFRFIDWorkerReadTypeASKOnly;
|
||||
} else if(
|
||||
string_cmp_str(type_string, "indala") == 0 ||
|
||||
string_cmp_str(type_string, "psk") == 0) {
|
||||
// psk
|
||||
type = LFRFIDWorkerReadTypePSKOnly;
|
||||
} else {
|
||||
lfrfid_cli_print_usage();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if(!args_read_probably_quoted_string_and_trim(args, filepath)) {
|
||||
lfrfid_cli_print_usage();
|
||||
break;
|
||||
}
|
||||
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
|
||||
FuriEventFlag* event = furi_event_flag_alloc();
|
||||
|
||||
lfrfid_worker_start_thread(worker);
|
||||
|
||||
bool overrun = false;
|
||||
|
||||
const uint32_t available_flags = (1 << LFRFIDWorkerReadRawFileError) |
|
||||
(1 << LFRFIDWorkerReadRawOverrun);
|
||||
|
||||
lfrfid_worker_read_raw_start(
|
||||
worker, string_get_cstr(filepath), type, lfrfid_cli_raw_read_callback, event);
|
||||
while(true) {
|
||||
uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100);
|
||||
|
||||
if(flags != FuriFlagErrorTimeout) {
|
||||
if(FURI_BIT(flags, LFRFIDWorkerReadRawFileError)) {
|
||||
printf("File is not RFID raw file\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(FURI_BIT(flags, LFRFIDWorkerReadRawOverrun)) {
|
||||
if(!overrun) {
|
||||
printf("Overrun\r\n");
|
||||
overrun = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cli_cmd_interrupt_received(cli)) break;
|
||||
}
|
||||
|
||||
if(overrun) {
|
||||
printf("An overrun occurred during read\r\n");
|
||||
}
|
||||
|
||||
lfrfid_worker_stop(worker);
|
||||
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
lfrfid_worker_free(worker);
|
||||
protocol_dict_free(dict);
|
||||
|
||||
furi_event_flag_free(event);
|
||||
|
||||
} while(false);
|
||||
|
||||
string_clear(filepath);
|
||||
string_clear(type_string);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_raw_emulate_callback(LFRFIDWorkerEmulateRawResult result, void* context) {
|
||||
furi_assert(context);
|
||||
FuriEventFlag* event = context;
|
||||
furi_event_flag_set(event, 1 << result);
|
||||
}
|
||||
|
||||
static void lfrfid_cli_raw_emulate(Cli* cli, string_t args) {
|
||||
UNUSED(cli);
|
||||
|
||||
string_t filepath;
|
||||
string_init(filepath);
|
||||
Storage* storage = furi_record_open(RECORD_STORAGE);
|
||||
|
||||
do {
|
||||
if(!args_read_probably_quoted_string_and_trim(args, filepath)) {
|
||||
lfrfid_cli_print_usage();
|
||||
break;
|
||||
}
|
||||
|
||||
if(!storage_file_exists(storage, string_get_cstr(filepath))) {
|
||||
printf("File not found: \"%s\"\r\n", string_get_cstr(filepath));
|
||||
break;
|
||||
}
|
||||
|
||||
ProtocolDict* dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
|
||||
LFRFIDWorker* worker = lfrfid_worker_alloc(dict);
|
||||
FuriEventFlag* event = furi_event_flag_alloc();
|
||||
|
||||
lfrfid_worker_start_thread(worker);
|
||||
|
||||
bool overrun = false;
|
||||
|
||||
const uint32_t available_flags = (1 << LFRFIDWorkerEmulateRawFileError) |
|
||||
(1 << LFRFIDWorkerEmulateRawOverrun);
|
||||
|
||||
lfrfid_worker_emulate_raw_start(
|
||||
worker, string_get_cstr(filepath), lfrfid_cli_raw_emulate_callback, event);
|
||||
while(true) {
|
||||
uint32_t flags = furi_event_flag_wait(event, available_flags, FuriFlagWaitAny, 100);
|
||||
|
||||
if(flags != FuriFlagErrorTimeout) {
|
||||
if(FURI_BIT(flags, LFRFIDWorkerEmulateRawFileError)) {
|
||||
printf("File is not RFID raw file\r\n");
|
||||
break;
|
||||
}
|
||||
|
||||
if(FURI_BIT(flags, LFRFIDWorkerEmulateRawOverrun)) {
|
||||
if(!overrun) {
|
||||
printf("Overrun\r\n");
|
||||
overrun = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(cli_cmd_interrupt_received(cli)) break;
|
||||
}
|
||||
|
||||
if(overrun) {
|
||||
printf("An overrun occurred during emulation\r\n");
|
||||
}
|
||||
|
||||
lfrfid_worker_stop(worker);
|
||||
|
||||
lfrfid_worker_stop_thread(worker);
|
||||
lfrfid_worker_free(worker);
|
||||
protocol_dict_free(dict);
|
||||
|
||||
furi_event_flag_free(event);
|
||||
|
||||
} while(false);
|
||||
|
||||
furi_record_close(RECORD_STORAGE);
|
||||
string_clear(filepath);
|
||||
}
|
||||
|
||||
static void lfrfid_cli(Cli* cli, string_t args, void* context) {
|
||||
UNUSED(context);
|
||||
string_t cmd;
|
||||
string_init(cmd);
|
||||
|
||||
if(!args_read_string_and_trim(args, cmd)) {
|
||||
string_clear(cmd);
|
||||
lfrfid_cli_print_usage();
|
||||
return;
|
||||
}
|
||||
|
||||
if(string_cmp_str(cmd, "read") == 0) {
|
||||
lfrfid_cli_read(cli, args);
|
||||
} else if(string_cmp_str(cmd, "write") == 0) {
|
||||
lfrfid_cli_write(cli, args);
|
||||
} else if(string_cmp_str(cmd, "emulate") == 0) {
|
||||
lfrfid_cli_emulate(cli, args);
|
||||
} else if(string_cmp_str(cmd, "raw_read") == 0) {
|
||||
lfrfid_cli_raw_read(cli, args);
|
||||
} else if(string_cmp_str(cmd, "raw_emulate") == 0) {
|
||||
lfrfid_cli_raw_emulate(cli, args);
|
||||
} else if(string_cmp_str(cmd, "raw_analyze") == 0) {
|
||||
lfrfid_cli_raw_analyze(cli, args);
|
||||
} else {
|
||||
lfrfid_cli_print_usage();
|
||||
}
|
||||
|
||||
string_clear(cmd);
|
||||
}
|
145
applications/main/lfrfid/lfrfid_i.h
Normal file
145
applications/main/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);
|
30
applications/main/lfrfid/scenes/lfrfid_scene.c
Normal file
30
applications/main/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/main/lfrfid/scenes/lfrfid_scene.h
Normal file
29
applications/main/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/main/lfrfid/scenes/lfrfid_scene_config.h
Normal file
24
applications/main/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)
|
@@ -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);
|
||||
}
|
@@ -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/main/lfrfid/scenes/lfrfid_scene_emulate.c
Normal file
44
applications/main/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/main/lfrfid/scenes/lfrfid_scene_exit_confirm.c
Normal file
39
applications/main/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/main/lfrfid/scenes/lfrfid_scene_extra_actions.c
Normal file
79
applications/main/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/main/lfrfid/scenes/lfrfid_scene_raw_info.c
Normal file
64
applications/main/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/main/lfrfid/scenes/lfrfid_scene_raw_name.c
Normal file
58
applications/main/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/main/lfrfid/scenes/lfrfid_scene_raw_read.c
Normal file
126
applications/main/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/main/lfrfid/scenes/lfrfid_scene_raw_success.c
Normal file
39
applications/main/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/main/lfrfid/scenes/lfrfid_scene_read.c
Normal file
109
applications/main/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/main/lfrfid/scenes/lfrfid_scene_read_key_menu.c
Normal file
58
applications/main/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/main/lfrfid/scenes/lfrfid_scene_read_success.c
Normal file
79
applications/main/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/main/lfrfid/scenes/lfrfid_scene_retry_confirm.c
Normal file
39
applications/main/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/main/lfrfid/scenes/lfrfid_scene_rpc.c
Normal file
67
applications/main/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/main/lfrfid/scenes/lfrfid_scene_save_data.c
Normal file
51
applications/main/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/main/lfrfid/scenes/lfrfid_scene_save_name.c
Normal file
76
applications/main/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/main/lfrfid/scenes/lfrfid_scene_save_success.c
Normal file
43
applications/main/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/main/lfrfid/scenes/lfrfid_scene_save_type.c
Normal file
86
applications/main/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/main/lfrfid/scenes/lfrfid_scene_saved_info.c
Normal file
51
applications/main/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);
|
||||
}
|
@@ -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/main/lfrfid/scenes/lfrfid_scene_select_key.c
Normal file
22
applications/main/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/main/lfrfid/scenes/lfrfid_scene_start.c
Normal file
72
applications/main/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/main/lfrfid/scenes/lfrfid_scene_write.c
Normal file
96
applications/main/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/main/lfrfid/scenes/lfrfid_scene_write_success.c
Normal file
38
applications/main/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);
|
||||
}
|
117
applications/main/lfrfid/views/lfrfid_view_read.c
Normal file
117
applications/main/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/main/lfrfid/views/lfrfid_view_read.h
Normal file
19
applications/main/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);
|
Reference in New Issue
Block a user