[FL-2529][FL-1628] New LF-RFID subsystem (#1601)
* Makefile: unit tests pack * RFID: pulse joiner and its unit test * Move pulse protocol helpers to appropriate place * Drop pulse_joiner tests * Generic protocol, protocols dictionary, unit test * Protocol dict unit test * iButton: protocols dictionary * Lib: varint * Lib: profiler * Unit test: varint * rfid: worker mockup * LFRFID: em4100 unit test * Storage: file_exist function * rfid: fsk osc * rfid: generic fsk demodulator * rfid: protocol em4100 * rfid: protocol h10301 * rfid: protocol io prox xsf * Unit test: rfid protocols * rfid: new hal * rfid: raw worker * Unit test: fix error output * rfid: worker * rfid: plain c cli * fw: migrate to scons * lfrfid: full io prox support * unit test: io prox protocol * SubGHZ: move bit defines to source * FSK oscillator: level duration compability * libs: bit manipulation library * lfrfid: ioprox protocol, use bit library and new level duration method of FSK ocillator * bit lib: unit tests * Bit lib: parity tests, remove every nth bit, copy bits * Lfrfid: awid protocol * bit lib: uint16 and uint32 getters, unit tests * lfrfid: FDX-B read, draft version * Minunit: better memeq assert * bit lib: reverse, print, print regions * Protocol dict: get protocol features, get protocol validate count * lfrfid worker: improved read * lfrfid raw worker: psk support * Cli: rfid plain C cli * protocol AWID: render * protocol em4100: render * protocol h10301: render * protocol indala26: support every indala 26 scramble * Protocol IO Prox: render * Protocol FDX-B: advanced read * lfrfid: remove unused test function * lfrfid: fix os primitives * bit lib: crc16 and unit tests * FDX-B: save data * lfrfid worker: increase stream size. Alloc raw worker only when needed. * lfrfid: indala26 emulation * lfrfid: prepare to write * lfrfid: fdx-b emulation * lfrfid: awid, ioprox write * lfrfid: write t55xx w\o validation * lfrfid: better t55xx block0 handling * lfrfid: use new t5577 functions in worker * lfrfid: improve protocol description * lfrfid: write and verify * lfrfid: delete cpp cli * lfrfid: improve worker usage * lfrfid-app: step to new worker * lfrfid: old indala (I40134) load fallback * lfrfid: indala26, recover wrong synced data * lfrfid: remove old worker * lfrfid app: dummy read screen * lfrfid app: less dummy read screen * lfrfid: generic 96-bit HID protocol (covers up to HID 37-bit) * rename * lfrfid: improve indala26 read * lfrfid: generic 192-bit HID protocol (covers all HID extended) * lfrfid: TODO about HID render * lfrfid: new protocol FDX-A * lfrfid-app: correct worker stop on exit * misc fixes * lfrfid: FDX-A and HID distinguishability has been fixed. * lfrfid: decode HID size header and render it (#1612) * lfrfid: rename HID96 and HID192 to HIDProx and HIDExt * lfrfid: extra actions scene * lfrfid: decode generic HID Proximity size lazily (#1618) * lib: stream of data buffers concept * lfrfid: raw file helper * lfrfid: changed raw worker api * lfrfid: packed varint pair * lfrfid: read stream speedup * lfrfid app: show read mode * Documentation * lfrfid app: raw read gui * lfrfid app: storage check for raw read * memleak fix * review fixes * lfrfid app: read blink color * lfrfid app: reset key name after read * review fixes * lfrfid app: fix copypasted text * review fixes * lfrfid: disable debug gpio * lfrfid: card detection events * lfrfid: change validation color from magenta to green * Update core_defines. * lfrfid: prefix fdx-b id by zeroes * lfrfid: parse up to 43-bit HID Proximity keys (#1640) * Fbt: downgrade toolchain and fix PS1 * lfrfid: fix unit tests * lfrfid app: remove printf * lfrfid: indala26, use bit 55 as data * lfrfid: indala26, better brief format * lfrfid: indala26, loading fallback * lfrfid: read timing tuning Co-authored-by: James Ide <ide@users.noreply.github.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
@@ -5,7 +5,6 @@
|
||||
|
||||
void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_data);
|
||||
string_init(string_decrypted);
|
||||
string_init(string_header);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
@@ -21,49 +20,26 @@ void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
auto line_3 = container->add<StringElement>();
|
||||
auto line_4 = container->add<StringElement>();
|
||||
|
||||
RfidKey& key = app->worker.key;
|
||||
const uint8_t* data = key.get_data();
|
||||
|
||||
for(uint8_t i = 0; i < key.get_type_data_count(); i++) {
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_data, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(string_data, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_printf(string_header, "Delete %s?", key.get_name());
|
||||
string_printf(string_header, "Delete %s?", string_get_cstr(app->file_name));
|
||||
line_1->set_text(
|
||||
string_get_cstr(string_header), 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
|
||||
string_get_cstr(string_header), 64, 0, 128 - 2, AlignCenter, AlignTop, FontPrimary);
|
||||
line_2->set_text(
|
||||
string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
switch(key.get_type()) {
|
||||
case LfrfidKeyType::KeyEM4100:
|
||||
string_printf(
|
||||
string_decrypted, "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
|
||||
|
||||
break;
|
||||
case LfrfidKeyType::KeyH10301:
|
||||
case LfrfidKeyType::KeyI40134:
|
||||
string_printf(
|
||||
string_decrypted, "FC: %u ID: %u", data[0], (uint16_t)((data[1] << 8) | (data[2])));
|
||||
break;
|
||||
case LfrfidKeyType::KeyIoProxXSF:
|
||||
string_printf(
|
||||
string_decrypted,
|
||||
"FC: %u VC: %u ID: %u",
|
||||
data[0],
|
||||
data[1],
|
||||
(uint16_t)((data[2] << 8) | (data[3])));
|
||||
break;
|
||||
}
|
||||
string_get_cstr(string_data), 64, 19, 0, AlignCenter, AlignTop, FontSecondary);
|
||||
line_3->set_text(
|
||||
string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
line_4->set_text(
|
||||
lfrfid_key_get_type_string(key.get_type()),
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
64,
|
||||
49,
|
||||
0,
|
||||
@@ -78,7 +54,7 @@ bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* eve
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->delete_key(&app->worker.key);
|
||||
app->delete_key();
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Stay) {
|
||||
@@ -94,7 +70,6 @@ bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* eve
|
||||
void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_data);
|
||||
string_clear(string_decrypted);
|
||||
string_clear(string_header);
|
||||
}
|
||||
|
||||
|
@@ -13,5 +13,4 @@ private:
|
||||
|
||||
string_t string_header;
|
||||
string_t string_data;
|
||||
string_t string_decrypted;
|
||||
};
|
||||
|
@@ -3,28 +3,21 @@
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(data_string);
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidEmulate);
|
||||
const 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", 89, 30, AlignCenter, AlignTop);
|
||||
if(strlen(app->worker.key.get_name())) {
|
||||
popup->set_text(app->worker.key.get_name(), 89, 43, AlignCenter, AlignTop);
|
||||
if(string_size(app->file_name)) {
|
||||
popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_text(string_get_cstr(data_string), 89, 43, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
|
||||
}
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
app->worker.start_emulate();
|
||||
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
@@ -37,7 +30,7 @@ bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
|
||||
void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
app->worker.stop_emulate();
|
||||
string_clear(data_string);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
}
|
||||
|
@@ -6,7 +6,4 @@ 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;
|
||||
};
|
||||
|
63
applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp
Normal file
63
applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp
Normal file
@@ -0,0 +1,63 @@
|
||||
#include "lfrfid_app_scene_extra_actions.h"
|
||||
|
||||
typedef enum {
|
||||
SubmenuASK,
|
||||
SubmenuPSK,
|
||||
SubmenuRAW,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneExtraActions::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
submenu->add_item("Read ASK (Animal, Ordinary Card)", SubmenuASK, submenu_callback, app);
|
||||
submenu->add_item("Read PSK (Indala)", SubmenuPSK, submenu_callback, app);
|
||||
|
||||
if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
|
||||
submenu->add_item("Read RAW RFID data", SubmenuRAW, submenu_callback, app);
|
||||
}
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneExtraActions::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuASK:
|
||||
app->read_type = LFRFIDWorkerReadTypeASKOnly;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
case SubmenuPSK:
|
||||
app->read_type = LFRFIDWorkerReadTypePSKOnly;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
case SubmenuRAW:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawName);
|
||||
break;
|
||||
}
|
||||
|
||||
consumed = true;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExtraActions::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneExtraActions::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
13
applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h
Normal file
13
applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneExtraActions : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
};
|
77
applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp
Normal file
77
applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp
Normal file
@@ -0,0 +1,77 @@
|
||||
#include "lfrfid_app_scene_raw_info.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
static void ok_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
static void back_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawInfo::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
|
||||
if(!sd_exist) {
|
||||
auto icon = container->add<IconElement>();
|
||||
icon->set_icon(0, 0, &I_SDQuestion_35x43);
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(
|
||||
"No SD card found.\nThis function will not\nwork without\nSD card.",
|
||||
81,
|
||||
4,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignTop,
|
||||
FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Back");
|
||||
button->set_callback(app, back_callback);
|
||||
} else {
|
||||
string_printf(
|
||||
string_info,
|
||||
"RAW RFID data reader\r\n"
|
||||
"1) Put the Flipper on your card\r\n"
|
||||
"2) Press OK\r\n"
|
||||
"3) Wait until data is read");
|
||||
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Center, "OK");
|
||||
button->set_callback(app, ok_callback);
|
||||
}
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawInfo::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.switch_to_scene({LfRfidApp::SceneType::RawRead});
|
||||
consumed = true;
|
||||
} else if(event->type == LfRfidApp::EventType::Back) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ExtraActions});
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawInfo::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
}
|
12
applications/lfrfid/scene/lfrfid_app_scene_raw_info.h
Normal file
12
applications/lfrfid/scene/lfrfid_app_scene_raw_info.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawInfo : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_info;
|
||||
};
|
46
applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp
Normal file
46
applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
|
||||
#include "lfrfid_app_scene_raw_name.h"
|
||||
#include "m-string.h"
|
||||
#include <lib/toolbox/random_name.h>
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
void LfRfidAppSceneRawName::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
const char* key_name = string_get_cstr(app->raw_file_name);
|
||||
|
||||
bool key_name_empty = (string_size(app->raw_file_name) == 0);
|
||||
if(key_name_empty) {
|
||||
app->text_store.set("RfidRecord");
|
||||
} else {
|
||||
app->text_store.set("%s", key_name);
|
||||
}
|
||||
|
||||
auto text_input = app->view_controller.get<TextInputVM>();
|
||||
text_input->set_header_text("Name the raw file");
|
||||
|
||||
text_input->set_result_callback(
|
||||
save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty);
|
||||
|
||||
app->view_controller.switch_to<TextInputVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
string_set_str(app->raw_file_name, app->text_store.text);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawInfo);
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawName::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<TextInputVM>()->clean();
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawName::save_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
12
applications/lfrfid/scene/lfrfid_app_scene_raw_name.h
Normal file
12
applications/lfrfid/scene/lfrfid_app_scene_raw_name.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawName : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void save_callback(void* context);
|
||||
};
|
107
applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp
Normal file
107
applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp
Normal file
@@ -0,0 +1,107 @@
|
||||
#include "lfrfid_app_scene_raw_read.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
#define RAW_READ_TIME 5000
|
||||
|
||||
static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
switch(result) {
|
||||
case LFRFIDWorkerReadRawFileError:
|
||||
event.type = LfRfidApp::EventType::ReadEventError;
|
||||
break;
|
||||
case LFRFIDWorkerReadRawOverrun:
|
||||
event.type = LfRfidApp::EventType::ReadEventOverrun;
|
||||
break;
|
||||
}
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
static void timer_callback(void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::ReadEventDone;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawRead::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_file_name);
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
app->make_app_folder();
|
||||
|
||||
timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app);
|
||||
furi_timer_start(timer, RAW_READ_TIME);
|
||||
string_printf(
|
||||
string_file_name, "%s/%s.ask.raw", app->app_sd_folder, string_get_cstr(app->raw_file_name));
|
||||
popup->set_header("Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(string_file_name),
|
||||
LFRFIDWorkerReadTypeASKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
|
||||
is_psk = false;
|
||||
error = false;
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
UNUSED(app);
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::ReadEventError:
|
||||
error = true;
|
||||
popup->set_header("Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_red);
|
||||
furi_timer_stop(timer);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventDone:
|
||||
if(!error) {
|
||||
if(is_psk) {
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::RawSuccess);
|
||||
} else {
|
||||
popup->set_header("Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
string_printf(
|
||||
string_file_name,
|
||||
"%s/%s.psk.raw",
|
||||
app->app_sd_folder,
|
||||
string_get_cstr(app->raw_file_name));
|
||||
lfrfid_worker_read_raw_start(
|
||||
app->lfworker,
|
||||
string_get_cstr(string_file_name),
|
||||
LFRFIDWorkerReadTypePSKOnly,
|
||||
lfrfid_read_callback,
|
||||
app);
|
||||
furi_timer_start(timer, RAW_READ_TIME);
|
||||
is_psk = true;
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawRead::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
furi_timer_free(timer);
|
||||
string_clear(string_file_name);
|
||||
}
|
15
applications/lfrfid/scene/lfrfid_app_scene_raw_read.h
Normal file
15
applications/lfrfid/scene/lfrfid_app_scene_raw_read.h
Normal file
@@ -0,0 +1,15 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawRead : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_file_name;
|
||||
FuriTimer* timer;
|
||||
bool is_psk;
|
||||
bool error;
|
||||
};
|
45
applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp
Normal file
45
applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp
Normal file
@@ -0,0 +1,45 @@
|
||||
#include "lfrfid_app_scene_raw_success.h"
|
||||
#include "../view/elements/button_element.h"
|
||||
#include "../view/elements/icon_element.h"
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneRawSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_info);
|
||||
|
||||
string_printf(string_info, "RAW RFID read success!\r\n");
|
||||
string_cat_printf(string_info, "Now you can analyze files\r\n");
|
||||
string_cat_printf(string_info, "Or send them to developers");
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto line = container->add<StringElement>();
|
||||
line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Center, "OK");
|
||||
button->set_callback(app, LfRfidAppSceneRawSuccess::ok_callback);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRawSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
{LfRfidApp::SceneType::ExtraActions});
|
||||
consumed = true;
|
||||
}
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawSuccess::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_info);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRawSuccess::ok_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Next;
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
13
applications/lfrfid/scene/lfrfid_app_scene_raw_success.h
Normal file
13
applications/lfrfid/scene/lfrfid_app_scene_raw_success.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
#include "../lfrfid_app.h"
|
||||
|
||||
class LfRfidAppSceneRawSuccess : public GenericScene<LfRfidApp> {
|
||||
public:
|
||||
void on_enter(LfRfidApp* app, bool need_restore) final;
|
||||
bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
string_t string_info;
|
||||
static void ok_callback(void* context);
|
||||
};
|
@@ -1,40 +1,100 @@
|
||||
#include "lfrfid_app_scene_read.h"
|
||||
#include <dolphin/dolphin.h>
|
||||
|
||||
static void lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
switch(result) {
|
||||
case LFRFIDWorkerReadSenseStart:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseStart;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseEnd:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseEnd;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseCardStart:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseCardStart;
|
||||
break;
|
||||
case LFRFIDWorkerReadSenseCardEnd:
|
||||
event.type = LfRfidApp::EventType::ReadEventSenseCardEnd;
|
||||
break;
|
||||
case LFRFIDWorkerReadDone:
|
||||
event.type = LfRfidApp::EventType::ReadEventDone;
|
||||
break;
|
||||
case LFRFIDWorkerReadStartASK:
|
||||
event.type = LfRfidApp::EventType::ReadEventStartASK;
|
||||
break;
|
||||
case LFRFIDWorkerReadStartPSK:
|
||||
event.type = LfRfidApp::EventType::ReadEventStartPSK;
|
||||
break;
|
||||
}
|
||||
|
||||
event.payload.signed_int = protocol;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
DOLPHIN_DEED(DolphinDeedRfidRead);
|
||||
popup->set_header("Reading\nLF RFID", 89, 34, AlignCenter, AlignTop);
|
||||
if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
|
||||
popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
}
|
||||
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
app->worker.start_read();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Tick) {
|
||||
if(app->worker.read()) {
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess);
|
||||
} else {
|
||||
if(app->worker.any_read()) {
|
||||
notification_message(app->notification, &sequence_blink_yellow_10);
|
||||
} else if(app->worker.detect()) {
|
||||
notification_message(app->notification, &sequence_blink_yellow_10);
|
||||
} else {
|
||||
notification_message(app->notification, &sequence_blink_cyan_10);
|
||||
}
|
||||
}
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::ReadEventSenseStart:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventSenseCardStart:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_green);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventSenseEnd:
|
||||
case LfRfidApp::EventType::ReadEventSenseCardEnd:
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
notification_message(app->notification, &sequence_blink_start_cyan);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventDone:
|
||||
app->protocol_id = event->payload.signed_int;
|
||||
DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
|
||||
notification_message(app->notification, &sequence_success);
|
||||
string_reset(app->file_name);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventStartPSK:
|
||||
popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop);
|
||||
break;
|
||||
case LfRfidApp::EventType::ReadEventStartASK:
|
||||
popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop);
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneRead::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
app->worker.stop_read();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
}
|
||||
|
@@ -24,8 +24,8 @@ bool LfRfidAppSceneReadKeyMenu::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) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuWrite:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
|
||||
break;
|
||||
@@ -54,7 +54,7 @@ void LfRfidAppSceneReadKeyMenu::submenu_callback(void* context, uint32_t index)
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
@@ -4,10 +4,37 @@
|
||||
#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]);
|
||||
string_init(string[3]);
|
||||
string_init(string_info);
|
||||
string_init(string_header);
|
||||
|
||||
string_init_printf(
|
||||
string_header,
|
||||
"%s[%s]",
|
||||
protocol_dict_get_name(app->dict, app->protocol_id),
|
||||
protocol_dict_get_manufacturer(app->dict, app->protocol_id));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_info, " ");
|
||||
}
|
||||
|
||||
if(i >= 9) {
|
||||
string_cat_printf(string_info, "...");
|
||||
break;
|
||||
} else {
|
||||
string_cat_printf(string_info, "%02X", data[i]);
|
||||
}
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
@@ -19,90 +46,11 @@ void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */
|
||||
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, 0, AlignCenter);
|
||||
header->set_text(string_get_cstr(string_header), 0, 2, 0, AlignLeft, AlignTop, FontPrimary);
|
||||
|
||||
auto line_1_text = container->add<StringElement>();
|
||||
auto line_2l_text = container->add<StringElement>();
|
||||
auto line_2r_text = container->add<StringElement>();
|
||||
auto line_3_text = container->add<StringElement>();
|
||||
|
||||
auto line_1_value = container->add<StringElement>();
|
||||
auto line_2l_value = container->add<StringElement>();
|
||||
auto line_2r_value = container->add<StringElement>();
|
||||
auto line_3_value = container->add<StringElement>();
|
||||
|
||||
const 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, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2l_text->set_text("Mod:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("ID:", 65, 47, 0, 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, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2l_value->set_text(
|
||||
string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_3_value->set_text(
|
||||
string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
break;
|
||||
case LfrfidKeyType::KeyH10301:
|
||||
case LfrfidKeyType::KeyI40134:
|
||||
line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2l_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("Card:", 65, 47, 0, 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, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2l_value->set_text(
|
||||
string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_3_value->set_text(
|
||||
string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
break;
|
||||
|
||||
case LfrfidKeyType::KeyIoProxXSF:
|
||||
line_1_text->set_text("HEX:", 65, 23, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2l_text->set_text("FC:", 65, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_2r_text->set_text("VС:", 95, 35, 0, AlignRight, AlignBottom, FontSecondary);
|
||||
line_3_text->set_text("Card:", 65, 47, 0, 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[2] << 8) | (data[3])));
|
||||
string_printf(string[3], "%u", data[1]);
|
||||
|
||||
line_1_value->set_text(
|
||||
string_get_cstr(string[0]), 68, 23, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2l_value->set_text(
|
||||
string_get_cstr(string[1]), 68, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_2r_value->set_text(
|
||||
string_get_cstr(string[3]), 98, 35, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
line_3_value->set_text(
|
||||
string_get_cstr(string[2]), 68, 47, 0, AlignLeft, AlignBottom, FontSecondary);
|
||||
|
||||
break;
|
||||
}
|
||||
auto text = container->add<StringElement>();
|
||||
text->set_text(string_get_cstr(string_info), 0, 16, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
|
||||
@@ -129,9 +77,8 @@ bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event
|
||||
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]);
|
||||
string_clear(string_info);
|
||||
string_clear(string_header);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneReadSuccess::back_callback(void* context) {
|
||||
|
@@ -11,5 +11,6 @@ private:
|
||||
static void back_callback(void* context);
|
||||
static void more_callback(void* context);
|
||||
|
||||
string_t string[3];
|
||||
string_t string_header;
|
||||
string_t string_info;
|
||||
};
|
||||
|
@@ -37,12 +37,13 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool result = false;
|
||||
if(arg && !emulating) {
|
||||
string_set_str(app->file_path, arg);
|
||||
if(app->load_key_data(app->file_path, &(app->worker.key), false)) {
|
||||
app->worker.start_emulate();
|
||||
if(app->load_key_data(app->file_path, false)) {
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
|
||||
emulating = true;
|
||||
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
app->text_store.set("emulating\n%s", app->worker.key.get_name());
|
||||
app->text_store.set("emulating\n%s", string_get_cstr(app->file_name));
|
||||
popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop);
|
||||
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
@@ -57,7 +58,8 @@ bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
|
||||
void LfRfidAppSceneRpc::on_exit(LfRfidApp* app) {
|
||||
if(emulating) {
|
||||
app->worker.stop_emulate();
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
}
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
|
@@ -3,31 +3,29 @@
|
||||
|
||||
void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto byte_input = app->view_controller.get<ByteInputVM>();
|
||||
RfidKey& key = app->worker.key;
|
||||
|
||||
if(need_restore) printf("restored\r\n");
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
|
||||
if(need_restore) {
|
||||
key.set_data(old_key_data, key.get_type_data_count());
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
} else {
|
||||
memcpy(old_key_data, key.get_data(), key.get_type_data_count());
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
|
||||
}
|
||||
|
||||
memcpy(new_key_data, key.get_data(), key.get_type_data_count());
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
|
||||
byte_input->set_header_text("Enter the data in hex");
|
||||
|
||||
byte_input->set_result_callback(
|
||||
save_callback, NULL, app, new_key_data, app->worker.key.get_type_data_count());
|
||||
byte_input->set_result_callback(save_callback, NULL, app, app->new_key_data, size);
|
||||
|
||||
app->view_controller.switch_to<ByteInputVM>();
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveData::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
RfidKey& key = app->worker.key;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
key.set_data(new_key_data, key.get_type_data_count());
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
|
||||
DOLPHIN_DEED(DolphinDeedRfidAdd);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
|
||||
}
|
||||
|
@@ -9,25 +9,4 @@ public:
|
||||
|
||||
private:
|
||||
static void save_callback(void* context);
|
||||
uint8_t old_key_data[LFRFID_KEY_SIZE] = {
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
0xAA,
|
||||
};
|
||||
|
||||
uint8_t new_key_data[LFRFID_KEY_SIZE] = {
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
0xBB,
|
||||
};
|
||||
};
|
||||
|
@@ -4,9 +4,9 @@
|
||||
#include <lib/toolbox/path.h>
|
||||
|
||||
void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
const char* key_name = app->worker.key.get_name();
|
||||
const char* key_name = string_get_cstr(app->file_name);
|
||||
|
||||
bool key_name_empty = !strcmp(key_name, "");
|
||||
bool key_name_empty = (string_size(app->file_name) == 0);
|
||||
if(key_name_empty) {
|
||||
string_set_str(app->file_path, app->app_folder);
|
||||
set_random_name(app->text_store.text, app->text_store.text_size);
|
||||
@@ -18,11 +18,7 @@ void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
text_input->set_header_text("Name the card");
|
||||
|
||||
text_input->set_result_callback(
|
||||
save_callback,
|
||||
app,
|
||||
app->text_store.text,
|
||||
app->worker.key.get_name_length(),
|
||||
key_name_empty);
|
||||
save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty);
|
||||
|
||||
string_t folder_path;
|
||||
string_init(folder_path);
|
||||
@@ -42,13 +38,13 @@ bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Next) {
|
||||
if(strlen(app->worker.key.get_name())) {
|
||||
app->delete_key(&app->worker.key);
|
||||
if(string_size(app->file_name) > 0) {
|
||||
app->delete_key();
|
||||
}
|
||||
|
||||
app->worker.key.set_name(app->text_store.text);
|
||||
string_set_str(app->file_name, app->text_store.text);
|
||||
|
||||
if(app->save_key(&app->worker.key)) {
|
||||
if(app->save_key()) {
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
|
||||
} else {
|
||||
app->scene_controller.search_and_switch_to_previous_scene(
|
||||
|
@@ -3,12 +3,12 @@
|
||||
void LfRfidAppSceneSaveType::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
auto submenu = app->view_controller.get<SubmenuVM>();
|
||||
|
||||
for(uint8_t i = 0; i <= keys_count; i++) {
|
||||
for(uint8_t i = 0; i < keys_count; i++) {
|
||||
string_init_printf(
|
||||
submenu_name[i],
|
||||
"%s %s",
|
||||
lfrfid_key_get_manufacturer_string(static_cast<LfrfidKeyType>(i)),
|
||||
lfrfid_key_get_type_string(static_cast<LfrfidKeyType>(i)));
|
||||
protocol_dict_get_manufacturer(app->dict, i),
|
||||
protocol_dict_get_name(app->dict, i));
|
||||
submenu->add_item(string_get_cstr(submenu_name[i]), i, submenu_callback, app);
|
||||
}
|
||||
|
||||
@@ -19,15 +19,15 @@ void LfRfidAppSceneSaveType::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
|
||||
// clear key name
|
||||
app->worker.key.set_name("");
|
||||
string_reset(app->file_name);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneSaveType::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.menu_index;
|
||||
app->worker.key.set_type(static_cast<LfrfidKeyType>(event->payload.menu_index));
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
app->protocol_id = event->payload.signed_int;
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData);
|
||||
consumed = true;
|
||||
}
|
||||
@@ -37,7 +37,7 @@ bool LfRfidAppSceneSaveType::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
|
||||
void LfRfidAppSceneSaveType::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<SubmenuVM>()->clean();
|
||||
for(uint8_t i = 0; i <= keys_count; i++) {
|
||||
for(uint8_t i = 0; i < keys_count; i++) {
|
||||
string_clear(submenu_name[i]);
|
||||
}
|
||||
}
|
||||
@@ -47,7 +47,7 @@ void LfRfidAppSceneSaveType::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
@@ -10,6 +10,6 @@ public:
|
||||
private:
|
||||
static void submenu_callback(void* context, uint32_t index);
|
||||
uint32_t submenu_item_selected = 0;
|
||||
static const uint8_t keys_count = static_cast<uint8_t>(LfrfidKeyType::KeyIoProxXSF);
|
||||
string_t submenu_name[keys_count + 1];
|
||||
static const uint8_t keys_count = static_cast<uint8_t>(LFRFIDProtocol::LFRFIDProtocolMax);
|
||||
string_t submenu_name[keys_count];
|
||||
};
|
||||
|
@@ -4,65 +4,36 @@
|
||||
#include "../view/elements/string_element.h"
|
||||
|
||||
void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
string_init(string_data);
|
||||
string_init(string_decrypted);
|
||||
string_init(string_info);
|
||||
|
||||
string_printf(
|
||||
string_info,
|
||||
"%s [%s]\r\n",
|
||||
string_get_cstr(app->file_name),
|
||||
protocol_dict_get_name(app->dict, app->protocol_id));
|
||||
|
||||
size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
|
||||
uint8_t* data = (uint8_t*)malloc(size);
|
||||
protocol_dict_get_data(app->dict, app->protocol_id, data, size);
|
||||
for(uint8_t i = 0; i < size; i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_info, " ");
|
||||
}
|
||||
|
||||
string_cat_printf(string_info, "%02X", data[i]);
|
||||
}
|
||||
free(data);
|
||||
|
||||
string_t render_data;
|
||||
string_init(render_data);
|
||||
protocol_dict_render_data(app->dict, render_data, app->protocol_id);
|
||||
string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
|
||||
string_clear(render_data);
|
||||
|
||||
auto container = app->view_controller.get<ContainerVM>();
|
||||
|
||||
auto button = container->add<ButtonElement>();
|
||||
button->set_type(ButtonElement::Type::Left, "Back");
|
||||
button->set_callback(app, LfRfidAppSceneSavedInfo::back_callback);
|
||||
|
||||
auto line_1 = container->add<StringElement>();
|
||||
auto line_2 = container->add<StringElement>();
|
||||
auto line_3 = container->add<StringElement>();
|
||||
auto line_4 = container->add<StringElement>();
|
||||
|
||||
RfidKey& key = app->worker.key;
|
||||
const uint8_t* data = key.get_data();
|
||||
|
||||
for(uint8_t i = 0; i < key.get_type_data_count(); i++) {
|
||||
if(i != 0) {
|
||||
string_cat_printf(string_data, " ");
|
||||
}
|
||||
string_cat_printf(string_data, "%02X", data[i]);
|
||||
}
|
||||
|
||||
line_1->set_text(key.get_name(), 64, 17, 128 - 2, AlignCenter, AlignBottom, FontSecondary);
|
||||
line_2->set_text(
|
||||
string_get_cstr(string_data), 64, 29, 0, AlignCenter, AlignBottom, FontPrimary);
|
||||
|
||||
switch(key.get_type()) {
|
||||
case LfrfidKeyType::KeyEM4100:
|
||||
string_printf(
|
||||
string_decrypted, "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4])));
|
||||
|
||||
break;
|
||||
case LfrfidKeyType::KeyH10301:
|
||||
case LfrfidKeyType::KeyI40134:
|
||||
string_printf(
|
||||
string_decrypted, "FC: %u ID: %u", data[0], (uint16_t)((data[1] << 8) | (data[2])));
|
||||
break;
|
||||
case LfrfidKeyType::KeyIoProxXSF:
|
||||
string_printf(
|
||||
string_decrypted,
|
||||
"FC: %u VC: %u ID: %u",
|
||||
data[0],
|
||||
data[1],
|
||||
(uint16_t)((data[2] << 8) | (data[3])));
|
||||
break;
|
||||
}
|
||||
line_3->set_text(
|
||||
string_get_cstr(string_decrypted), 64, 39, 0, AlignCenter, AlignBottom, FontSecondary);
|
||||
|
||||
line_4->set_text(
|
||||
lfrfid_key_get_type_string(key.get_type()),
|
||||
64,
|
||||
49,
|
||||
0,
|
||||
AlignCenter,
|
||||
AlignBottom,
|
||||
FontSecondary);
|
||||
line_1->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
|
||||
|
||||
app->view_controller.switch_to<ContainerVM>();
|
||||
}
|
||||
@@ -73,13 +44,5 @@ bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /
|
||||
|
||||
void LfRfidAppSceneSavedInfo::on_exit(LfRfidApp* app) {
|
||||
app->view_controller.get<ContainerVM>()->clean();
|
||||
string_clear(string_data);
|
||||
string_clear(string_decrypted);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneSavedInfo::back_callback(void* context) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(context);
|
||||
LfRfidApp::Event event;
|
||||
event.type = LfRfidApp::EventType::Back;
|
||||
app->view_controller.send_event(&event);
|
||||
string_clear(string_info);
|
||||
}
|
||||
|
@@ -8,8 +8,5 @@ public:
|
||||
void on_exit(LfRfidApp* app) final;
|
||||
|
||||
private:
|
||||
static void back_callback(void* context);
|
||||
|
||||
string_t string_data;
|
||||
string_t string_decrypted;
|
||||
string_t string_info;
|
||||
};
|
||||
|
@@ -28,8 +28,8 @@ bool LfRfidAppSceneSavedKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* even
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.menu_index;
|
||||
switch(event->payload.menu_index) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuEmulate:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
|
||||
break;
|
||||
@@ -61,7 +61,7 @@ void LfRfidAppSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index)
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
@@ -4,6 +4,7 @@ typedef enum {
|
||||
SubmenuRead,
|
||||
SubmenuSaved,
|
||||
SubmenuAddManually,
|
||||
SubmenuExtraActions,
|
||||
} SubmenuIndex;
|
||||
|
||||
void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
@@ -12,6 +13,7 @@ void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
submenu->add_item("Read", SubmenuRead, submenu_callback, app);
|
||||
submenu->add_item("Saved", SubmenuSaved, submenu_callback, app);
|
||||
submenu->add_item("Add Manually", SubmenuAddManually, submenu_callback, app);
|
||||
submenu->add_item("Extra Actions", SubmenuExtraActions, submenu_callback, app);
|
||||
|
||||
if(need_restore) {
|
||||
submenu->set_selected_item(submenu_item_selected);
|
||||
@@ -20,15 +22,17 @@ void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) {
|
||||
app->view_controller.switch_to<SubmenuVM>();
|
||||
|
||||
// clear key
|
||||
app->worker.key.clear();
|
||||
string_reset(app->file_name);
|
||||
app->protocol_id = PROTOCOL_NO;
|
||||
app->read_type = LFRFIDWorkerReadTypeAuto;
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneStart::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
|
||||
if(event->type == LfRfidApp::EventType::MenuSelected) {
|
||||
submenu_item_selected = event->payload.menu_index;
|
||||
switch(event->payload.menu_index) {
|
||||
submenu_item_selected = event->payload.signed_int;
|
||||
switch(event->payload.signed_int) {
|
||||
case SubmenuRead:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
|
||||
break;
|
||||
@@ -38,6 +42,9 @@ bool LfRfidAppSceneStart::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
case SubmenuAddManually:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveType);
|
||||
break;
|
||||
case SubmenuExtraActions:
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ExtraActions);
|
||||
break;
|
||||
}
|
||||
consumed = true;
|
||||
}
|
||||
@@ -54,7 +61,7 @@ void LfRfidAppSceneStart::submenu_callback(void* context, uint32_t index) {
|
||||
LfRfidApp::Event event;
|
||||
|
||||
event.type = LfRfidApp::EventType::MenuSelected;
|
||||
event.payload.menu_index = index;
|
||||
event.payload.signed_int = index;
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
@@ -1,66 +1,79 @@
|
||||
#include "lfrfid_app_scene_write.h"
|
||||
|
||||
void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
card_not_supported = false;
|
||||
string_init(data_string);
|
||||
static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* ctx) {
|
||||
LfRfidApp* app = static_cast<LfRfidApp*>(ctx);
|
||||
LfRfidApp::Event event;
|
||||
|
||||
const 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]);
|
||||
switch(result) {
|
||||
case LFRFIDWorkerWriteOK:
|
||||
event.type = LfRfidApp::EventType::WriteEventOK;
|
||||
break;
|
||||
case LFRFIDWorkerWriteProtocolCannotBeWritten:
|
||||
event.type = LfRfidApp::EventType::WriteEventProtocolCannotBeWritten;
|
||||
break;
|
||||
case LFRFIDWorkerWriteFobCannotBeWritten:
|
||||
event.type = LfRfidApp::EventType::WriteEventFobCannotBeWritten;
|
||||
break;
|
||||
case LFRFIDWorkerWriteTooLongToWrite:
|
||||
event.type = LfRfidApp::EventType::WriteEventTooLongToWrite;
|
||||
break;
|
||||
}
|
||||
|
||||
app->view_controller.send_event(&event);
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
popup->set_header("Writing", 89, 30, AlignCenter, AlignTop);
|
||||
if(strlen(app->worker.key.get_name())) {
|
||||
popup->set_text(app->worker.key.get_name(), 89, 43, AlignCenter, AlignTop);
|
||||
if(string_size(app->file_name)) {
|
||||
popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
|
||||
} else {
|
||||
popup->set_text(string_get_cstr(data_string), 89, 43, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
|
||||
}
|
||||
popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
|
||||
|
||||
app->view_controller.switch_to<PopupVM>();
|
||||
app->worker.start_write();
|
||||
lfrfid_worker_start_thread(app->lfworker);
|
||||
lfrfid_worker_write_start(
|
||||
app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app);
|
||||
notification_message(app->notification, &sequence_blink_start_magenta);
|
||||
}
|
||||
|
||||
bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
|
||||
bool consumed = false;
|
||||
bool consumed = true;
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
|
||||
if(event->type == LfRfidApp::EventType::Tick) {
|
||||
RfidWorker::WriteResult result = app->worker.write();
|
||||
|
||||
switch(result) {
|
||||
case RfidWorker::WriteResult::Nothing:
|
||||
notification_message(app->notification, &sequence_blink_magenta_10);
|
||||
break;
|
||||
case RfidWorker::WriteResult::Ok:
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::WriteSuccess);
|
||||
break;
|
||||
case RfidWorker::WriteResult::NotWritable:
|
||||
if(!card_not_supported) {
|
||||
auto popup = app->view_controller.get<PopupVM>();
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
"Make sure this\ncard is writable\nand not\nprotected.",
|
||||
3,
|
||||
17,
|
||||
AlignLeft,
|
||||
AlignTop);
|
||||
card_not_supported = true;
|
||||
}
|
||||
notification_message(app->notification, &sequence_blink_yellow_10);
|
||||
break;
|
||||
}
|
||||
switch(event->type) {
|
||||
case LfRfidApp::EventType::WriteEventOK:
|
||||
notification_message(app->notification, &sequence_success);
|
||||
app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::WriteSuccess);
|
||||
break;
|
||||
case LfRfidApp::EventType::WriteEventProtocolCannotBeWritten:
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Error", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text("This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_red);
|
||||
break;
|
||||
case LfRfidApp::EventType::WriteEventFobCannotBeWritten:
|
||||
case LfRfidApp::EventType::WriteEventTooLongToWrite:
|
||||
popup->set_icon(72, 17, &I_DolphinCommon_56x48);
|
||||
popup->set_header("Still trying to write...", 64, 3, AlignCenter, AlignTop);
|
||||
popup->set_text(
|
||||
"Make sure this\ncard is writable\nand not\nprotected.", 3, 17, AlignLeft, AlignTop);
|
||||
notification_message(app->notification, &sequence_blink_start_yellow);
|
||||
break;
|
||||
default:
|
||||
consumed = false;
|
||||
}
|
||||
|
||||
return consumed;
|
||||
}
|
||||
|
||||
void LfRfidAppSceneWrite::on_exit(LfRfidApp* app) {
|
||||
notification_message(app->notification, &sequence_blink_stop);
|
||||
app->view_controller.get<PopupVM>()->clean();
|
||||
app->worker.stop_write();
|
||||
string_clear(data_string);
|
||||
lfrfid_worker_stop(app->lfworker);
|
||||
lfrfid_worker_stop_thread(app->lfworker);
|
||||
}
|
||||
|
@@ -6,8 +6,4 @@ 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;
|
||||
bool card_not_supported;
|
||||
};
|
||||
|
Reference in New Issue
Block a user