[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:
SG
2022-08-24 01:57:39 +10:00
committed by GitHub
parent f92127c0a7
commit 9bfb641d3e
179 changed files with 10234 additions and 4804 deletions

View File

@@ -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);
}

View File

@@ -13,5 +13,4 @@ private:
string_t string_header;
string_t string_data;
string_t string_decrypted;
};

View File

@@ -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);
}

View File

@@ -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;
};

View 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);
}

View 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;
};

View 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);
}

View 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;
};

View 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);
}

View 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);
};

View 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);
}

View 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;
};

View 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);
}

View 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);
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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) {

View File

@@ -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;
};

View File

@@ -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();

View File

@@ -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);
}

View File

@@ -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,
};
};

View File

@@ -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(

View File

@@ -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);
}

View File

@@ -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];
};

View File

@@ -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);
}

View File

@@ -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;
};

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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;
};