New LF-RFID app (#534)

* Hal lfrfid: add read timer pulse and period config fns
* New debug application for lfrfid subsystem
* New lfrfid: app, fix naming
* App lfrfid: assets
* Container view module
* App ibutton: remove unused header
* App lfrfid scenes
* App notification, add yield to blocking operations, add speaker volume control
* App lfrfid: reading key scene
* Assets: placeholder icon
* App lfrfid: reworked container view module
* App lfrfid: new scenes
* App lfrfid: write scene
* App lfrfid: write hid
* App lfrfid: emulate scene
* App lfrfid: save name scene
* App lfrfid: add missing file
This commit is contained in:
SG 2021-06-29 00:42:30 +10:00 committed by GitHub
parent 5d746234e9
commit 22e1ecb642
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
141 changed files with 2504 additions and 1666 deletions

View File

@ -16,7 +16,6 @@ int32_t gui_task(void* p);
int32_t backlight_control(void* p);
int32_t irda(void* p);
int32_t app_loader(void* p);
int32_t app_lfrfid(void* p);
int32_t nfc_task(void* p);
int32_t dolphin_task(void* p);
int32_t power_task(void* p);
@ -40,6 +39,8 @@ int32_t internal_storage_task(void* p);
int32_t app_archive(void* p);
int32_t notification_app(void* p);
int32_t scened_app(void* p);
int32_t lfrfid_app(void* p);
int32_t lfrfid_debug_app(void* p);
// On system start hooks declaration
void irda_cli_init();
@ -104,7 +105,8 @@ const FlipperApplication FLIPPER_SERVICES[] = {
#endif
#ifdef SRV_LF_RFID
{.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_Plugins_14},
// TODO: fix stack size when sd api will be in separate thread
{.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_Plugins_14},
#endif
#ifdef SRV_IRDA
@ -186,7 +188,8 @@ const FlipperApplication FLIPPER_APPS[] = {
#endif
#ifdef APP_LF_RFID
{.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_125khz_14},
// TODO: fix stack size when sd api will be in separate thread
{.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_125khz_14},
#endif
#ifdef APP_IRDA
@ -302,6 +305,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = {
#ifdef APP_SCENED
{.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = A_Plugins_14},
#endif
#ifdef APP_LF_RFID
{.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = A_125khz_14},
#endif
};
const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication);

View File

@ -39,8 +39,7 @@ static void dialog_ex_view_draw_callback(Canvas* canvas, void* _model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
// TODO other criteria for the draw
if(model->icon.x >= 0 && model->icon.y >= 0) {
if(model->icon.name != I_Empty_1x1) {
canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name);
}
@ -135,10 +134,9 @@ DialogEx* dialog_ex_alloc() {
model->text.horizontal = AlignLeft;
model->text.vertical = AlignBottom;
// TODO other criteria for the draw
model->icon.x = -1;
model->icon.y = -1;
model->icon.name = I_ButtonCenter_7x7;
model->icon.x = 0;
model->icon.y = 0;
model->icon.name = I_Empty_1x1;
model->left_text = NULL;
model->center_text = NULL;
@ -208,7 +206,7 @@ void dialog_ex_set_text(
});
}
void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name) {
void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name) {
furi_assert(dialog_ex);
with_view_model(
dialog_ex->view, (DialogExModel * model) {

View File

@ -84,7 +84,7 @@ void dialog_ex_set_text(
* @param x, y - icon position
* @param name - icon to be shown
*/
void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name);
void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name);
/* Set left button text
* If text is null, left button will not be rendered and processed

View File

@ -21,8 +21,8 @@ typedef struct {
} TextElement;
typedef struct {
int8_t x;
int8_t y;
uint8_t x;
uint8_t y;
IconName name;
} IconElement;
@ -39,8 +39,7 @@ static void popup_view_draw_callback(Canvas* canvas, void* _model) {
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
// TODO other criteria for the draw
if(model->icon.x >= 0 && model->icon.y >= 0) {
if(model->icon.name != I_Empty_1x1) {
canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name);
}
@ -137,10 +136,9 @@ Popup* popup_alloc() {
model->text.horizontal = AlignLeft;
model->text.vertical = AlignBottom;
// TODO other criteria for the draw
model->icon.x = -1;
model->icon.y = -1;
model->icon.name = I_ButtonCenter_7x7;
model->icon.x = 0;
model->icon.y = 0;
model->icon.name = I_Empty_1x1;
return true;
});
return popup;
@ -206,7 +204,7 @@ void popup_set_text(
});
}
void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name) {
void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name) {
furi_assert(popup);
with_view_model(
popup->view, (PopupModel * model) {

View File

@ -77,7 +77,7 @@ void popup_set_text(
* @param x, y - icon position
* @param name - icon to be shown
*/
void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name);
void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name);
/* Set popup timeout
* @param popup - Popup instance

View File

@ -27,7 +27,6 @@
#include <sd-card-api.h>
#include <filesystem-api.h>
#include "../cli/cli.h"
#include "one_wire_master.h"
#include "maxim_crc.h"

View File

@ -36,7 +36,7 @@ void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) {
Popup* popup = app->get_view_manager()->get_popup();
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
popup_disable_timeout(popup);
popup_set_context(popup, NULL);

View File

@ -89,5 +89,5 @@ void iButtonSceneEmulate::on_exit(iButtonApp* app) {
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
}

View File

@ -74,7 +74,7 @@ void iButtonSceneReadSuccess::on_exit(iButtonApp* app) {
dialog_ex_set_right_button_text(dialog_ex, NULL);
dialog_ex_set_result_callback(dialog_ex, NULL);
dialog_ex_set_context(dialog_ex, NULL);
dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7);
dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1);
app->notify_green_off();
}

View File

@ -49,5 +49,5 @@ void iButtonSceneRead::on_exit(iButtonApp* app) {
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
}

View File

@ -39,7 +39,7 @@ void iButtonSceneSaveSuccess::on_exit(iButtonApp* app) {
Popup* popup = app->get_view_manager()->get_popup();
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
popup_disable_timeout(popup);
popup_set_context(popup, NULL);

View File

@ -40,7 +40,7 @@ void iButtonSceneWriteSuccess::on_exit(iButtonApp* app) {
Popup* popup = app->get_view_manager()->get_popup();
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
popup_disable_timeout(popup);
popup_set_context(popup, NULL);

View File

@ -92,7 +92,7 @@ void iButtonSceneWrite::on_exit(iButtonApp* app) {
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
popup_set_icon(popup, -1, -1, I_DolphinWait_61x59);
popup_set_icon(popup, 0, 0, I_Empty_1x1);
app->get_key_worker()->stop_write();
}

View File

@ -41,7 +41,7 @@ void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) {
}
dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 32, AlignCenter, AlignCenter);
dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7);
dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1);
dialog_ex_set_left_button_text(dialog_ex, "Back");
dialog_ex_set_right_button_text(dialog_ex, "Delete");
dialog_ex_set_result_callback(dialog_ex, dialog_result_callback);

View File

@ -1,140 +0,0 @@
#include "lf-rfid-app.h"
#include <furi.h>
#include <api-hal.h>
#include <stdarg.h>
void LfrfidApp::run(void) {
LfrfidEvent event;
bool consumed;
bool exit = false;
scenes[current_scene]->on_enter(this);
while(!exit) {
view.receive_event(&event);
consumed = scenes[current_scene]->on_event(this, &event);
if(!consumed) {
if(event.type == LfrfidEvent::Type::Back) {
exit = switch_to_previous_scene();
}
}
};
scenes[current_scene]->on_exit(this);
}
LfrfidApp::LfrfidApp() {
api_hal_power_insomnia_enter();
notification = static_cast<NotificationApp*>(furi_record_open("notification"));
}
LfrfidApp::~LfrfidApp() {
for(std::map<Scene, LfrfidScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) {
delete it->second;
scenes.erase(it);
}
furi_record_close("notification");
api_hal_power_insomnia_exit();
}
LfrfidAppViewManager* LfrfidApp::get_view_manager() {
return &view;
}
void LfrfidApp::switch_to_next_scene(Scene next_scene) {
previous_scenes_list.push_front(current_scene);
if(next_scene != Scene::Exit) {
scenes[current_scene]->on_exit(this);
current_scene = next_scene;
scenes[current_scene]->on_enter(this);
}
}
void LfrfidApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) {
Scene previous_scene = Scene::Start;
bool scene_found = false;
while(!scene_found) {
previous_scene = get_previous_scene();
for(Scene element : scenes_list) {
if(previous_scene == element || previous_scene == Scene::Start) {
scene_found = true;
break;
}
}
}
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
}
bool LfrfidApp::switch_to_previous_scene(uint8_t count) {
Scene previous_scene = Scene::Start;
for(uint8_t i = 0; i < count; i++) {
previous_scene = get_previous_scene();
if(previous_scene == Scene::Exit) break;
}
if(previous_scene == Scene::Exit) {
return true;
} else {
scenes[current_scene]->on_exit(this);
current_scene = previous_scene;
scenes[current_scene]->on_enter(this);
return false;
}
}
LfrfidApp::Scene LfrfidApp::get_previous_scene() {
Scene scene = previous_scenes_list.front();
previous_scenes_list.pop_front();
return scene;
}
/***************************** NOTIFY *******************************/
void LfrfidApp::notify_green_blink() {
notification_message(notification, &sequence_blink_green_10);
}
void LfrfidApp::notify_success() {
notification_message(notification, &sequence_success);
}
/*************************** TEXT STORE *****************************/
char* LfrfidApp::get_text_store() {
return text_store;
}
uint8_t LfrfidApp::get_text_store_size() {
return text_store_size;
}
void LfrfidApp::set_text_store(const char* text...) {
va_list args;
va_start(args, text);
vsnprintf(text_store, text_store_size, text, args);
va_end(args);
}
RfidReader* LfrfidApp::get_reader() {
return &reader;
}
RfidTimerEmulator* LfrfidApp::get_emulator() {
return &emulator;
}
RfidWriter* LfrfidApp::get_writer() {
return &writer;
}

View File

@ -1,79 +0,0 @@
#pragma once
#include <map>
#include <list>
#include "lf-rfid-view-manager.h"
#include "scene/lf-rfid-scene-start.h"
#include "scene/lf-rfid-scene-emulate-indala.h"
#include "scene/lf-rfid-scene-emulate-hid.h"
#include "scene/lf-rfid-scene-emulate-emmarine.h"
#include "scene/lf-rfid-scene-read-normal.h"
#include "scene/lf-rfid-scene-read-indala.h"
#include "scene/lf-rfid-scene-tune.h"
#include "scene/lf-rfid-scene-write.h"
#include "helpers/rfid-reader.h"
#include "helpers/rfid-timer-emulator.h"
#include <notification/notification-messages.h>
class LfrfidApp {
public:
void run(void);
LfrfidApp();
~LfrfidApp();
enum class Scene : uint8_t {
Exit,
Start,
ReadNormal,
ReadIndala,
EmulateIndala,
EmulateHID,
EmulateEM,
Tune,
Write,
};
LfrfidAppViewManager* get_view_manager();
void switch_to_next_scene(Scene index);
void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list);
bool switch_to_previous_scene(uint8_t count = 1);
Scene get_previous_scene();
void notify_green_blink();
void notify_success();
char* get_text_store();
uint8_t get_text_store_size();
void set_text_store(const char* text...);
RfidReader* get_reader();
RfidTimerEmulator* get_emulator();
RfidWriter* get_writer();
private:
std::list<Scene> previous_scenes_list = {Scene::Exit};
Scene current_scene = Scene::Start;
LfrfidAppViewManager view;
std::map<Scene, LfrfidScene*> scenes = {
{Scene::Start, new LfrfidSceneStart()},
{Scene::ReadNormal, new LfrfidSceneReadNormal()},
{Scene::ReadIndala, new LfrfidSceneReadIndala()},
{Scene::EmulateIndala, new LfrfidSceneEmulateIndala()},
{Scene::EmulateHID, new LfrfidSceneEmulateHID()},
{Scene::EmulateEM, new LfrfidSceneEmulateEMMarine()},
{Scene::Tune, new LfrfidSceneTune()},
{Scene::Write, new LfrfidSceneWrite()},
};
static const uint8_t text_store_size = 128;
char text_store[text_store_size + 1];
NotificationApp* notification;
RfidReader reader;
RfidTimerEmulator emulator;
RfidWriter writer;
};

View File

@ -1,21 +0,0 @@
#pragma once
#include <stdint.h>
class LfrfidEvent {
public:
// events enum
enum class Type : uint8_t {
Tick,
Back,
MenuSelected,
NextScene,
};
// payload
union {
uint32_t menu_index;
} payload;
// event type
Type type;
};

View File

@ -1,90 +0,0 @@
#include "lf-rfid-view-manager.h"
#include "lf-rfid-event.h"
#include <callback-connector.h>
LfrfidAppViewManager::LfrfidAppViewManager() {
event_queue = osMessageQueueNew(10, sizeof(LfrfidEvent), NULL);
view_dispatcher = view_dispatcher_alloc();
auto callback = cbc::obtain_connector(this, &LfrfidAppViewManager::previous_view_callback);
// allocate views
submenu = submenu_alloc();
add_view(ViewType::Submenu, submenu_get_view(submenu));
popup = popup_alloc();
add_view(ViewType::Popup, popup_get_view(popup));
tune = new LfRfidViewTune();
add_view(ViewType::Tune, tune->get_view());
gui = static_cast<Gui*>(furi_record_open("gui"));
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
// set previous view callback for all views
view_set_previous_callback(submenu_get_view(submenu), callback);
view_set_previous_callback(popup_get_view(popup), callback);
view_set_previous_callback(tune->get_view(), callback);
}
LfrfidAppViewManager::~LfrfidAppViewManager() {
// remove views
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Submenu));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Popup));
view_dispatcher_remove_view(
view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Tune));
// free view modules
submenu_free(submenu);
popup_free(popup);
delete tune;
// free dispatcher
view_dispatcher_free(view_dispatcher);
// free event queue
osMessageQueueDelete(event_queue);
}
void LfrfidAppViewManager::switch_to(ViewType type) {
view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
}
Submenu* LfrfidAppViewManager::get_submenu() {
return submenu;
}
Popup* LfrfidAppViewManager::get_popup() {
return popup;
}
LfRfidViewTune* LfrfidAppViewManager::get_tune() {
return tune;
}
void LfrfidAppViewManager::receive_event(LfrfidEvent* event) {
if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
event->type = LfrfidEvent::Type::Tick;
}
}
void LfrfidAppViewManager::send_event(LfrfidEvent* event) {
osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0);
furi_check(result == osOK);
}
uint32_t LfrfidAppViewManager::previous_view_callback(void* context) {
if(event_queue != NULL) {
LfrfidEvent event;
event.type = LfrfidEvent::Type::Back;
send_event(&event);
}
return VIEW_IGNORE;
}
void LfrfidAppViewManager::add_view(ViewType view_type, View* view) {
view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view);
}

View File

@ -1,42 +0,0 @@
#pragma once
#include <furi.h>
#include <gui/view_dispatcher.h>
#include <gui/modules/submenu.h>
#include <gui/modules/popup.h>
#include "lf-rfid-event.h"
#include "view/lf-rfid-view-tune.h"
class LfrfidAppViewManager {
public:
enum class ViewType : uint8_t {
Submenu,
Popup,
Tune,
};
osMessageQueueId_t event_queue;
LfrfidAppViewManager();
~LfrfidAppViewManager();
void switch_to(ViewType type);
void receive_event(LfrfidEvent* event);
void send_event(LfrfidEvent* event);
Submenu* get_submenu();
Popup* get_popup();
LfRfidViewTune* get_tune();
private:
ViewDispatcher* view_dispatcher;
Gui* gui;
uint32_t previous_view_callback(void* context);
void add_view(ViewType view_type, View* view);
// view elements
Submenu* submenu;
Popup* popup;
LfRfidViewTune* tune;
};

View File

@ -1,10 +0,0 @@
#include "lf-rfid-app.h"
// app enter function
extern "C" int32_t app_lfrfid(void* p) {
LfrfidApp* app = new LfrfidApp();
app->run();
delete app;
return 255;
}

View File

@ -1,34 +0,0 @@
#include "lf-rfid-scene-emulate-emmarine.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneEmulateEMMarine::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("EM emulation");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
app->get_emulator()->start(LfrfidKeyType::KeyEM4100, data, 5);
}
bool LfrfidSceneEmulateEMMarine::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
return consumed;
}
void LfrfidSceneEmulateEMMarine::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
app->get_emulator()->stop();
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
class LfrfidSceneEmulateEMMarine : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
const uint8_t data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2};
};

View File

@ -1,34 +0,0 @@
#include "lf-rfid-scene-emulate-hid.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneEmulateHID::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("HID H10301 emulation");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
app->get_emulator()->start(LfrfidKeyType::KeyH10301, data, 3);
}
bool LfrfidSceneEmulateHID::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
return consumed;
}
void LfrfidSceneEmulateHID::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
app->get_emulator()->stop();
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
class LfrfidSceneEmulateHID : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
const uint8_t data[3] = {0xED, 0x87, 0x70};
};

View File

@ -1,34 +0,0 @@
#include "lf-rfid-scene-emulate-indala.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneEmulateIndala::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("Indala 40134 emulation");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
app->get_emulator()->start(LfrfidKeyType::KeyI40134, data, 3);
}
bool LfrfidSceneEmulateIndala::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
return consumed;
}
void LfrfidSceneEmulateIndala::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
app->get_emulator()->stop();
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
class LfrfidSceneEmulateIndala : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
const uint8_t data[3] = {0x1F, 0x2E, 0x3D};
};

View File

@ -1,14 +0,0 @@
#pragma once
#include "../lf-rfid-event.h"
class LfrfidApp;
class LfrfidScene {
public:
virtual void on_enter(LfrfidApp* app) = 0;
virtual bool on_event(LfrfidApp* app, LfrfidEvent* event) = 0;
virtual void on_exit(LfrfidApp* app) = 0;
virtual ~LfrfidScene(){};
private:
};

View File

@ -1,34 +0,0 @@
#include "lf-rfid-scene-read-indala.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneReadIndala::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID read Indala", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("[decoder not implemented]");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
app->get_reader()->start(RfidReader::Type::Indala);
}
bool LfrfidSceneReadIndala::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
return consumed;
}
void LfrfidSceneReadIndala::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
app->get_reader()->stop();
}

View File

@ -1,15 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
class LfrfidSceneReadIndala : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
uint32_t success_reads = 0;
static const uint8_t data_size = LFRFID_KEY_SIZE;
uint8_t last_data[data_size] = {0};
};

View File

@ -1,89 +0,0 @@
#include "lf-rfid-scene-read-normal.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneReadNormal::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID read EM & HID", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("waiting...");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
app->get_reader()->start(RfidReader::Type::Normal);
}
bool LfrfidSceneReadNormal::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
if(event->type == LfrfidEvent::Type::Tick) {
uint8_t data[data_size];
LfrfidKeyType type;
if(app->get_reader()->read(&type, data, data_size)) {
if(memcmp(last_data, data, data_size) == 0) {
success_reads++;
app->notify_green_blink();
} else {
success_reads = 1;
memcpy(last_data, data, data_size);
app->notify_success();
}
switch(type) {
case LfrfidKeyType::KeyEM4100:
app->set_text_store(
"[EM] %02X %02X %02X %02X %02X\n"
"count: %u",
data[0],
data[1],
data[2],
data[3],
data[4],
success_reads);
break;
case LfrfidKeyType::KeyH10301:
app->set_text_store(
"[HID26] %02X %02X %02X\n"
"count: %u",
data[0],
data[1],
data[2],
success_reads);
break;
case LfrfidKeyType::KeyI40134:
app->set_text_store(
"[IND] %02X %02X %02X\n"
"count: %u",
data[0],
data[1],
data[2],
success_reads);
break;
}
popup_set_text(
app->get_view_manager()->get_popup(),
app->get_text_store(),
64,
22,
AlignCenter,
AlignTop);
}
}
return consumed;
}
void LfrfidSceneReadNormal::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
app->get_reader()->stop();
}

View File

@ -1,15 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
class LfrfidSceneReadNormal : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
uint32_t success_reads = 0;
static const uint8_t data_size = LFRFID_KEY_SIZE;
uint8_t last_data[data_size] = {0};
};

View File

@ -1,82 +0,0 @@
#include "lf-rfid-scene-start.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include <callback-connector.h>
typedef enum {
SubmenuIndexWrite,
SubmenuIndexReadNormal,
SubmenuIndexReadIndala,
SubmenuIndexEmulateEM,
SubmenuIndexEmulateHID,
SubmenuIndexEmulateIndala,
SubmenuIndexTune
} SubmenuIndex;
void LfrfidSceneStart::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
auto callback = cbc::obtain_connector(this, &LfrfidSceneStart::submenu_callback);
submenu_add_item(submenu, "Write T5577", SubmenuIndexWrite, callback, app);
submenu_add_item(submenu, "Read Normal", SubmenuIndexReadNormal, callback, app);
submenu_add_item(submenu, "Read Indala", SubmenuIndexReadIndala, callback, app);
submenu_add_item(submenu, "Emulate EM", SubmenuIndexEmulateEM, callback, app);
submenu_add_item(submenu, "Emulate HID", SubmenuIndexEmulateHID, callback, app);
submenu_add_item(submenu, "Emulate Indala", SubmenuIndexEmulateIndala, callback, app);
submenu_add_item(submenu, "Tune", SubmenuIndexTune, callback, app);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Submenu);
}
bool LfrfidSceneStart::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
if(event->type == LfrfidEvent::Type::MenuSelected) {
switch(event->payload.menu_index) {
case SubmenuIndexWrite:
app->switch_to_next_scene(LfrfidApp::Scene::Write);
break;
case SubmenuIndexReadNormal:
app->switch_to_next_scene(LfrfidApp::Scene::ReadNormal);
break;
case SubmenuIndexReadIndala:
app->switch_to_next_scene(LfrfidApp::Scene::ReadIndala);
break;
case SubmenuIndexEmulateEM:
app->switch_to_next_scene(LfrfidApp::Scene::EmulateEM);
break;
break;
case SubmenuIndexEmulateHID:
app->switch_to_next_scene(LfrfidApp::Scene::EmulateHID);
break;
case SubmenuIndexEmulateIndala:
app->switch_to_next_scene(LfrfidApp::Scene::EmulateIndala);
break;
case SubmenuIndexTune:
app->switch_to_next_scene(LfrfidApp::Scene::Tune);
break;
}
consumed = true;
}
return consumed;
}
void LfrfidSceneStart::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Submenu* submenu = view_manager->get_submenu();
submenu_clean(submenu);
}
void LfrfidSceneStart::submenu_callback(void* context, uint32_t index) {
LfrfidApp* app = static_cast<LfrfidApp*>(context);
LfrfidEvent event;
event.type = LfrfidEvent::Type::MenuSelected;
event.payload.menu_index = index;
app->get_view_manager()->send_event(&event);
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/rfid-timer-emulator.h"
class LfrfidSceneStart : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
void submenu_callback(void* context, uint32_t index);
};

View File

@ -1,35 +0,0 @@
#include "lf-rfid-scene-tune.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include <callback-connector.h>
void LfrfidSceneTune::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
//LfRfidViewTune* tune = view_manager->get_tune();
view_manager->switch_to(LfrfidAppViewManager::ViewType::Tune);
reader.start(RfidReader::Type::Indala);
}
bool LfrfidSceneTune::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
if(event->type == LfrfidEvent::Type::Tick) {
LfRfidViewTune* tune = app->get_view_manager()->get_tune();
if(tune->is_dirty()) {
LFRFID_TIM.Instance->ARR = tune->get_ARR();
LFRFID_TIM.Instance->CCR1 = tune->get_CCR();
}
}
return consumed;
}
void LfrfidSceneTune::on_exit(LfrfidApp* app) {
//LfRfidViewTune* tune = app->get_view_manager()->get_tune();
reader.stop();
}

View File

@ -1,13 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/rfid-reader.h"
class LfrfidSceneTune : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
RfidReader reader;
};

View File

@ -1,70 +0,0 @@
#include "lf-rfid-scene-write.h"
#include "../lf-rfid-app.h"
#include "../lf-rfid-view-manager.h"
#include "../lf-rfid-event.h"
#include "../helpers/key-info.h"
void LfrfidSceneWrite::on_enter(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom);
app->set_text_store("Writing...");
popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop);
view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup);
timing_index = 0;
}
bool LfrfidSceneWrite::on_event(LfrfidApp* app, LfrfidEvent* event) {
bool consumed = false;
// TODO move read\write logic to key worker
bool readed = false;
uint8_t em_data[5] = {0x1A, 0x2B, 0xC3, 0xD4, 0xE5};
if(timing_index == 0) {
app->get_reader()->stop();
app->get_writer()->start();
app->get_writer()->write_em(em_data);
app->get_writer()->stop();
delay(200);
app->get_reader()->start(RfidReader::Type::Normal);
} else {
uint8_t data[LFRFID_KEY_SIZE];
LfrfidKeyType type;
app->get_reader()->read(&type, data, LFRFID_KEY_SIZE);
if(type == LfrfidKeyType::KeyEM4100) {
if(memcmp(em_data, data, 5) == 0) {
readed = true;
}
}
}
if(readed) {
app->set_text_store("Writed!");
app->notify_green_blink();
} else {
app->set_text_store("Writing [1A 2B C3 D4 E5]");
timing_index++;
if(timing_index == 4) {
timing_index = 0;
}
}
popup_set_text(
app->get_view_manager()->get_popup(), app->get_text_store(), 64, 22, AlignCenter, AlignTop);
return consumed;
}
void LfrfidSceneWrite::on_exit(LfrfidApp* app) {
LfrfidAppViewManager* view_manager = app->get_view_manager();
Popup* popup = view_manager->get_popup();
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
}

View File

@ -1,14 +0,0 @@
#pragma once
#include "lf-rfid-scene-generic.h"
#include "../helpers/key-info.h"
#include "../helpers/rfid-writer.h"
class LfrfidSceneWrite : public LfrfidScene {
public:
void on_enter(LfrfidApp* app) final;
bool on_event(LfrfidApp* app, LfrfidEvent* event) final;
void on_exit(LfrfidApp* app) final;
private:
uint8_t timing_index;
};

View File

@ -0,0 +1,10 @@
#include "lfrfid-debug-app.h"
// app enter function
extern "C" int32_t lfrfid_debug_app(void* p) {
LfRfidDebugApp* app = new LfRfidDebugApp();
app->run();
delete app;
return 0;
}

View File

@ -0,0 +1,16 @@
#include "lfrfid-debug-app.h"
#include "scene/lfrfid-debug-app-scene-start.h"
#include "scene/lfrfid-debug-app-scene-tune.h"
LfRfidDebugApp::LfRfidDebugApp()
: scene_controller{this} {
}
LfRfidDebugApp::~LfRfidDebugApp() {
}
void LfRfidDebugApp::run() {
scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart());
scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune());
scene_controller.process(100);
}

View File

@ -0,0 +1,40 @@
#pragma once
#include <furi.h>
#include <api-hal.h>
#include <generic-scene.hpp>
#include <scene-controller.hpp>
#include <view-controller.hpp>
#include <view-modules/submenu-vm.h>
#include "view-modules/lfrfid-view-tune-vm.h"
class LfRfidDebugApp {
public:
enum class EventType : uint8_t {
GENERIC_EVENT_ENUM_VALUES,
MenuSelected,
};
enum class SceneType : uint8_t {
GENERIC_SCENE_ENUM_VALUES,
TuneScene,
};
class Event {
public:
union {
int32_t menu_index;
} payload;
EventType type;
};
SceneController<GenericScene<LfRfidDebugApp>, LfRfidDebugApp> scene_controller;
ViewController<LfRfidDebugApp, SubmenuVM, LfRfidViewTuneVM> view_controller;
~LfRfidDebugApp();
LfRfidDebugApp();
void run();
};

View File

@ -0,0 +1,47 @@
#include "lfrfid-debug-app-scene-start.h"
typedef enum {
SubmenuTune,
} SubmenuIndex;
void LfRfidDebugAppSceneStart::on_enter(LfRfidDebugApp* app, bool need_restore) {
auto submenu = app->view_controller.get<SubmenuVM>();
auto callback = cbc::obtain_connector(this, &LfRfidDebugAppSceneStart::submenu_callback);
submenu->add_item("Tune", SubmenuTune, callback, app);
if(need_restore) {
submenu->set_selected_item(submenu_item_selected);
}
app->view_controller.switch_to<SubmenuVM>();
}
bool LfRfidDebugAppSceneStart::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidDebugApp::EventType::MenuSelected) {
submenu_item_selected = event->payload.menu_index;
switch(event->payload.menu_index) {
case SubmenuTune:
app->scene_controller.switch_to_next_scene(LfRfidDebugApp::SceneType::TuneScene);
break;
}
consumed = true;
}
return consumed;
}
void LfRfidDebugAppSceneStart::on_exit(LfRfidDebugApp* app) {
app->view_controller.get<SubmenuVM>()->clean();
}
void LfRfidDebugAppSceneStart::submenu_callback(void* context, uint32_t index) {
LfRfidDebugApp* app = static_cast<LfRfidDebugApp*>(context);
LfRfidDebugApp::Event event;
event.type = LfRfidDebugApp::EventType::MenuSelected;
event.payload.menu_index = index;
app->view_controller.send_event(&event);
}

View File

@ -0,0 +1,13 @@
#pragma once
#include "../lfrfid-debug-app.h"
class LfRfidDebugAppSceneStart : public GenericScene<LfRfidDebugApp> {
public:
void on_enter(LfRfidDebugApp* app, bool need_restore) final;
bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final;
void on_exit(LfRfidDebugApp* app) final;
private:
void submenu_callback(void* context, uint32_t index);
uint32_t submenu_item_selected = 0;
};

View File

@ -0,0 +1,28 @@
#include "lfrfid-debug-app-scene-tune.h"
void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) {
app->view_controller.switch_to<LfRfidViewTuneVM>();
api_hal_rfid_pins_read();
api_hal_rfid_tim_read(125000, 0.5);
api_hal_rfid_tim_read_start();
}
bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) {
bool consumed = false;
LfRfidViewTuneVM* tune = app->view_controller;
if(tune->is_dirty()) {
api_hal_rfid_set_read_period(tune->get_ARR());
api_hal_rfid_set_read_pulse(tune->get_CCR());
}
return consumed;
}
void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) {
api_hal_rfid_tim_read_stop();
api_hal_rfid_tim_reset();
api_hal_rfid_pins_reset();
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "../lfrfid-debug-app.h"
class LfRfidDebugAppSceneTune : public GenericScene<LfRfidDebugApp> {
public:
void on_enter(LfRfidDebugApp* app, bool need_restore) final;
bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final;
void on_exit(LfRfidDebugApp* app) final;
};

View File

@ -1,10 +1,8 @@
#include "lf-rfid-view-tune.h"
#include "lfrfid-view-tune-vm.h"
#include <callback-connector.h>
#include <gui/elements.h>
#include <variant>
#include <list>
struct LfRfidViewTuneModel {
struct LfRfidViewTuneVMModel {
bool dirty;
bool fine;
uint32_t ARR;
@ -12,8 +10,8 @@ struct LfRfidViewTuneModel {
int pos;
};
void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) {
LfRfidViewTuneModel* model = reinterpret_cast<LfRfidViewTuneModel*>(_model);
void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) {
LfRfidViewTuneVMModel* model = reinterpret_cast<LfRfidViewTuneVMModel*>(_model);
canvas_clear(canvas);
canvas_set_color(canvas, ColorBlack);
@ -47,8 +45,8 @@ void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) {
elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer);
}
bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) {
LfRfidViewTune* _this = reinterpret_cast<LfRfidViewTune*>(context);
bool LfRfidViewTuneVM::view_input_callback(InputEvent* event, void* context) {
LfRfidViewTuneVM* _this = reinterpret_cast<LfRfidViewTuneVM*>(context);
bool consumed = false;
// Process key presses only
@ -80,22 +78,22 @@ bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) {
return consumed;
}
void LfRfidViewTune::button_up() {
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
void LfRfidViewTuneVM::button_up() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
if(model->pos > 0) model->pos--;
return true;
});
}
void LfRfidViewTune::button_down() {
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
void LfRfidViewTuneVM::button_down() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
if(model->pos < 1) model->pos++;
return true;
});
}
void LfRfidViewTune::button_left() {
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
void LfRfidViewTuneVM::button_left() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
if(model->pos == 0) {
if(model->fine) {
model->ARR -= 1;
@ -115,8 +113,8 @@ void LfRfidViewTune::button_left() {
});
}
void LfRfidViewTune::button_right() {
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
void LfRfidViewTuneVM::button_right() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
if(model->pos == 0) {
if(model->fine) {
model->ARR += 1;
@ -136,19 +134,19 @@ void LfRfidViewTune::button_right() {
});
}
void LfRfidViewTune::button_ok() {
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
void LfRfidViewTuneVM::button_ok() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
model->fine = !model->fine;
return true;
});
}
LfRfidViewTune::LfRfidViewTune() {
LfRfidViewTuneVM::LfRfidViewTuneVM() {
view = view_alloc();
view_set_context(view, this);
view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneModel));
view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneVMModel));
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
model->dirty = true;
model->fine = false;
model->ARR = 511;
@ -157,22 +155,34 @@ LfRfidViewTune::LfRfidViewTune() {
return true;
});
view_set_draw_callback(view, cbc::obtain_connector(this, &LfRfidViewTune::view_draw_callback));
view_set_draw_callback(
view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_draw_callback));
view_set_input_callback(
view, cbc::obtain_connector(this, &LfRfidViewTune::view_input_callback));
view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_input_callback));
}
LfRfidViewTune::~LfRfidViewTune() {
LfRfidViewTuneVM::~LfRfidViewTuneVM() {
view_free(view);
}
View* LfRfidViewTune::get_view() {
View* LfRfidViewTuneVM::get_view() {
return view;
}
bool LfRfidViewTune::is_dirty() {
void LfRfidViewTuneVM::clean() {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
model->dirty = true;
model->fine = false;
model->ARR = 511;
model->CCR = 255;
model->pos = 0;
return true;
});
}
bool LfRfidViewTuneVM::is_dirty() {
bool result;
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
result = model->dirty;
model->dirty = false;
return false;
@ -181,9 +191,9 @@ bool LfRfidViewTune::is_dirty() {
return result;
}
uint32_t LfRfidViewTune::get_ARR() {
uint32_t LfRfidViewTuneVM::get_ARR() {
uint32_t result;
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
result = model->ARR;
return false;
});
@ -191,9 +201,9 @@ uint32_t LfRfidViewTune::get_ARR() {
return result;
}
uint32_t LfRfidViewTune::get_CCR() {
uint32_t LfRfidViewTuneVM::get_CCR() {
uint32_t result;
with_view_model_cpp(view, LfRfidViewTuneModel, model, {
with_view_model_cpp(view, LfRfidViewTuneVMModel, model, {
result = model->CCR;
return false;
});

View File

@ -1,12 +1,13 @@
#pragma once
#include <gui/view.h>
#include <view-modules/generic-view-module.h>
class LfRfidViewTune {
class LfRfidViewTuneVM : public GenericViewModule {
public:
LfRfidViewTune();
~LfRfidViewTune();
View* get_view();
LfRfidViewTuneVM();
~LfRfidViewTuneVM() final;
View* get_view() final;
void clean() final;
bool is_dirty();
uint32_t get_ARR();

View File

@ -2,6 +2,7 @@
#include <stdint.h>
static const uint8_t LFRFID_KEY_SIZE = 8;
static const uint8_t LFRFID_KEY_NAME_SIZE = 22;
enum class LfrfidKeyType : uint8_t {
KeyEM4100,

View File

@ -0,0 +1,44 @@
#include "rfid-key.h"
#include <furi/check.h>
RfidKey::RfidKey() {
data.fill(0);
for(uint8_t i = 0; i < (LFRFID_KEY_NAME_SIZE + 1); i++) {
name[i] = 0;
}
}
RfidKey::~RfidKey() {
}
void RfidKey::set_type(LfrfidKeyType _type) {
type = _type;
}
void RfidKey::set_data(uint8_t* _data, const uint8_t _data_size) {
furi_assert(_data_size <= data.size());
for(uint8_t i = 0; i < _data_size; i++) {
data[i] = _data[i];
}
}
LfrfidKeyType RfidKey::get_type() {
return type;
}
uint8_t* RfidKey::get_data() {
return &data[0];
}
const char* RfidKey::get_type_text() {
return lfrfid_key_get_type_string(type);
}
const uint8_t RfidKey::get_type_data_count() {
return lfrfid_key_get_type_data_count(type);
}
char* RfidKey::get_name() {
return name;
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "key-info.h"
#include <array>
class RfidKey {
public:
RfidKey();
~RfidKey();
void set_type(LfrfidKeyType type);
void set_data(uint8_t* data, const uint8_t data_size);
LfrfidKeyType get_type();
uint8_t* get_data();
const char* get_type_text();
const uint8_t get_type_data_count();
char* get_name();
private:
std::array<uint8_t, LFRFID_KEY_SIZE> data;
LfrfidKeyType type;
char name[LFRFID_KEY_NAME_SIZE + 1];
};

View File

@ -0,0 +1,35 @@
#include "rfid-name-generator.h"
#include <stdio.h>
#include <stdlib.h>
void rfid_generate_random_name(char* name, uint8_t max_name_size) {
const uint8_t prefix_size = 9;
const char* prefix[prefix_size] = {
"good",
"nice",
"best",
"some",
"strange",
"working",
"that",
"forgettable",
"easy",
};
const uint8_t suffix_size = 7;
const char* suffix[suffix_size] = {
"pass",
"card",
"key",
"fob",
"permit",
"pass",
"one",
};
sniprintf(
name, max_name_size, "%s_%s", prefix[rand() % prefix_size], suffix[rand() % suffix_size]);
// to upper
name[0] = name[0] - ('a' - 'A');
}

View File

@ -0,0 +1,4 @@
#pragma once
#include "stdint.h"
void rfid_generate_random_name(char* name, uint8_t max_name_size);

View File

@ -18,7 +18,7 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d
if(encoders.count(type)) {
current_encoder = encoders.find(type)->second;
if(lfrfid_key_get_type_data_count(type) == data_size) {
if(data_size >= lfrfid_key_get_type_data_count(type)) {
current_encoder->init(data, data_size);
api_hal_rfid_tim_emulate(125000);
@ -26,14 +26,6 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d
api_interrupt_add(timer_update_callback, InterruptTypeTimerUpdate, this);
// TODO make api for interrupts priority
for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) {
HAL_NVIC_SetPriority(static_cast<IRQn_Type>(i), 15, 0);
}
HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 5, 0);
HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);
api_hal_rfid_tim_emulate_start();
}
} else {

View File

@ -0,0 +1,111 @@
#include "rfid-worker.h"
RfidWorker::RfidWorker() {
}
RfidWorker::~RfidWorker() {
}
void RfidWorker::start_read() {
reader.start(RfidReader::Type::Normal);
}
bool RfidWorker::read() {
static const uint8_t data_size = LFRFID_KEY_SIZE;
uint8_t data[data_size] = {0};
LfrfidKeyType type;
bool result = reader.read(&type, data, data_size);
if(result) {
key.set_type(type);
key.set_data(data, data_size);
};
return result;
}
void RfidWorker::stop_read() {
reader.stop();
}
void RfidWorker::start_write() {
write_result = WriteResult::Nothing;
write_sequence = new TickSequencer();
validate_counts = 0;
write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write, this));
write_sequence->do_after_tick(2, std::bind(&RfidWorker::sq_write_start_validate, this));
write_sequence->do_after_tick(15, std::bind(&RfidWorker::sq_write_validate, this));
write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write_stop_validate, this));
}
RfidWorker::WriteResult RfidWorker::write() {
write_sequence->tick();
return write_result;
}
void RfidWorker::stop_write() {
delete write_sequence;
reader.stop();
}
void RfidWorker::start_emulate() {
emulator.start(key.get_type(), key.get_data(), key.get_type_data_count());
}
void RfidWorker::stop_emulate() {
emulator.stop();
}
void RfidWorker::sq_write() {
// TODO expand this
switch(key.get_type()) {
case LfrfidKeyType::KeyEM4100:
writer.start();
writer.write_em(key.get_data());
writer.stop();
break;
case LfrfidKeyType::KeyH10301:
writer.start();
writer.write_hid(key.get_data());
writer.stop();
break;
default:
break;
}
}
void RfidWorker::sq_write_start_validate() {
reader.start(RfidReader::Type::Normal);
}
void RfidWorker::sq_write_validate() {
static const uint8_t data_size = LFRFID_KEY_SIZE;
uint8_t data[data_size] = {0};
LfrfidKeyType type;
bool result = reader.read(&type, data, data_size);
if(result) {
if(type == key.get_type()) {
if(memcmp(data, key.get_data(), key.get_type_data_count()) == 0) {
write_result = WriteResult::Ok;
validate_counts = 0;
} else {
validate_counts++;
}
} else {
validate_counts++;
}
if(validate_counts > 5) {
write_result = WriteResult::NotWritable;
}
};
}
void RfidWorker::sq_write_stop_validate() {
reader.stop();
}

View File

@ -0,0 +1,46 @@
#pragma once
#include "key-info.h"
#include "rfid-reader.h"
#include "rfid-writer.h"
#include "rfid-timer-emulator.h"
#include "rfid-key.h"
#include "state-sequencer.h"
class RfidWorker {
public:
RfidWorker();
~RfidWorker();
void start_read();
bool read();
void stop_read();
enum class WriteResult : uint8_t {
Ok,
NotWritable,
Nothing,
};
void start_write();
WriteResult write();
void stop_write();
void start_emulate();
void stop_emulate();
RfidKey key;
private:
RfidWriter writer;
RfidReader reader;
RfidTimerEmulator emulator;
WriteResult write_result;
TickSequencer* write_sequence;
void sq_write();
void sq_write_start_validate();
void sq_write_validate();
uint8_t validate_counts;
void sq_write_stop_validate();
};

View File

@ -1,6 +1,7 @@
#include "rfid-writer.h"
#include <api-hal.h>
#include "protocols/protocol-emmarin.h"
#include "protocols/protocol-hid-h10301.h"
extern COMP_HandleTypeDef hcomp1;
@ -11,8 +12,8 @@ extern COMP_HandleTypeDef hcomp1;
class T55xxTiming {
public:
constexpr static const uint16_t wait_time = 400;
constexpr static const uint8_t start_gap = 15;
constexpr static const uint8_t write_gap = 10;
constexpr static const uint8_t start_gap = 30;
constexpr static const uint8_t write_gap = 18;
constexpr static const uint8_t data_0 = 24;
constexpr static const uint8_t data_1 = 56;
constexpr static const uint16_t program = 700;
@ -34,6 +35,7 @@ RfidWriter::~RfidWriter() {
void RfidWriter::start() {
api_hal_rfid_tim_read(125000, 0.5);
api_hal_rfid_pins_read();
api_hal_rfid_tim_read_start();
}
void RfidWriter::stop() {
@ -64,8 +66,6 @@ void RfidWriter::write_byte(uint8_t value) {
}
void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) {
// wait to power card
api_hal_rfid_tim_read_start();
delay_us(T55xxTiming::wait_time * 8);
// start gap
@ -101,18 +101,42 @@ void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_
delay_us(T55xxTiming::program * 8);
api_hal_rfid_tim_read_stop();
delay_us(T55xxTiming::wait_time * 8);
write_reset();
}
void RfidWriter::write_reset() {
write_gap(T55xxTiming::start_gap);
write_bit(1);
write_bit(0);
}
void RfidWriter::write_em(uint8_t em_data[5]) {
ProtocolEMMarin em_card;
uint64_t em_encoded_data;
em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t));
uint32_t em_config_block_data = 0b01100000000101001000000001000000;
const uint32_t em_config_block_data = 0b01100000000101001000000001000000;
__disable_irq();
write_block(0, 0, false, em_config_block_data);
write_block(0, 1, false, em_encoded_data);
write_block(0, 2, false, em_encoded_data >> 32);
write_reset();
__enable_irq();
}
void RfidWriter::write_hid(uint8_t hid_data[3]) {
ProtocolHID10301 hid_card;
uint32_t card_data[3];
hid_card.encode(hid_data, 3, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data) * 3);
const uint32_t hid_config_block_data = 0b00000000000100000111000001100000;
__disable_irq();
write_block(0, 0, false, hid_config_block_data);
write_block(0, 1, false, card_data[0]);
write_block(0, 2, false, card_data[1]);
write_block(0, 3, false, card_data[2]);
write_reset();
__enable_irq();
}

View File

@ -8,10 +8,12 @@ public:
void start();
void stop();
void write_em(uint8_t em_data[5]);
void write_hid(uint8_t hid_data[3]);
private:
void write_gap(uint32_t gap_time);
void write_bit(bool value);
void write_byte(uint8_t value);
void write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data);
void write_reset();
};

View File

@ -0,0 +1,50 @@
#include "state-sequencer.h"
#include "stdio.h"
TickSequencer::TickSequencer() {
}
TickSequencer::~TickSequencer() {
}
void TickSequencer::tick() {
if(tick_count == list_it->first) {
tick_count = 0;
list_it++;
if(list_it == list.end()) {
list_it = list.begin();
}
}
list_it->second();
tick_count++;
}
void TickSequencer::reset() {
list_it = list.begin();
tick_count = 0;
}
void TickSequencer::clear() {
list.clear();
reset();
}
void TickSequencer::do_every_tick(uint32_t tick_count, std::function<void(void)> fn) {
list.push_back(std::make_pair(tick_count, fn));
reset();
}
void TickSequencer::do_after_tick(uint32_t tick_count, std::function<void(void)> fn) {
if(tick_count > 1) {
list.push_back(
std::make_pair(tick_count - 1, std::bind(&TickSequencer::do_nothing, this)));
}
list.push_back(std::make_pair(1, fn));
reset();
}
void TickSequencer::do_nothing() {
}

View File

@ -0,0 +1,25 @@
#pragma once
#include "stdint.h"
#include <list>
#include <functional>
class TickSequencer {
public:
TickSequencer();
~TickSequencer();
void tick();
void reset();
void clear();
void do_every_tick(uint32_t tick_count, std::function<void(void)> fn);
void do_after_tick(uint32_t tick_count, std::function<void(void)> fn);
private:
std::list<std::pair<uint32_t, std::function<void(void)> > > list;
std::list<std::pair<uint32_t, std::function<void(void)> > >::iterator list_it;
uint32_t tick_count;
void do_nothing();
};

View File

@ -0,0 +1,10 @@
#include "lfrfid-app.h"
// app enter function
extern "C" int32_t lfrfid_app(void* p) {
LfRfidApp* app = new LfRfidApp();
app->run();
delete app;
return 0;
}

View File

@ -0,0 +1,37 @@
#include "lfrfid-app.h"
#include "scene/lfrfid-app-scene-start.h"
#include "scene/lfrfid-app-scene-read.h"
#include "scene/lfrfid-app-scene-read-success.h"
#include "scene/lfrfid-app-scene-readed-menu.h"
#include "scene/lfrfid-app-scene-write.h"
#include "scene/lfrfid-app-scene-write-success.h"
#include "scene/lfrfid-app-scene-emulate.h"
#include "scene/lfrfid-app-scene-save-name.h"
LfRfidApp::LfRfidApp()
: scene_controller{this}
, fs_api{"sdcard"}
, sd_ex_api{"sdcard-ex"}
, notification{"notification"}
, text_store(40) {
api_hal_power_insomnia_enter();
// we need random
srand(DWT->CYCCNT);
}
LfRfidApp::~LfRfidApp() {
api_hal_power_insomnia_exit();
}
void LfRfidApp::run() {
scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess());
scene_controller.add_scene(SceneType::ReadedMenu, new LfRfidAppSceneReadedMenu());
scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite());
scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName());
scene_controller.process(100);
}

View File

@ -0,0 +1,67 @@
#pragma once
#include <furi.h>
#include <api-hal.h>
#include <generic-scene.hpp>
#include <scene-controller.hpp>
#include <view-controller.hpp>
#include <record-controller.hpp>
#include <text-store.h>
#include <view-modules/submenu-vm.h>
#include <view-modules/popup-vm.h>
#include <view-modules/dialog-ex-vm.h>
#include <view-modules/text-input-vm.h>
#include <view-modules/byte-input-vm.h>
#include "view/container-vm.h"
#include <sd-card-api.h>
#include <filesystem-api.h>
#include <notification/notification-messages.h>
#include "helpers/rfid-worker.h"
class LfRfidApp {
public:
enum class EventType : uint8_t {
GENERIC_EVENT_ENUM_VALUES,
Next,
MenuSelected,
};
enum class SceneType : uint8_t {
GENERIC_SCENE_ENUM_VALUES,
Read,
ReadSuccess,
ReadedMenu,
Write,
WriteSuccess,
Emulate,
SaveName,
};
class Event {
public:
union {
int32_t menu_index;
} payload;
EventType type;
};
SceneController<GenericScene<LfRfidApp>, LfRfidApp> scene_controller;
ViewController<LfRfidApp, SubmenuVM, PopupVM, DialogExVM, TextInputVM, ByteInputVM, ContainerVM>
view_controller;
~LfRfidApp();
LfRfidApp();
RecordController<FS_Api> fs_api;
RecordController<SdCard_Api> sd_ex_api;
RecordController<NotificationApp> notification;
RfidWorker worker;
TextStore text_store;
void run();
};

View File

@ -0,0 +1,36 @@
#include "lfrfid-app-scene-emulate.h"
void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool need_restore) {
string_init(data_string);
uint8_t* data = app->worker.key.get_data();
for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
string_cat_printf(data_string, "%02X", data[i]);
}
auto popup = app->view_controller.get<PopupVM>();
popup->set_header("Emulating", 90, 34, AlignCenter, AlignTop);
popup->set_text(string_get_cstr(data_string), 90, 48, AlignCenter, AlignTop);
popup->set_icon(0, 4, I_RFIDDolphinSend_98x60);
app->view_controller.switch_to<PopupVM>();
app->worker.start_emulate();
}
bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::Tick) {
notification_message(app->notification, &sequence_blink_cyan_10);
}
return consumed;
}
void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) {
app->view_controller.get<PopupVM>()->clean();
app->worker.stop_emulate();
string_clear(data_string);
}

View File

@ -0,0 +1,12 @@
#pragma once
#include "../lfrfid-app.h"
class LfRfidAppSceneEmulate : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
void on_exit(LfRfidApp* app) final;
private:
string_t data_string;
};

View File

@ -0,0 +1,117 @@
#include "lfrfid-app-scene-read-success.h"
#include "../view/elements/button-element.h"
#include "../view/elements/icon-element.h"
#include "../view/elements/string-element.h"
void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) {
string_init(string[0]);
string_init(string[1]);
string_init(string[2]);
auto container = app->view_controller.get<ContainerVM>();
auto button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Left, "Retry");
button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback);
button = container->add<ButtonElement>();
button->set_type(ButtonElement::Type::Right, "More");
button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback);
auto icon = container->add<IconElement>();
icon->set_icon(3, 12, I_RFIDBigChip_37x36);
auto header = container->add<StringElement>();
header->set_text(app->worker.key.get_type_text(), 89, 3, AlignCenter);
auto line_1_text = container->add<StringElement>();
auto line_2_text = container->add<StringElement>();
auto line_3_text = container->add<StringElement>();
auto line_1_value = container->add<StringElement>();
auto line_2_value = container->add<StringElement>();
auto line_3_value = container->add<StringElement>();
uint8_t* data = app->worker.key.get_data();
switch(app->worker.key.get_type()) {
case LfrfidKeyType::KeyEM4100:
line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
line_2_text->set_text("Mod:", 65, 35, AlignRight, AlignBottom, FontSecondary);
line_3_text->set_text("ID:", 65, 47, AlignRight, AlignBottom, FontSecondary);
for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
string_cat_printf(string[0], "%02X", data[i]);
}
string_printf(string[1], "Manchester");
string_printf(string[2], "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
line_1_value->set_text(
string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
line_2_value->set_text(
string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
line_3_value->set_text(
string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
break;
case LfrfidKeyType::KeyH10301:
line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary);
line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary);
line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary);
for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) {
string_cat_printf(string[0], "%02X", data[i]);
}
string_printf(string[1], "%u", data[0]);
string_printf(string[2], "%u", (uint16_t)((data[1] << 8) | (data[2])));
line_1_value->set_text(
string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary);
line_2_value->set_text(
string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary);
line_3_value->set_text(
string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary);
break;
case LfrfidKeyType::KeyI40134:
//TODO implement when we can read Indala
break;
}
app->view_controller.switch_to<ContainerVM>();
notification_message_block(app->notification, &sequence_set_green_255);
}
bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::Next) {
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadedMenu);
consumed = true;
}
return consumed;
}
void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
notification_message_block(app->notification, &sequence_reset_green);
app->view_controller.get<ContainerVM>()->clean();
string_clear(string[0]);
string_clear(string[1]);
string_clear(string[2]);
}
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Back;
app->view_controller.send_event(&event);
}
void LfRfidAppSceneReadSuccess::more_callback(void* context) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::Next;
app->view_controller.send_event(&event);
}

View File

@ -0,0 +1,15 @@
#pragma once
#include "../lfrfid-app.h"
class LfRfidAppSceneReadSuccess : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
void on_exit(LfRfidApp* app) final;
private:
static void back_callback(void* context);
static void more_callback(void* context);
string_t string[3];
};

View File

@ -0,0 +1,31 @@
#include "lfrfid-app-scene-read.h"
void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool need_restore) {
auto popup = app->view_controller.get<PopupVM>();
popup->set_header("Reading\nLF RFID", 70, 34, AlignLeft, AlignTop);
popup->set_icon(0, 4, I_RFIDDolphinReceive_98x60);
app->view_controller.switch_to<PopupVM>();
app->worker.start_read();
}
bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::Tick) {
if(app->worker.read()) {
notification_message(app->notification, &sequence_success);
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess);
} else {
notification_message(app->notification, &sequence_blink_red_10);
}
}
return consumed;
}
void LfRfidAppSceneRead::on_exit(LfRfidApp* app) {
app->view_controller.get<PopupVM>()->clean();
app->worker.stop_read();
}

View File

@ -0,0 +1,9 @@
#pragma once
#include "../lfrfid-app.h"
class LfRfidAppSceneRead : public GenericScene<LfRfidApp> {
public:
void on_enter(LfRfidApp* app, bool need_restore) final;
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
void on_exit(LfRfidApp* app) final;
};

View File

@ -0,0 +1,60 @@
#include "lfrfid-app-scene-readed-menu.h"
typedef enum {
SubmenuWrite,
SubmenuNameAndSave,
SubmenuEmulate,
} SubmenuIndex;
void LfRfidAppSceneReadedMenu::on_enter(LfRfidApp* app, bool need_restore) {
auto submenu = app->view_controller.get<SubmenuVM>();
submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
submenu->add_item("Name and Save", SubmenuNameAndSave, submenu_callback, app);
submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
if(need_restore) {
submenu->set_selected_item(submenu_item_selected);
}
app->view_controller.switch_to<SubmenuVM>();
}
bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
bool consumed = false;
if(event->type == LfRfidApp::EventType::MenuSelected) {
submenu_item_selected = event->payload.menu_index;
switch(event->payload.menu_index) {
case SubmenuWrite:
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
break;
case SubmenuNameAndSave:
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
break;
case SubmenuEmulate:
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
break;
}
consumed = true;
} else if(event->type == LfRfidApp::EventType::Back) {
app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
consumed = true;
}
return consumed;
}
void LfRfidAppSceneReadedMenu::on_exit(LfRfidApp* app) {
app->view_controller.get<SubmenuVM>()->clean();
}
void LfRfidAppSceneReadedMenu::submenu_callback(void* context, uint32_t index) {
LfRfidApp* app = static_cast<LfRfidApp*>(context);
LfRfidApp::Event event;
event.type = LfRfidApp::EventType::MenuSelected;
event.payload.menu_index = index;
app->view_controller.send_event(&event);
}

Some files were not shown because too many files have changed in this diff Show More