diff --git a/.drone.yml b/.drone.yml
index 15c5dfce1..9bcb35546 100644
--- a/.drone.yml
+++ b/.drone.yml
@@ -36,6 +36,7 @@ steps:
- mkdir -p sd-card/nfc/assets
- mkdir -p sd-card/infrared/assets
- mkdir -p sd-card/unirf
+ - mkdir -p sd-card/rfidfuzzer
- mkdir -p sd-card/badusb/layouts
- cp assets/resources/badusb/layouts/* sd-card/badusb/layouts/
- cp assets/resources/subghz/assets/dangerous_settings sd-card/subghz/assets/dangerous_settings
@@ -44,9 +45,11 @@ steps:
- cp assets/resources/nfc/assets/mf_classic_dict.nfc sd-card/nfc/assets/mf_classic_dict.nfc
- cp assets/resources/infrared/assets/tv.ir sd-card/infrared/assets/tv.ir
- cp assets/resources/infrared/assets/ac.ir sd-card/infrared/assets/ac.ir
+ - cp assets/resources/infrared/assets/fans.ir sd-card/infrared/assets/fans.ir
- cp assets/resources/infrared/assets/projectors.ir sd-card/infrared/assets/projectors.ir
- cp assets/resources/infrared/assets/audio.ir sd-card/infrared/assets/audio.ir
- cp assets/resources/unirf/unirf_map_example.txt sd-card/unirf/unirf_map_example.txt
+ - cp assets/resources/rfidfuzzer/example_uids.txt sd-card/rfidfuzzer/example_uids.txt
- cp assets/resources/Manifest sd-card/Manifest
- zip -r artifacts-default/sd-card-${DRONE_TAG}.zip sd-card
- rm -rf sd-card
@@ -115,9 +118,7 @@ steps:
[-Install via Web Updater-](https://my.flipp.dev/?url=https://unleashedflip.com/builds/flipper-z-f7-update-${DRONE_TAG}.tgz&channel=dev-cfw&version=${DRONE_TAG})"
document:
- - artifacts-default/flipper-z-f7-full-${DRONE_TAG}.dfu
- - artifacts-default/flipper-z-f7-update-${DRONE_TAG}.zip
- - artifacts-default/sd-card-${DRONE_TAG}.zip
+ - artifacts-default/flipper-z-f7-update-${DRONE_TAG}.tgz
- name: "Send discord notification"
image: appleboy/drone-discord
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 64ed851a2..6c404d929 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,24 +1,10 @@
### New changes
-* New universal remote for projectors
-* OFW: New LF-RFID subsystem (New protocols, Animal tags support)
-* Updated universal remote assets (by @Amec0e)
-* Renamed UniRF Remix -> Sub-GHz Remote
-* Replaced Hex/Dec converter with Multi Converter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
-* New update screen, readme pictures (by @Svaarich)
-* Fixed crash if Center button is pressed on the "update success" screen via screensharing
-* Temporary disabled one log call in picopass plugin to fix crash/freeze on Read screen
-* OFW: Picopass load/info/delete
-* OFW: SubGhz: add protocol Magellen
-* OFW: Fix mifare ultralight/ntag unlock
-* OFW: Dolphin level thresholds update
-* OFW: Add MFC 1/4K 4/7bUID to "Add Manually"
-* OFW: Other fixes and changes
+* Actually fix universal tv remote
+* bt and lfrfid tune debug apps excluded from releases
-**Note: Prefer installing using web updater or by self update package, all needed assets will be installed**
+**Note: To avoid issues prefer installing using web updater or by self update package, all needed assets will be installed**
-**Build naming has been changed - all same as before but `cg - codegrabber` changed to `un - unleashed`**
-
-Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip`
+Self-update package (update from microSD) - `flipper-z-f7-update-(version).zip` or `.tgz` for iOS mobile app
DFU for update using qFlipper - `flipper-z-f7-full-(version).dfu`
diff --git a/ReadMe.md b/ReadMe.md
index b9cc9e257..c555e734c 100644
--- a/ReadMe.md
+++ b/ReadMe.md
@@ -4,10 +4,10 @@
-Welcome to Flipper Zero's Custom Firmware repo!
+### Welcome to Flipper Zero Unleashed Firmware repo!
Our goal is to make any features possible in this device without any limitations!
-Please help us implement emulation for all subghz dynamic (rolling code) protocols and static code brute-force app!
+Please help us implement emulation for all subghz dynamic (rolling code) protocols!
@@ -27,25 +27,26 @@ Our Discord Community:
* SubGHz frequecy range can be extended in settings file (Warning: It can damage flipper's hardware)
* Many rolling code protocols now have the ability to save & send captured signals
* FAAC SLH (Spa) & BFT Mitto (secure with seed) manual creation
+* Sub-GHz static code brute-force plugin
+* LFRFID Fuzzer plugin
* Custom community plugins and games added
* Extra SubGHz frequencies + extra Mifare Classic keys
* Picopass/iClass plugin included in releases
* Recompiled IR TV Universal Remote for ALL buttons
-* Universal A/C and Audio(soundbars, etc.) remote
-* Universal remote for Projectors
+* Universal remote for Projectors, Fans, A/Cs and Audio(soundbars, etc.)
* BadUSB keyboard layouts
* Customizable Flipper name
* Other small fixes and changes throughout
See changelog in releases for latest updates!
-### Current modified and new SubGhz protocols list:
+### Current modified and new SubGHz protocols list:
- HCS101
- An-Motors
- CAME Atomo
-- FAAC SLH (Spa) [if cloning existing remote - external seed calculation required]
-- BFT Mitto [if cloning existing remote - external seed calculation required]
-- Keeloq (+ proper manufacturer codes selection) [Not ALL systems supported yet!]
+- FAAC SLH (Spa) [External seed calculation required]
+- BFT Mitto [External seed calculation required]
+- Keeloq [Not ALL systems supported yet!]
- Nice Flor S
- Security+ v1 & v2
- Star Line
@@ -56,10 +57,10 @@ See changelog in releases for latest updates!
* DOGE: `D6R6gYgBn5LwTNmPyvAQR6bZ9EtGgFCpvv`
* LTC: `ltc1q3ex4ejkl0xpx3znwrmth4lyuadr5qgv8tmq8z9`
-**Big thanks to all sponsors!**
-
### Community apps included:
+- RFID Fuzzer plugin [(by Ganapati)](https://github.com/Eng1n33r/flipperzero-firmware/pull/54) with some changes by xMasterX
+- Sub-GHz bruteforce plugin [(by Ganapati & xMasterX)](https://github.com/Eng1n33r/flipperzero-firmware/pull/57)
- ESP8266 Deauther plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-Wifi-ESP8266-Deauther-Module)
- WiFi Scanner plugin [(by SequoiaSan)](https://github.com/SequoiaSan/FlipperZero-WiFi-Scanner_Module)
- MultiConverter plugin [(by theisolinearchip)](https://github.com/theisolinearchip/flipperzero_stuff)
@@ -68,8 +69,8 @@ See changelog in releases for latest updates!
- GPIO: Sentry Safe plugin [(by H4ckd4ddy)](https://github.com/H4ckd4ddy/flipperzero-sentry-safe-plugin)
- ESP32: WiFi Marauder companion plugin [(by 0xchocolate)](https://github.com/0xchocolate/flipperzero-firmware-with-wifi-marauder-companion)
- NRF24: Sniffer & MouseJacker (with changes) [(by mothball187)](https://github.com/mothball187/flipperzero-nrf24/tree/main/mousejacker)
-- Simple Clock (fixed) !! New version WIP, wait for updates !! [(Original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
-- UniversalRF Remix (with changes)(only RAW subghz files) [(by ESurge)(Original UniversalRF by jimilinuxguy)](https://github.com/ESurge/flipperzero-firmware-unirfremix)
+- Simple Clock (fixed) [(Original by CompaqDisc)](https://gist.github.com/CompaqDisc/4e329c501bd03c1e801849b81f48ea61)
+- UniversalRF Remix / Sub-GHz Remote [(by ESurge)](https://github.com/ESurge/flipperzero-firmware-unirfremix)[(updated and all protocol support added by darmiel & xMasterX)](https://github.com/darmiel/flipper-playlist/tree/feat/unirf-protocols)
- Tetris (with fixes) [(by jeffplang)](https://github.com/jeffplang/flipperzero-firmware/tree/tetris_game/applications/tetris_game)
- Spectrum Analyzer (with changes) [(by jolcese)](https://github.com/jolcese/flipperzero-firmware/tree/spectrum/applications/spectrum_analyzer) - [Ultra Narrow mode & scan channels non-consecutively](https://github.com/theY4Kman/flipperzero-firmware/commits?author=theY4Kman)
- Arkanoid (with fixes) [(by gotnull)](https://github.com/gotnull/flipperzero-firmware-wPlugins)
diff --git a/SConstruct b/SConstruct
index 52fe75a6a..4462f2f30 100644
--- a/SConstruct
+++ b/SConstruct
@@ -1,5 +1,5 @@
#
-# Main Fipper Build System entry point
+# Main Flipper Build System entry point
#
# This file is evaluated by scons (the build system) every time fbt is invoked.
# Scons constructs all referenced environments & their targets' dependency
@@ -15,7 +15,7 @@ DefaultEnvironment(tools=[])
# Progress(["OwO\r", "owo\r", "uwu\r", "owo\r"], interval=15)
-# This environment is created only for loading options & validating file/dir existance
+# This environment is created only for loading options & validating file/dir existence
fbt_variables = SConscript("site_scons/commandline.scons")
cmd_environment = Environment(tools=[], variables=fbt_variables)
Help(fbt_variables.GenerateHelpText(cmd_environment))
diff --git a/applications/bad_usb/views/bad_usb_view.h b/applications/bad_usb/views/bad_usb_view.h
old mode 100755
new mode 100644
diff --git a/applications/bt/application.fam b/applications/bt/application.fam
index 248386ff3..1d276d019 100644
--- a/applications/bt/application.fam
+++ b/applications/bt/application.fam
@@ -11,7 +11,7 @@ App(
provides=[
"bt_start",
"bt_settings",
- "bt_debug",
+ #"bt_debug",
],
stack_size=1 * 1024,
order=20,
diff --git a/applications/bt/bt_debug_app/views/bt_carrier_test.c b/applications/bt/bt_debug_app/views/bt_carrier_test.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_debug_app/views/bt_test.c b/applications/bt/bt_debug_app/views/bt_test.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_debug_app/views/bt_test.h b/applications/bt/bt_debug_app/views/bt_test.h
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_hid_app/views/bt_hid_keynote.c b/applications/bt/bt_hid_app/views/bt_hid_keynote.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_hid_app/views/bt_hid_media.c b/applications/bt/bt_hid_app/views/bt_hid_media.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/bt_settings_app.c b/applications/bt/bt_settings_app/bt_settings_app.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/bt_settings_app.h b/applications/bt/bt_settings_app/bt_settings_app.h
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h b/applications/bt/bt_settings_app/scenes/bt_settings_scene_config.h
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_confirm.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_forget_dev_success.c
old mode 100755
new mode 100644
diff --git a/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c b/applications/bt/bt_settings_app/scenes/bt_settings_scene_start.c
old mode 100755
new mode 100644
diff --git a/applications/cli/cli_commands.c b/applications/cli/cli_commands.c
index 177a274a1..a6dd672fc 100644
--- a/applications/cli/cli_commands.c
+++ b/applications/cli/cli_commands.c
@@ -281,6 +281,9 @@ void cli_command_free(Cli* cli, string_t args, void* context) {
printf("Total heap size: %d\r\n", memmgr_get_total_heap());
printf("Minimum heap size: %d\r\n", memmgr_get_minimum_free_heap());
printf("Maximum heap block: %d\r\n", memmgr_heap_get_max_free_block());
+
+ printf("Pool free: %d\r\n", memmgr_pool_get_free());
+ printf("Maximum pool block: %d\r\n", memmgr_pool_get_max_block());
}
void cli_command_free_blocks(Cli* cli, string_t args, void* context) {
diff --git a/applications/cli/cli_i.h b/applications/cli/cli_i.h
old mode 100755
new mode 100644
diff --git a/applications/debug_tools/application.fam b/applications/debug_tools/application.fam
index 8cb495b0c..701115241 100644
--- a/applications/debug_tools/application.fam
+++ b/applications/debug_tools/application.fam
@@ -15,6 +15,16 @@ App(
],
)
+App(
+ appid="debug_apps_lite",
+ name="Basic debug apps bundle",
+ apptype=FlipperAppType.METAPACKAGE,
+ provides=[
+ "usb_mouse",
+ "uart_echo",
+ ],
+)
+
App(
appid="blink_test",
name="Blink Test",
diff --git a/applications/desktop/desktop_settings/desktop_settings.h b/applications/desktop/desktop_settings/desktop_settings.h
index 800847d56..c33aadb76 100644
--- a/applications/desktop/desktop_settings/desktop_settings.h
+++ b/applications/desktop/desktop_settings/desktop_settings.h
@@ -46,4 +46,5 @@ typedef struct {
PinCode pin_code;
uint8_t is_locked;
uint32_t auto_lock_delay_ms;
+ uint8_t displayBatteryPercentage;
} DesktopSettings;
diff --git a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c
index aaaf2e779..d3c3aa072 100644
--- a/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c
+++ b/applications/desktop/desktop_settings/scenes/desktop_settings_scene_start.c
@@ -8,6 +8,7 @@
#define SCENE_EVENT_SELECT_FAVORITE_SECONDARY 1
#define SCENE_EVENT_SELECT_PIN_SETUP 2
#define SCENE_EVENT_SELECT_AUTO_LOCK_DELAY 3
+#define SCENE_EVENT_SELECT_BATTERY_DISPLAY 4
#define AUTO_LOCK_DELAY_COUNT 9
const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
@@ -25,11 +26,31 @@ const char* const auto_lock_delay_text[AUTO_LOCK_DELAY_COUNT] = {
const uint32_t auto_lock_delay_value[AUTO_LOCK_DELAY_COUNT] =
{0, 10000, 15000, 30000, 60000, 90000, 120000, 300000, 600000};
+#define BATTERY_VIEW_COUNT 5
+
+const char* const battery_view_count_text[BATTERY_VIEW_COUNT] = {
+ "Bar",
+ "%",
+ "Inv. %",
+ "Retro 3",
+ "Retro 5",
+};
+
+const uint32_t displayBatteryPercentage_value[BATTERY_VIEW_COUNT] = {0, 1, 2, 3, 4};
+
static void desktop_settings_scene_start_var_list_enter_callback(void* context, uint32_t index) {
DesktopSettingsApp* app = context;
view_dispatcher_send_custom_event(app->view_dispatcher, index);
}
+static void desktop_settings_scene_start_battery_view_changed(VariableItem* item) {
+ DesktopSettingsApp* app = variable_item_get_context(item);
+ uint8_t index = variable_item_get_current_value_index(item);
+
+ variable_item_set_current_value_text(item, battery_view_count_text[index]);
+ app->settings.displayBatteryPercentage = index;
+}
+
static void desktop_settings_scene_start_auto_lock_delay_changed(VariableItem* item) {
DesktopSettingsApp* app = variable_item_get_context(item);
uint8_t index = variable_item_get_current_value_index(item);
@@ -65,6 +86,20 @@ void desktop_settings_scene_start_on_enter(void* context) {
variable_item_set_current_value_index(item, value_index);
variable_item_set_current_value_text(item, auto_lock_delay_text[value_index]);
+ item = variable_item_list_add(
+ variable_item_list,
+ "Battery View",
+ BATTERY_VIEW_COUNT,
+ desktop_settings_scene_start_battery_view_changed,
+ app);
+
+ value_index = value_index_uint32(
+ app->settings.displayBatteryPercentage,
+ displayBatteryPercentage_value,
+ BATTERY_VIEW_COUNT);
+ variable_item_set_current_value_index(item, value_index);
+ variable_item_set_current_value_text(item, battery_view_count_text[value_index]);
+
view_dispatcher_switch_to_view(app->view_dispatcher, DesktopSettingsAppViewVarItemList);
}
@@ -91,6 +126,9 @@ bool desktop_settings_scene_start_on_event(void* context, SceneManagerEvent even
case SCENE_EVENT_SELECT_AUTO_LOCK_DELAY:
consumed = true;
break;
+ case SCENE_EVENT_SELECT_BATTERY_DISPLAY:
+ consumed = true;
+ break;
}
}
return consumed;
diff --git a/applications/desktop/views/desktop_view_main.c b/applications/desktop/views/desktop_view_main.c
index a3aa63707..397011a43 100644
--- a/applications/desktop/views/desktop_view_main.c
+++ b/applications/desktop/views/desktop_view_main.c
@@ -16,7 +16,7 @@ struct DesktopMainView {
TimerHandle_t poweroff_timer;
};
-#define DESKTOP_MAIN_VIEW_POWEROFF_TIMEOUT 3000
+#define DESKTOP_MAIN_VIEW_POWEROFF_TIMEOUT 2000
static void desktop_main_poweroff_timer_callback(TimerHandle_t timer) {
DesktopMainView* main_view = pvTimerGetTimerID(timer);
diff --git a/applications/flipfrid/LICENSE.md b/applications/flipfrid/LICENSE.md
new file mode 100644
index 000000000..a856581c9
--- /dev/null
+++ b/applications/flipfrid/LICENSE.md
@@ -0,0 +1,8 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * @G4N4P4T1 wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return.
+ * ----------------------------------------------------------------------------
+ */
\ No newline at end of file
diff --git a/applications/flipfrid/README.md b/applications/flipfrid/README.md
new file mode 100644
index 000000000..51ed2fa67
--- /dev/null
+++ b/applications/flipfrid/README.md
@@ -0,0 +1,21 @@
+# Flipfrid
+
+Basic EM4100 Fuzzer
+
+## Why
+
+Flipfrid is a simple Rfid fuzzer using EM4100 protocol (125khz).
+Objective is to provide a simple to use fuzzer to test readers by emulating various cards.
+
+EM4100 cards use a 1 byte customer id and 4 bytes card id.
+
+## How
+
+There is 4 modes :
+- Default key loop over 16 factory/default keys and emulate each one after one ;
+- BF customer id. just an iteration from 0X00 to 0XFF on the first byte ;
+- Load Dump file : Load an existing EM4100 dump generated by Flipperzero, select an index and bruteforce from 0X00 to 0XFF;
+- Uids list: loop over a text file (one uid per line)
+
+TODO :
+- blank screen on back press
diff --git a/applications/flipfrid/application.fam b/applications/flipfrid/application.fam
new file mode 100644
index 000000000..4bcb38139
--- /dev/null
+++ b/applications/flipfrid/application.fam
@@ -0,0 +1,10 @@
+App(
+ appid="flipfrid",
+ name="RFID Fuzzer",
+ apptype=FlipperAppType.PLUGIN,
+ entry_point="flipfrid_start",
+ cdefines=["APP_FLIP_FRID"],
+ requires=["gui"],
+ stack_size=1 * 1024,
+ order=13,
+)
diff --git a/applications/flipfrid/flipfrid.c b/applications/flipfrid/flipfrid.c
new file mode 100644
index 000000000..1dab3cae1
--- /dev/null
+++ b/applications/flipfrid/flipfrid.c
@@ -0,0 +1,258 @@
+#include "flipfrid.h"
+
+#include "scene/flipfrid_scene_entrypoint.h"
+#include "scene/flipfrid_scene_load_file.h"
+#include "scene/flipfrid_scene_select_field.h"
+#include "scene/flipfrid_scene_run_attack.h"
+#include "scene/flipfrid_scene_load_custom_uids.h"
+
+#define RFIDFUZZER_APP_FOLDER "/ext/rfidfuzzer"
+
+static void flipfrid_draw_callback(Canvas* const canvas, void* ctx) {
+ FlipFridState* flipfrid_state = (FlipFridState*)acquire_mutex((ValueMutex*)ctx, 100);
+
+ if(flipfrid_state == NULL) {
+ return;
+ }
+
+ // Draw correct Canvas
+ switch(flipfrid_state->current_scene) {
+ case NoneScene:
+ case SceneEntryPoint:
+ flipfrid_scene_entrypoint_on_draw(canvas, flipfrid_state);
+ break;
+ case SceneSelectFile:
+ flipfrid_scene_load_file_on_draw(canvas, flipfrid_state);
+ break;
+ case SceneSelectField:
+ flipfrid_scene_select_field_on_draw(canvas, flipfrid_state);
+ break;
+ case SceneAttack:
+ flipfrid_scene_run_attack_on_draw(canvas, flipfrid_state);
+ break;
+ case SceneLoadCustomUids:
+ flipfrid_scene_load_custom_uids_on_draw(canvas, flipfrid_state);
+ break;
+ }
+
+ release_mutex((ValueMutex*)ctx, flipfrid_state);
+}
+
+void flipfrid_input_callback(InputEvent* input_event, FuriMessageQueue* event_queue) {
+ furi_assert(event_queue);
+
+ FlipFridEvent event = {
+ .evt_type = EventTypeKey, .key = input_event->key, .input_type = input_event->type};
+ furi_message_queue_put(event_queue, &event, 25);
+}
+
+static void flipfrid_timer_callback(FuriMessageQueue* event_queue) {
+ furi_assert(event_queue);
+ FlipFridEvent event = {
+ .evt_type = EventTypeTick, .key = InputKeyUp, .input_type = InputTypeRelease};
+ furi_message_queue_put(event_queue, &event, 25);
+}
+
+FlipFridState* flipfrid_alloc() {
+ FlipFridState* flipfrid = malloc(sizeof(FlipFridState));
+ string_init(flipfrid->notification_msg);
+ string_init(flipfrid->attack_name);
+
+ flipfrid->previous_scene = NoneScene;
+ flipfrid->current_scene = SceneEntryPoint;
+ flipfrid->is_running = true;
+ flipfrid->is_attacking = false;
+ flipfrid->key_index = 0;
+ flipfrid->menu_index = 0;
+
+ flipfrid->attack = FlipFridAttackDefaultValues;
+ flipfrid->notify = furi_record_open(RECORD_NOTIFICATION);
+
+ flipfrid->data[0] = 0x00;
+ flipfrid->data[1] = 0x00;
+ flipfrid->data[2] = 0x00;
+ flipfrid->data[3] = 0x00;
+ flipfrid->data[4] = 0x00;
+
+ flipfrid->payload[0] = 0x00;
+ flipfrid->payload[1] = 0x00;
+ flipfrid->payload[2] = 0x00;
+ flipfrid->payload[3] = 0x00;
+ flipfrid->payload[4] = 0x00;
+
+ //Dialog
+ flipfrid->dialogs = furi_record_open(RECORD_DIALOGS);
+
+ return flipfrid;
+}
+
+void flipfrid_free(FlipFridState* flipfrid) {
+ //Dialog
+ furi_record_close(RECORD_DIALOGS);
+ notification_message(flipfrid->notify, &sequence_blink_stop);
+
+ // Strings
+ string_clear(flipfrid->notification_msg);
+ string_clear(flipfrid->attack_name);
+
+ free(flipfrid->data);
+ free(flipfrid->payload);
+
+ // The rest
+ free(flipfrid);
+}
+
+// ENTRYPOINT
+int32_t flipfrid_start(void* p) {
+ UNUSED(p);
+ // Input
+ FURI_LOG_I(TAG, "Initializing input");
+ FuriMessageQueue* event_queue = furi_message_queue_alloc(8, sizeof(FlipFridEvent));
+ FlipFridState* flipfrid_state = flipfrid_alloc();
+ ValueMutex flipfrid_state_mutex;
+
+ // Mutex
+ FURI_LOG_I(TAG, "Initializing flipfrid mutex");
+ if(!init_mutex(&flipfrid_state_mutex, flipfrid_state, sizeof(FlipFridState))) {
+ FURI_LOG_E(TAG, "cannot create mutex\r\n");
+ furi_message_queue_free(event_queue);
+ furi_record_close(RECORD_NOTIFICATION);
+ furi_record_close(RECORD_DIALOGS);
+ free(flipfrid_state);
+ return 255;
+ }
+
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ if(!storage_simply_mkdir(storage, RFIDFUZZER_APP_FOLDER)) {
+ FURI_LOG_E(TAG, "Could not create folder %s", RFIDFUZZER_APP_FOLDER);
+ }
+ furi_record_close(RECORD_STORAGE);
+
+ // Configure view port
+ FURI_LOG_I(TAG, "Initializing viewport");
+ ViewPort* view_port = view_port_alloc();
+ view_port_draw_callback_set(view_port, flipfrid_draw_callback, &flipfrid_state_mutex);
+ view_port_input_callback_set(view_port, flipfrid_input_callback, event_queue);
+
+ // Configure timer
+ FURI_LOG_I(TAG, "Initializing timer");
+ FuriTimer* timer =
+ furi_timer_alloc(flipfrid_timer_callback, FuriTimerTypePeriodic, event_queue);
+ furi_timer_start(timer, furi_kernel_get_tick_frequency() / 10); // 10 times per second
+
+ // Register view port in GUI
+ FURI_LOG_I(TAG, "Initializing gui");
+ Gui* gui = (Gui*)furi_record_open(RECORD_GUI);
+ gui_add_view_port(gui, view_port, GuiLayerFullscreen);
+
+ // Init values
+ FlipFridEvent event;
+ while(flipfrid_state->is_running) {
+ // Get next event
+ FuriStatus event_status = furi_message_queue_get(event_queue, &event, 25);
+ if(event_status == FuriStatusOk) {
+ if(event.evt_type == EventTypeKey) {
+ //Handle event key
+ switch(flipfrid_state->current_scene) {
+ case NoneScene:
+ case SceneEntryPoint:
+ flipfrid_scene_entrypoint_on_event(event, flipfrid_state);
+ break;
+ case SceneSelectFile:
+ flipfrid_scene_load_file_on_event(event, flipfrid_state);
+ break;
+ case SceneSelectField:
+ flipfrid_scene_select_field_on_event(event, flipfrid_state);
+ break;
+ case SceneAttack:
+ flipfrid_scene_run_attack_on_event(event, flipfrid_state);
+ break;
+ case SceneLoadCustomUids:
+ flipfrid_scene_load_custom_uids_on_event(event, flipfrid_state);
+ break;
+ }
+
+ } else if(event.evt_type == EventTypeTick) {
+ //Handle event tick
+ if(flipfrid_state->current_scene != flipfrid_state->previous_scene) {
+ // Trigger Exit Scene
+ switch(flipfrid_state->previous_scene) {
+ case SceneEntryPoint:
+ flipfrid_scene_entrypoint_on_exit(flipfrid_state);
+ break;
+ case SceneSelectFile:
+ flipfrid_scene_load_file_on_exit(flipfrid_state);
+ break;
+ case SceneSelectField:
+ flipfrid_scene_select_field_on_exit(flipfrid_state);
+ break;
+ case SceneAttack:
+ flipfrid_scene_run_attack_on_exit(flipfrid_state);
+ break;
+ case SceneLoadCustomUids:
+ flipfrid_scene_load_custom_uids_on_exit(flipfrid_state);
+ break;
+ case NoneScene:
+ break;
+ }
+
+ // Trigger Entry Scene
+ switch(flipfrid_state->current_scene) {
+ case NoneScene:
+ case SceneEntryPoint:
+ flipfrid_scene_entrypoint_on_enter(flipfrid_state);
+ break;
+ case SceneSelectFile:
+ flipfrid_scene_load_file_on_enter(flipfrid_state);
+ break;
+ case SceneSelectField:
+ flipfrid_scene_select_field_on_enter(flipfrid_state);
+ break;
+ case SceneAttack:
+ flipfrid_scene_run_attack_on_enter(flipfrid_state);
+ break;
+ case SceneLoadCustomUids:
+ flipfrid_scene_load_custom_uids_on_enter(flipfrid_state);
+ break;
+ }
+ flipfrid_state->previous_scene = flipfrid_state->current_scene;
+ }
+
+ // Trigger Tick Scene
+ switch(flipfrid_state->current_scene) {
+ case NoneScene:
+ case SceneEntryPoint:
+ flipfrid_scene_entrypoint_on_tick(flipfrid_state);
+ break;
+ case SceneSelectFile:
+ flipfrid_scene_load_file_on_tick(flipfrid_state);
+ break;
+ case SceneSelectField:
+ flipfrid_scene_select_field_on_tick(flipfrid_state);
+ break;
+ case SceneAttack:
+ flipfrid_scene_run_attack_on_tick(flipfrid_state);
+ break;
+ case SceneLoadCustomUids:
+ flipfrid_scene_load_custom_uids_on_tick(flipfrid_state);
+ break;
+ }
+ view_port_update(view_port);
+ }
+ }
+ }
+
+ // Cleanup
+ furi_timer_stop(timer);
+ furi_timer_free(timer);
+
+ FURI_LOG_I(TAG, "Cleaning up");
+ gui_remove_view_port(gui, view_port);
+ view_port_free(view_port);
+ furi_message_queue_free(event_queue);
+ furi_record_close(RECORD_GUI);
+ furi_record_close(RECORD_NOTIFICATION);
+ flipfrid_free(flipfrid_state);
+
+ return 0;
+}
\ No newline at end of file
diff --git a/applications/flipfrid/flipfrid.h b/applications/flipfrid/flipfrid.h
new file mode 100644
index 000000000..95bb2121d
--- /dev/null
+++ b/applications/flipfrid/flipfrid.h
@@ -0,0 +1,76 @@
+#pragma once
+#include
+#include
+#include
+#include
+#include
+#include "m-string.h"
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#define TAG "FlipFrid"
+
+typedef enum {
+ FlipFridAttackDefaultValues,
+ FlipFridAttackBfCustomerId,
+ FlipFridAttackLoadFile,
+ FlipFridAttackLoadFileCustomUids,
+} FlipFridAttacks;
+
+typedef enum {
+ NoneScene,
+ SceneEntryPoint,
+ SceneSelectFile,
+ SceneSelectField,
+ SceneAttack,
+ SceneLoadCustomUids,
+} FlipFridScene;
+
+typedef enum {
+ EventTypeTick,
+ EventTypeKey,
+} EventType;
+
+typedef struct {
+ EventType evt_type;
+ InputKey key;
+ InputType input_type;
+} FlipFridEvent;
+
+// STRUCTS
+typedef struct {
+ bool is_running;
+ bool is_attacking;
+ FlipFridScene current_scene;
+ FlipFridScene previous_scene;
+ NotificationApp* notify;
+ u_int8_t menu_index;
+
+ string_t data_str;
+ uint8_t data[5];
+ uint8_t payload[5];
+ uint8_t attack_step;
+ FlipFridAttacks attack;
+ string_t attack_name;
+
+ DialogsApp* dialogs;
+ string_t notification_msg;
+ uint8_t key_index;
+ LFRFIDWorker* worker;
+ ProtocolDict* dict;
+ ProtocolId protocol;
+
+ // Used for custom dictionnary
+ Stream* uids_stream;
+} FlipFridState;
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_entrypoint.c b/applications/flipfrid/scene/flipfrid_scene_entrypoint.c
new file mode 100644
index 000000000..f30bb8e1d
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_entrypoint.c
@@ -0,0 +1,123 @@
+#include "flipfrid_scene_entrypoint.h"
+
+string_t menu_items[4];
+
+void flipfrid_scene_entrypoint_menu_callback(FlipFridState* context, uint32_t index) {
+ switch(index) {
+ case FlipFridAttackDefaultValues:
+ context->attack = FlipFridAttackDefaultValues;
+ context->current_scene = SceneAttack;
+ string_set_str(context->attack_name, "Default Values");
+ break;
+ case FlipFridAttackBfCustomerId:
+ context->attack = FlipFridAttackBfCustomerId;
+ context->current_scene = SceneAttack;
+ string_set_str(context->attack_name, "Bad Customer ID");
+ break;
+ case FlipFridAttackLoadFile:
+ context->attack = FlipFridAttackLoadFile;
+ context->current_scene = SceneSelectFile;
+ string_set_str(context->attack_name, "Load File");
+ break;
+ case FlipFridAttackLoadFileCustomUids:
+ context->attack = FlipFridAttackLoadFileCustomUids;
+ context->current_scene = SceneLoadCustomUids;
+ string_set_str(context->attack_name, "Load Custom UIDs");
+ break;
+ default:
+ break;
+ }
+}
+
+void flipfrid_scene_entrypoint_on_enter(FlipFridState* context) {
+ // Clear the previous payload
+ context->payload[0] = 0x00;
+ context->payload[1] = 0x00;
+ context->payload[2] = 0x00;
+ context->payload[3] = 0x00;
+ context->payload[4] = 0x00;
+
+ context->menu_index = 0;
+ for(uint32_t i = 0; i < 4; i++) {
+ string_init(menu_items[i]);
+ }
+
+ string_set(menu_items[0], "Default Values");
+ string_set(menu_items[1], "BF Customer ID");
+ string_set(menu_items[2], "Load File");
+ string_set(menu_items[3], "Load uids from file");
+}
+
+void flipfrid_scene_entrypoint_on_exit(FlipFridState* context) {
+ UNUSED(context);
+ for(uint32_t i = 0; i < 4; i++) {
+ string_clear(menu_items[i]);
+ }
+}
+
+void flipfrid_scene_entrypoint_on_tick(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context) {
+ if(event.evt_type == EventTypeKey) {
+ if(event.input_type == InputTypeShort) {
+ switch(event.key) {
+ case InputKeyDown:
+ if(context->menu_index < FlipFridAttackLoadFileCustomUids) {
+ context->menu_index++;
+ }
+ break;
+ case InputKeyUp:
+ if(context->menu_index > FlipFridAttackDefaultValues) {
+ context->menu_index--;
+ }
+ break;
+ case InputKeyLeft:
+ case InputKeyRight:
+ break;
+ case InputKeyOk:
+ flipfrid_scene_entrypoint_menu_callback(context, context->menu_index);
+ break;
+ case InputKeyBack:
+ context->is_running = false;
+ break;
+ }
+ }
+ }
+}
+
+void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context) {
+ canvas_clear(canvas);
+ canvas_set_color(canvas, ColorBlack);
+
+ // Title
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str_aligned(canvas, 64, 6, AlignCenter, AlignTop, "RFID Fuzzer");
+
+ if(context->menu_index > FlipFridAttackDefaultValues) {
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_aligned(
+ canvas,
+ 64,
+ 24,
+ AlignCenter,
+ AlignTop,
+ string_get_cstr(menu_items[context->menu_index - 1]));
+ }
+
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str_aligned(
+ canvas, 64, 36, AlignCenter, AlignTop, string_get_cstr(menu_items[context->menu_index]));
+
+ if(context->menu_index < FlipFridAttackLoadFileCustomUids) {
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_aligned(
+ canvas,
+ 64,
+ 48,
+ AlignCenter,
+ AlignTop,
+ string_get_cstr(menu_items[context->menu_index + 1]));
+ }
+}
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_entrypoint.h b/applications/flipfrid/scene/flipfrid_scene_entrypoint.h
new file mode 100644
index 000000000..29ca5bdfa
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_entrypoint.h
@@ -0,0 +1,8 @@
+#pragma once
+#include "../flipfrid.h"
+
+void flipfrid_scene_entrypoint_on_enter(FlipFridState* context);
+void flipfrid_scene_entrypoint_on_exit(FlipFridState* context);
+void flipfrid_scene_entrypoint_on_tick(FlipFridState* context);
+void flipfrid_scene_entrypoint_on_event(FlipFridEvent event, FlipFridState* context);
+void flipfrid_scene_entrypoint_on_draw(Canvas* canvas, FlipFridState* context);
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.c b/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.c
new file mode 100644
index 000000000..bb3cf37d7
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.c
@@ -0,0 +1,79 @@
+#include "flipfrid_scene_load_custom_uids.h"
+#include "flipfrid_scene_run_attack.h"
+#include "flipfrid_scene_entrypoint.h"
+
+#define LFRFID_UIDS_EXTENSION ".txt"
+#define RFIDFUZZER_APP_PATH_FOLDER "/ext/rfidfuzzer"
+
+bool flipfrid_load_uids(FlipFridState* context, const char* file_path) {
+ bool result = false;
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ context->uids_stream = buffered_file_stream_alloc(storage);
+ result =
+ buffered_file_stream_open(context->uids_stream, file_path, FSAM_READ, FSOM_OPEN_EXISTING);
+ // Close if loading fails
+ if(!result) {
+ buffered_file_stream_close(context->uids_stream);
+ return false;
+ }
+ return result;
+}
+
+bool flipfrid_load_custom_uids_from_file(FlipFridState* context) {
+ // Input events and views are managed by file_select
+ string_t uid_path;
+ string_init(uid_path);
+ string_set_str(uid_path, RFIDFUZZER_APP_PATH_FOLDER);
+
+ bool res = dialog_file_browser_show(
+ context->dialogs, uid_path, uid_path, LFRFID_UIDS_EXTENSION, true, &I_125_10px, false);
+
+ if(res) {
+ res = flipfrid_load_uids(context, string_get_cstr(uid_path));
+ }
+
+ string_clear(uid_path);
+
+ return res;
+}
+
+void flipfrid_scene_load_custom_uids_on_enter(FlipFridState* context) {
+ if(flipfrid_load_custom_uids_from_file(context)) {
+ // Force context loading
+ flipfrid_scene_run_attack_on_enter(context);
+ context->current_scene = SceneAttack;
+ } else {
+ flipfrid_scene_entrypoint_on_enter(context);
+ context->current_scene = SceneEntryPoint;
+ }
+}
+
+void flipfrid_scene_load_custom_uids_on_exit(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_load_custom_uids_on_tick(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState* context) {
+ if(event.evt_type == EventTypeKey) {
+ if(event.input_type == InputTypeShort) {
+ switch(event.key) {
+ case InputKeyDown:
+ case InputKeyUp:
+ case InputKeyLeft:
+ case InputKeyRight:
+ case InputKeyOk:
+ case InputKeyBack:
+ context->current_scene = SceneEntryPoint;
+ break;
+ }
+ }
+ }
+}
+
+void flipfrid_scene_load_custom_uids_on_draw(Canvas* canvas, FlipFridState* context) {
+ UNUSED(context);
+ UNUSED(canvas);
+}
diff --git a/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.h b/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.h
new file mode 100644
index 000000000..a8ed982b6
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_load_custom_uids.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "../flipfrid.h"
+
+void flipfrid_scene_load_custom_uids_on_enter(FlipFridState* context);
+void flipfrid_scene_load_custom_uids_on_exit(FlipFridState* context);
+void flipfrid_scene_load_custom_uids_on_tick(FlipFridState* context);
+void flipfrid_scene_load_custom_uids_on_event(FlipFridEvent event, FlipFridState* context);
+void flipfrid_scene_load_custom_uids_on_draw(Canvas* canvas, FlipFridState* context);
+bool flipfrid_load_custom_uids_from_file(FlipFridState* context);
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_load_file.c b/applications/flipfrid/scene/flipfrid_scene_load_file.c
new file mode 100644
index 000000000..c4b1321d6
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_load_file.c
@@ -0,0 +1,146 @@
+#include "flipfrid_scene_load_file.h"
+#include "flipfrid_scene_entrypoint.h"
+
+#define LFRFID_APP_EXTENSION ".rfid"
+#define LFRFID_APP_PATH_FOLDER "/ext/lfrfid"
+
+bool flipfrid_load(FlipFridState* context, const char* file_path) {
+ bool result = false;
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ FlipperFormat* fff_data_file = flipper_format_file_alloc(storage);
+ string_t temp_str;
+ string_init(temp_str);
+ do {
+ if(!flipper_format_file_open_existing(fff_data_file, file_path)) {
+ FURI_LOG_E(TAG, "Error open file %s", file_path);
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Error open file");
+ break;
+ }
+
+ // FileType
+ if(!flipper_format_read_string(fff_data_file, "Filetype", temp_str)) {
+ FURI_LOG_E(TAG, "Missing or incorrect Filetype");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Missing or incorrect Filetypes");
+ break;
+ } else {
+ FURI_LOG_I(TAG, "Filetype: %s", string_get_cstr(temp_str));
+ }
+
+ // Key type
+ if(!flipper_format_read_string(fff_data_file, "Key type", temp_str)) {
+ FURI_LOG_E(TAG, "Missing or incorrect Key type");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Missing or incorrect Key type");
+ break;
+ } else {
+ FURI_LOG_I(TAG, "Key type: %s", string_get_cstr(temp_str));
+ if(strcmp(string_get_cstr(temp_str), "EM4100") != 0) {
+ FURI_LOG_E(TAG, "Unsupported Key type");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Unsupported Key type");
+ break;
+ }
+ }
+
+ // Data
+ if(!flipper_format_read_string(fff_data_file, "Data", context->data_str)) {
+ FURI_LOG_E(TAG, "Missing or incorrect Data");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Missing or incorrect Key");
+ break;
+ } else {
+ FURI_LOG_I(TAG, "Key: %s", string_get_cstr(context->data_str));
+
+ // Check data size
+ if(string_size(context->data_str) != 14) {
+ FURI_LOG_E(TAG, "Incorrect Key length");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Incorrect Key length");
+ break;
+ }
+ // String to uint8_t
+ for(uint8_t i = 0; i < 5; i++) {
+ char temp_str2[3];
+ temp_str2[0] = string_get_cstr(context->data_str)[i * 3];
+ temp_str2[1] = string_get_cstr(context->data_str)[i * 3 + 1];
+ temp_str2[2] = '\0';
+ context->data[i] = (uint8_t)strtol(temp_str2, NULL, 16);
+ }
+ }
+
+ result = true;
+ } while(0);
+ string_clear(temp_str);
+ flipper_format_free(fff_data_file);
+ if(result) {
+ FURI_LOG_I(TAG, "Loaded successfully");
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, "Source loaded.");
+ }
+ return result;
+}
+
+void flipfrid_scene_load_file_on_enter(FlipFridState* context) {
+ if(flipfrid_load_protocol_from_file(context)) {
+ context->current_scene = SceneSelectField;
+ } else {
+ flipfrid_scene_entrypoint_on_enter(context);
+ context->current_scene = SceneEntryPoint;
+ }
+}
+
+void flipfrid_scene_load_file_on_exit(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_load_file_on_tick(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context) {
+ if(event.evt_type == EventTypeKey) {
+ if(event.input_type == InputTypeShort) {
+ switch(event.key) {
+ case InputKeyDown:
+ case InputKeyUp:
+ case InputKeyLeft:
+ case InputKeyRight:
+ case InputKeyOk:
+ case InputKeyBack:
+ context->current_scene = SceneEntryPoint;
+ break;
+ }
+ }
+ }
+}
+
+void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context) {
+ UNUSED(context);
+ UNUSED(canvas);
+}
+
+bool flipfrid_load_protocol_from_file(FlipFridState* context) {
+ string_t user_file_path;
+ string_init(user_file_path);
+ string_set_str(user_file_path, LFRFID_APP_PATH_FOLDER);
+
+ // Input events and views are managed by file_select
+ bool res = dialog_file_browser_show(
+ context->dialogs,
+ user_file_path,
+ user_file_path,
+ LFRFID_APP_EXTENSION,
+ true,
+ &I_125_10px,
+ true);
+
+ if(res) {
+ res = flipfrid_load(context, string_get_cstr(user_file_path));
+ }
+
+ string_clear(user_file_path);
+
+ return res;
+}
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_load_file.h b/applications/flipfrid/scene/flipfrid_scene_load_file.h
new file mode 100644
index 000000000..ca82daab4
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_load_file.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "../flipfrid.h"
+
+void flipfrid_scene_load_file_on_enter(FlipFridState* context);
+void flipfrid_scene_load_file_on_exit(FlipFridState* context);
+void flipfrid_scene_load_file_on_tick(FlipFridState* context);
+void flipfrid_scene_load_file_on_event(FlipFridEvent event, FlipFridState* context);
+void flipfrid_scene_load_file_on_draw(Canvas* canvas, FlipFridState* context);
+bool flipfrid_load_protocol_from_file(FlipFridState* context);
\ No newline at end of file
diff --git a/applications/flipfrid/scene/flipfrid_scene_run_attack.c b/applications/flipfrid/scene/flipfrid_scene_run_attack.c
new file mode 100644
index 000000000..e34cb8986
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_run_attack.c
@@ -0,0 +1,214 @@
+#include "flipfrid_scene_run_attack.h"
+#include
+
+uint8_t counter = 0;
+#define TIME_BETWEEN_CARDS 5
+uint8_t id_list[16][5] = {
+ {0x00, 0x00, 0x00, 0x00, 0x00}, // Null bytes
+ {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, // Only FF
+ {0x11, 0x11, 0x11, 0x11, 0x11}, // Only 11
+ {0x22, 0x22, 0x22, 0x22, 0x22}, // Only 22
+ {0x33, 0x33, 0x33, 0x33, 0x33}, // Only 33
+ {0x44, 0x44, 0x44, 0x44, 0x44}, // Only 44
+ {0x55, 0x55, 0x55, 0x55, 0x55}, // Only 55
+ {0x66, 0x66, 0x66, 0x66, 0x66}, // Only 66
+ {0x77, 0x77, 0x77, 0x77, 0x77}, // Only 77
+ {0x88, 0x88, 0x88, 0x88, 0x88}, // Only 88
+ {0x99, 0x99, 0x99, 0x99, 0x99}, // Only 99
+ {0x12, 0x34, 0x56, 0x78, 0x9A}, // Incremental UID
+ {0x04, 0xd0, 0x9b, 0x0d, 0x6a}, // From arha
+ {0x34, 0x00, 0x29, 0x3d, 0x9e}, // From arha
+ {0x04, 0xdf, 0x00, 0x00, 0x01}, // From arha
+ {0xCA, 0xCA, 0xCA, 0xCA, 0xCA}, // From arha
+};
+
+void flipfrid_scene_run_attack_on_enter(FlipFridState* context) {
+ context->attack_step = 0;
+ context->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
+ context->worker = lfrfid_worker_alloc(context->dict);
+ context->protocol = protocol_dict_get_protocol_by_name(context->dict, "EM4100");
+}
+
+void flipfrid_scene_run_attack_on_exit(FlipFridState* context) {
+ lfrfid_worker_stop(context->worker);
+ lfrfid_worker_stop_thread(context->worker);
+ lfrfid_worker_free(context->worker);
+ protocol_dict_free(context->dict);
+ notification_message(context->notify, &sequence_blink_stop);
+}
+
+void flipfrid_scene_run_attack_on_tick(FlipFridState* context) {
+ if(context->is_attacking) {
+ if(1 == counter) {
+ protocol_dict_set_data(context->dict, context->protocol, context->payload, 5);
+ lfrfid_worker_free(context->worker);
+ context->worker = lfrfid_worker_alloc(context->dict);
+ lfrfid_worker_start_thread(context->worker);
+ lfrfid_worker_emulate_start(context->worker, context->protocol);
+ } else if(0 == counter) {
+ lfrfid_worker_stop(context->worker);
+ lfrfid_worker_stop_thread(context->worker);
+ switch(context->attack) {
+ case FlipFridAttackDefaultValues:
+ context->payload[0] = id_list[context->attack_step][0];
+ context->payload[1] = id_list[context->attack_step][1];
+ context->payload[2] = id_list[context->attack_step][2];
+ context->payload[3] = id_list[context->attack_step][3];
+ context->payload[4] = id_list[context->attack_step][4];
+
+ if(context->attack_step == 15) {
+ context->attack_step = 0;
+ counter = 0;
+ context->is_attacking = false;
+ notification_message(context->notify, &sequence_blink_stop);
+ notification_message(context->notify, &sequence_single_vibro);
+
+ } else {
+ context->attack_step++;
+ }
+ break;
+
+ case FlipFridAttackBfCustomerId:
+ context->payload[0] = context->attack_step;
+ context->payload[1] = 0x00;
+ context->payload[2] = 0x00;
+ context->payload[3] = 0x00;
+ context->payload[4] = 0x00;
+
+ if(context->attack_step == 255) {
+ context->attack_step = 0;
+ counter = 0;
+ context->is_attacking = false;
+ notification_message(context->notify, &sequence_blink_stop);
+ notification_message(context->notify, &sequence_single_vibro);
+ } else {
+ context->attack_step++;
+ }
+ break;
+ case FlipFridAttackLoadFile:
+ context->payload[0] = context->data[0];
+ context->payload[1] = context->data[1];
+ context->payload[2] = context->data[2];
+ context->payload[3] = context->data[3];
+ context->payload[4] = context->data[4];
+
+ context->payload[context->key_index] = context->attack_step;
+
+ if(context->attack_step == 255) {
+ context->attack_step = 0;
+ counter = 0;
+ context->is_attacking = false;
+ notification_message(context->notify, &sequence_blink_stop);
+ notification_message(context->notify, &sequence_single_vibro);
+ break;
+ } else {
+ context->attack_step++;
+ }
+ break;
+ case FlipFridAttackLoadFileCustomUids:
+ while(true) {
+ string_reset(context->data_str);
+ if(!stream_read_line(context->uids_stream, context->data_str)) {
+ context->attack_step = 0;
+ counter = 0;
+ context->is_attacking = false;
+ notification_message(context->notify, &sequence_blink_stop);
+ notification_message(context->notify, &sequence_single_vibro);
+ break;
+ };
+ if(string_get_char(context->data_str, 0) == '#') continue;
+ if(string_size(context->data_str) != 11) continue;
+ break;
+ }
+ FURI_LOG_D(TAG, string_get_cstr(context->data_str));
+
+ // string is valid, parse it in context->payload
+ for(uint8_t i = 0; i < 5; i++) {
+ char temp_str[3];
+ temp_str[0] = string_get_cstr(context->data_str)[i * 2];
+ temp_str[1] = string_get_cstr(context->data_str)[i * 2 + 1];
+ temp_str[2] = '\0';
+ context->payload[i] = (uint8_t)strtol(temp_str, NULL, 16);
+ }
+ break;
+ }
+ }
+
+ if(counter > TIME_BETWEEN_CARDS) {
+ counter = 0;
+ } else {
+ counter++;
+ }
+ }
+}
+
+void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context) {
+ if(event.evt_type == EventTypeKey) {
+ if(event.input_type == InputTypeShort) {
+ switch(event.key) {
+ case InputKeyDown:
+ case InputKeyUp:
+ case InputKeyLeft:
+ case InputKeyRight:
+ break;
+ case InputKeyOk:
+ counter = 0;
+ if(!context->is_attacking) {
+ notification_message(context->notify, &sequence_blink_start_blue);
+ context->is_attacking = true;
+ } else {
+ context->is_attacking = false;
+ notification_message(context->notify, &sequence_blink_stop);
+ notification_message(context->notify, &sequence_single_vibro);
+ }
+ break;
+ case InputKeyBack:
+ if(context->attack == FlipFridAttackLoadFileCustomUids) {
+ buffered_file_stream_close(context->uids_stream);
+ }
+
+ context->attack_step = 0;
+ context->is_attacking = false;
+ string_reset(context->notification_msg);
+ context->current_scene = SceneEntryPoint;
+ notification_message(context->notify, &sequence_blink_stop);
+ break;
+ }
+ }
+ }
+}
+
+void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context) {
+ canvas_clear(canvas);
+ canvas_set_color(canvas, ColorBlack);
+
+ // Frame
+ //canvas_draw_frame(canvas, 0, 0, 128, 64);
+
+ // Title
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str_aligned(
+ canvas, 64, 8, AlignCenter, AlignTop, string_get_cstr(context->attack_name));
+
+ char uid[16];
+ snprintf(
+ uid,
+ sizeof(uid),
+ "%02X:%02X:%02X:%02X:%02X",
+ context->payload[0],
+ context->payload[1],
+ context->payload[2],
+ context->payload[3],
+ context->payload[4]);
+ canvas_draw_str_aligned(canvas, 64, 24, AlignCenter, AlignTop, uid);
+
+ canvas_set_font(canvas, FontSecondary);
+ //char start_stop_msg[20];
+ if(context->is_attacking) {
+ elements_button_center(canvas, "Stop");
+ //snprintf(start_stop_msg, sizeof(start_stop_msg), " Press OK to stop ");
+ } else {
+ elements_button_center(canvas, "Start");
+ }
+ //canvas_draw_str_aligned(canvas, 64, 44, AlignCenter, AlignTop, start_stop_msg);
+}
diff --git a/applications/flipfrid/scene/flipfrid_scene_run_attack.h b/applications/flipfrid/scene/flipfrid_scene_run_attack.h
new file mode 100644
index 000000000..ae56d35e7
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_run_attack.h
@@ -0,0 +1,8 @@
+#pragma once
+#include "../flipfrid.h"
+
+void flipfrid_scene_run_attack_on_enter(FlipFridState* context);
+void flipfrid_scene_run_attack_on_exit(FlipFridState* context);
+void flipfrid_scene_run_attack_on_tick(FlipFridState* context);
+void flipfrid_scene_run_attack_on_event(FlipFridEvent event, FlipFridState* context);
+void flipfrid_scene_run_attack_on_draw(Canvas* canvas, FlipFridState* context);
diff --git a/applications/flipfrid/scene/flipfrid_scene_select_field.c b/applications/flipfrid/scene/flipfrid_scene_select_field.c
new file mode 100644
index 000000000..03411b2f4
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_select_field.c
@@ -0,0 +1,121 @@
+#include "flipfrid_scene_select_field.h"
+
+void flipfrid_center_displayed_key(FlipFridState* context, uint8_t index) {
+ const char* key_cstr = string_get_cstr(context->data_str);
+ uint8_t str_index = (index * 3);
+
+ char display_menu[17] = {
+ 'X', 'X', ' ', 'X', 'X', ' ', '<', 'X', 'X', '>', ' ', 'X', 'X', ' ', 'X', 'X', '\0'};
+
+ if(index > 1) {
+ display_menu[0] = key_cstr[str_index - 6];
+ display_menu[1] = key_cstr[str_index - 5];
+ } else {
+ display_menu[0] = ' ';
+ display_menu[1] = ' ';
+ }
+
+ if(index > 0) {
+ display_menu[3] = key_cstr[str_index - 3];
+ display_menu[4] = key_cstr[str_index - 2];
+ } else {
+ display_menu[3] = ' ';
+ display_menu[4] = ' ';
+ }
+
+ display_menu[7] = key_cstr[str_index];
+ display_menu[8] = key_cstr[str_index + 1];
+
+ if((str_index + 4) <= (uint8_t)strlen(key_cstr)) {
+ display_menu[11] = key_cstr[str_index + 3];
+ display_menu[12] = key_cstr[str_index + 4];
+ } else {
+ display_menu[11] = ' ';
+ display_menu[12] = ' ';
+ }
+
+ if((str_index + 8) <= (uint8_t)strlen(key_cstr)) {
+ display_menu[14] = key_cstr[str_index + 6];
+ display_menu[15] = key_cstr[str_index + 7];
+ } else {
+ display_menu[14] = ' ';
+ display_menu[15] = ' ';
+ }
+
+ string_reset(context->notification_msg);
+ string_set_str(context->notification_msg, display_menu);
+}
+
+void flipfrid_scene_select_field_on_enter(FlipFridState* context) {
+ string_clear(context->notification_msg);
+}
+
+void flipfrid_scene_select_field_on_exit(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_select_field_on_tick(FlipFridState* context) {
+ UNUSED(context);
+}
+
+void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context) {
+ if(event.evt_type == EventTypeKey) {
+ if(event.input_type == InputTypeShort) {
+ const char* key_cstr = string_get_cstr(context->data_str);
+
+ // don't look, it's ugly but I'm a python dev so...
+ uint8_t nb_bytes = 0;
+ for(uint8_t i = 0; i < strlen(key_cstr); i++) {
+ if(' ' == key_cstr[i]) {
+ nb_bytes++;
+ }
+ }
+
+ switch(event.key) {
+ case InputKeyDown:
+ case InputKeyUp:
+ break;
+ case InputKeyLeft:
+ if(context->key_index > 0) {
+ context->key_index = context->key_index - 1;
+ }
+ break;
+ case InputKeyRight:
+ if(context->key_index < nb_bytes) {
+ context->key_index = context->key_index + 1;
+ }
+ break;
+ case InputKeyOk:
+ string_reset(context->notification_msg);
+ context->current_scene = SceneAttack;
+ break;
+ case InputKeyBack:
+ string_reset(context->notification_msg);
+ context->current_scene = SceneSelectFile;
+ break;
+ }
+ FURI_LOG_D(TAG, "Position: %d/%d", context->key_index, nb_bytes);
+ }
+ }
+}
+
+void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context) {
+ canvas_clear(canvas);
+ canvas_set_color(canvas, ColorBlack);
+
+ // Frame
+ //canvas_draw_frame(canvas, 0, 0, 128, 64);
+
+ // Title
+ canvas_set_font(canvas, FontPrimary);
+ canvas_draw_str_aligned(canvas, 64, 10, AlignCenter, AlignTop, "Use < > to select byte.");
+
+ char msg_index[18];
+ snprintf(msg_index, sizeof(msg_index), "Field index : %d", context->key_index);
+ canvas_draw_str_aligned(canvas, 64, 26, AlignCenter, AlignTop, msg_index);
+
+ flipfrid_center_displayed_key(context, context->key_index);
+ canvas_set_font(canvas, FontSecondary);
+ canvas_draw_str_aligned(
+ canvas, 64, 40, AlignCenter, AlignTop, string_get_cstr(context->notification_msg));
+}
diff --git a/applications/flipfrid/scene/flipfrid_scene_select_field.h b/applications/flipfrid/scene/flipfrid_scene_select_field.h
new file mode 100644
index 000000000..5533e321c
--- /dev/null
+++ b/applications/flipfrid/scene/flipfrid_scene_select_field.h
@@ -0,0 +1,9 @@
+#pragma once
+#include "../flipfrid.h"
+
+void flipfrid_scene_select_field_on_enter(FlipFridState* context);
+void flipfrid_scene_select_field_on_exit(FlipFridState* context);
+void flipfrid_scene_select_field_on_tick(FlipFridState* context);
+void flipfrid_scene_select_field_on_event(FlipFridEvent event, FlipFridState* context);
+void flipfrid_scene_select_field_on_draw(Canvas* canvas, FlipFridState* context);
+void center_displayed_key(FlipFridState* context, uint8_t index);
\ No newline at end of file
diff --git a/applications/gpio/views/gpio_test.c b/applications/gpio/views/gpio_test.c
old mode 100755
new mode 100644
diff --git a/applications/gpio/views/gpio_test.h b/applications/gpio/views/gpio_test.h
old mode 100755
new mode 100644
diff --git a/applications/gpio/views/gpio_usb_uart.h b/applications/gpio/views/gpio_usb_uart.h
old mode 100755
new mode 100644
diff --git a/applications/gui/canvas.c b/applications/gui/canvas.c
index 1e275aafb..562f2e183 100644
--- a/applications/gui/canvas.c
+++ b/applications/gui/canvas.c
@@ -12,6 +12,7 @@ const CanvasFontParameters canvas_font_params[FontTotalNumber] = {
[FontSecondary] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
[FontKeyboard] = {.leading_default = 11, .leading_min = 9, .height = 7, .descender = 2},
[FontBigNumbers] = {.leading_default = 18, .leading_min = 16, .height = 15, .descender = 0},
+ [FontBatteryPercent] = {.leading_default = 11, .leading_min = 9, .height = 6, .descender = 0},
};
Canvas* canvas_init() {
@@ -132,6 +133,8 @@ void canvas_set_font(Canvas* canvas, Font font) {
u8g2_SetFont(&canvas->fb, u8g2_font_profont11_mr);
} else if(font == FontBigNumbers) {
u8g2_SetFont(&canvas->fb, u8g2_font_profont22_tn);
+ } else if(font == FontBatteryPercent) {
+ u8g2_SetFont(&canvas->fb, u8g2_font_5x7_tf); //u8g2_font_micro_tr);
} else {
furi_crash(NULL);
}
diff --git a/applications/gui/canvas.h b/applications/gui/canvas.h
old mode 100755
new mode 100644
index 4923e2e66..edde10a01
--- a/applications/gui/canvas.h
+++ b/applications/gui/canvas.h
@@ -25,6 +25,7 @@ typedef enum {
FontSecondary,
FontKeyboard,
FontBigNumbers,
+ FontBatteryPercent,
// Keep last for fonts number calculation
FontTotalNumber,
diff --git a/applications/gui/modules/button_panel.c b/applications/gui/modules/button_panel.c
index e3ae59a36..ff52ebd8c 100644
--- a/applications/gui/modules/button_panel.c
+++ b/applications/gui/modules/button_panel.c
@@ -83,6 +83,15 @@ ButtonPanel* button_panel_alloc() {
return button_panel;
}
+void button_panel_reset_selection(ButtonPanel* button_panel) {
+ with_view_model(
+ button_panel->view, (ButtonPanelModel * model) {
+ model->selected_item_x = 0;
+ model->selected_item_y = 0;
+ return true;
+ });
+}
+
void button_panel_reserve(ButtonPanel* button_panel, size_t reserve_x, size_t reserve_y) {
furi_check(reserve_x > 0);
furi_check(reserve_y > 0);
diff --git a/applications/gui/modules/button_panel.h b/applications/gui/modules/button_panel.h
index 0c17e3a7c..9c944ca46 100644
--- a/applications/gui/modules/button_panel.h
+++ b/applications/gui/modules/button_panel.h
@@ -35,6 +35,12 @@ void button_panel_free(ButtonPanel* button_panel);
*/
void button_panel_reset(ButtonPanel* button_panel);
+/** Resets selected_item_x and selected_item_y.
+ *
+ * @param button_panel ButtonPanel instance
+ */
+void button_panel_reset_selection(ButtonPanel* button_panel);
+
/** Reserve space for adding items.
*
* One does not simply use button_panel_add_item() without this function. It
diff --git a/applications/gui/modules/dialog_ex.c b/applications/gui/modules/dialog_ex.c
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/menu.h b/applications/gui/modules/menu.h
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/text_box.c b/applications/gui/modules/text_box.c
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/text_box.h b/applications/gui/modules/text_box.h
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/text_input.c b/applications/gui/modules/text_input.c
index 26f74e7ac..b8098a3b9 100644
--- a/applications/gui/modules/text_input.c
+++ b/applications/gui/modules/text_input.c
@@ -463,8 +463,6 @@ void text_input_free(TextInput* text_input) {
// Send stop command
furi_timer_stop(text_input->timer);
- // Wait till timer stop
- while(furi_timer_is_running(text_input->timer)) furi_delay_tick(1);
// Release allocated memory
furi_timer_free(text_input->timer);
diff --git a/applications/gui/modules/validators.c b/applications/gui/modules/validators.c
index ac293f8cb..52f9946ca 100644
--- a/applications/gui/modules/validators.c
+++ b/applications/gui/modules/validators.c
@@ -42,7 +42,9 @@ ValidatorIsFile* validator_is_file_alloc_init(
instance->app_path_folder = strdup(app_path_folder);
instance->app_extension = app_extension;
- instance->current_name = strdup(current_name);
+ if(current_name != NULL) {
+ instance->current_name = strdup(current_name);
+ }
return instance;
}
diff --git a/applications/gui/modules/variable_item_list.h b/applications/gui/modules/variable_item_list.h
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/widget.h b/applications/gui/modules/widget.h
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/widget_elements/widget_element_frame.c b/applications/gui/modules/widget_elements/widget_element_frame.c
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/widget_elements/widget_element_i.h b/applications/gui/modules/widget_elements/widget_element_i.h
old mode 100755
new mode 100644
diff --git a/applications/gui/modules/widget_elements/widget_element_string.c b/applications/gui/modules/widget_elements/widget_element_string.c
old mode 100755
new mode 100644
diff --git a/applications/gui/scene_manager.c b/applications/gui/scene_manager.c
old mode 100755
new mode 100644
diff --git a/applications/gui/scene_manager.h b/applications/gui/scene_manager.h
old mode 100755
new mode 100644
diff --git a/applications/gui/scene_manager_i.h b/applications/gui/scene_manager_i.h
old mode 100755
new mode 100644
diff --git a/applications/gui/view_dispatcher.h b/applications/gui/view_dispatcher.h
old mode 100755
new mode 100644
diff --git a/applications/infrared/infrared_brute_force.c b/applications/infrared/infrared_brute_force.c
index 8dbc23012..89272de7e 100644
--- a/applications/infrared/infrared_brute_force.c
+++ b/applications/infrared/infrared_brute_force.c
@@ -35,6 +35,10 @@ InfraredBruteForce* infrared_brute_force_alloc() {
return brute_force;
}
+void infrared_brute_force_clear_records(InfraredBruteForce* brute_force) {
+ InfraredBruteForceRecordDict_reset(brute_force->records);
+}
+
void infrared_brute_force_free(InfraredBruteForce* brute_force) {
furi_assert(!brute_force->ff);
InfraredBruteForceRecordDict_clear(brute_force->records);
diff --git a/applications/infrared/infrared_brute_force.h b/applications/infrared/infrared_brute_force.h
index acf0d7b6e..fff472e79 100644
--- a/applications/infrared/infrared_brute_force.h
+++ b/applications/infrared/infrared_brute_force.h
@@ -16,6 +16,7 @@ bool infrared_brute_force_start(
bool infrared_brute_force_is_started(InfraredBruteForce* brute_force);
void infrared_brute_force_stop(InfraredBruteForce* brute_force);
bool infrared_brute_force_send_next(InfraredBruteForce* brute_force);
+void infrared_brute_force_clear_records(InfraredBruteForce* brute_force);
void infrared_brute_force_add_record(
InfraredBruteForce* brute_force,
uint32_t index,
diff --git a/applications/infrared/infrared_cli.c b/applications/infrared/infrared_cli.c
index aae02e8fd..693e191ee 100644
--- a/applications/infrared/infrared_cli.c
+++ b/applications/infrared/infrared_cli.c
@@ -3,6 +3,8 @@
#include
#include
#include
+#include
+#include
#include "infrared_signal.h"
@@ -10,6 +12,7 @@
static void infrared_cli_start_ir_rx(Cli* cli, string_t args);
static void infrared_cli_start_ir_tx(Cli* cli, string_t args);
+static void infrared_cli_process_decode(Cli* cli, string_t args);
static const struct {
const char* cmd;
@@ -17,6 +20,7 @@ static const struct {
} infrared_cli_commands[] = {
{.cmd = "rx", .process_function = infrared_cli_start_ir_rx},
{.cmd = "tx", .process_function = infrared_cli_start_ir_tx},
+ {.cmd = "decode", .process_function = infrared_cli_process_decode},
};
static void signal_received_callback(void* context, InfraredWorkerSignal* received_signal) {
@@ -86,6 +90,7 @@ static void infrared_cli_print_usage(void) {
"\tFrequency (%d - %d), Duty cycle (0 - 100), max 512 samples\r\n",
INFRARED_MIN_FREQUENCY,
INFRARED_MAX_FREQUENCY);
+ printf("\tir decode []\r\n");
}
static bool infrared_cli_parse_message(const char* str, InfraredSignal* signal) {
@@ -162,6 +167,160 @@ static void infrared_cli_start_ir_tx(Cli* cli, string_t args) {
infrared_signal_free(signal);
}
+static bool
+ infrared_cli_save_signal(InfraredSignal* signal, FlipperFormat* file, const char* name) {
+ bool ret = infrared_signal_save(signal, file, name);
+ if(!ret) {
+ printf("Failed to save signal: \"%s\"\r\n", name);
+ }
+ return ret;
+}
+
+static bool infrared_cli_decode_raw_signal(
+ InfraredRawSignal* raw_signal,
+ InfraredDecoderHandler* decoder,
+ FlipperFormat* output_file,
+ const char* signal_name) {
+ InfraredSignal* signal = infrared_signal_alloc();
+ bool ret = false, level = true, is_decoded = false;
+
+ size_t i;
+ for(i = 0; i < raw_signal->timings_size; ++i) {
+ // TODO: Any infrared_check_decoder_ready() magic?
+ const InfraredMessage* message = infrared_decode(decoder, level, raw_signal->timings[i]);
+
+ if(message) {
+ is_decoded = true;
+ printf(
+ "Protocol: %s address: 0x%lX command: 0x%lX %s\r\n",
+ infrared_get_protocol_name(message->protocol),
+ message->address,
+ message->command,
+ (message->repeat ? "R" : ""));
+ if(output_file && !message->repeat) {
+ infrared_signal_set_message(signal, message);
+ if(!infrared_cli_save_signal(signal, output_file, signal_name)) break;
+ }
+ }
+
+ level = !level;
+ }
+
+ if(i == raw_signal->timings_size) {
+ if(!is_decoded && output_file) {
+ infrared_signal_set_raw_signal(
+ signal,
+ raw_signal->timings,
+ raw_signal->timings_size,
+ raw_signal->frequency,
+ raw_signal->duty_cycle);
+ ret = infrared_cli_save_signal(signal, output_file, signal_name);
+ } else {
+ ret = true;
+ }
+ }
+
+ infrared_reset_decoder(decoder);
+ infrared_signal_free(signal);
+ return ret;
+}
+
+static bool infrared_cli_decode_file(FlipperFormat* input_file, FlipperFormat* output_file) {
+ bool ret = false;
+
+ InfraredSignal* signal = infrared_signal_alloc();
+ InfraredDecoderHandler* decoder = infrared_alloc_decoder();
+
+ string_t tmp;
+ string_init(tmp);
+
+ while(infrared_signal_read(signal, input_file, tmp)) {
+ ret = false;
+ if(!infrared_signal_is_valid(signal)) {
+ printf("Invalid signal\r\n");
+ break;
+ }
+ if(!infrared_signal_is_raw(signal)) {
+ if(output_file &&
+ !infrared_cli_save_signal(signal, output_file, string_get_cstr(tmp))) {
+ break;
+ } else {
+ printf("Skipping decoded signal\r\n");
+ continue;
+ }
+ }
+ InfraredRawSignal* raw_signal = infrared_signal_get_raw_signal(signal);
+ printf("Raw signal: %s, %u samples\r\n", string_get_cstr(tmp), raw_signal->timings_size);
+ if(!infrared_cli_decode_raw_signal(raw_signal, decoder, output_file, string_get_cstr(tmp)))
+ break;
+ ret = true;
+ }
+
+ infrared_free_decoder(decoder);
+ infrared_signal_free(signal);
+ string_clear(tmp);
+
+ return ret;
+}
+
+static void infrared_cli_process_decode(Cli* cli, string_t args) {
+ UNUSED(cli);
+ Storage* storage = furi_record_open(RECORD_STORAGE);
+ FlipperFormat* input_file = flipper_format_buffered_file_alloc(storage);
+ FlipperFormat* output_file = NULL;
+
+ uint32_t version;
+ string_t tmp, header, input_path, output_path;
+ string_init(tmp);
+ string_init(header);
+ string_init(input_path);
+ string_init(output_path);
+
+ do {
+ if(!args_read_probably_quoted_string_and_trim(args, input_path)) {
+ printf("Wrong arguments.\r\n");
+ infrared_cli_print_usage();
+ break;
+ }
+ args_read_probably_quoted_string_and_trim(args, output_path);
+ if(!flipper_format_buffered_file_open_existing(input_file, string_get_cstr(input_path))) {
+ printf("Failed to open file for reading: \"%s\"\r\n", string_get_cstr(input_path));
+ break;
+ }
+ if(!flipper_format_read_header(input_file, header, &version) ||
+ (!string_start_with_str_p(header, "IR")) || version != 1) {
+ printf("Invalid or corrupted input file: \"%s\"\r\n", string_get_cstr(input_path));
+ break;
+ }
+ if(!string_empty_p(output_path)) {
+ printf("Writing output to file: \"%s\"\r\n", string_get_cstr(output_path));
+ output_file = flipper_format_file_alloc(storage);
+ }
+ if(output_file &&
+ !flipper_format_file_open_always(output_file, string_get_cstr(output_path))) {
+ printf("Failed to open file for writing: \"%s\"\r\n", string_get_cstr(output_path));
+ break;
+ }
+ if(output_file && !flipper_format_write_header(output_file, header, version)) {
+ printf("Failed to write to the output file: \"%s\"\r\n", string_get_cstr(output_path));
+ break;
+ }
+ if(!infrared_cli_decode_file(input_file, output_file)) {
+ break;
+ }
+ printf("File successfully decoded.\r\n");
+ } while(false);
+
+ string_clear(tmp);
+ string_clear(header);
+ string_clear(input_path);
+ string_clear(output_path);
+
+ flipper_format_free(input_file);
+ if(output_file) flipper_format_free(output_file);
+ furi_record_close(RECORD_STORAGE);
+}
+
static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) {
UNUSED(context);
if(furi_hal_infrared_is_busy()) {
@@ -169,18 +328,15 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) {
return;
}
+ string_t command;
+ string_init(command);
+ args_read_string_and_trim(args, command);
+
size_t i = 0;
for(; i < COUNT_OF(infrared_cli_commands); ++i) {
- size_t size = strlen(infrared_cli_commands[i].cmd);
- bool cmd_found = !strncmp(string_get_cstr(args), infrared_cli_commands[i].cmd, size);
- if(cmd_found) {
- if(string_size(args) == size) {
- break;
- }
- if(string_get_cstr(args)[size] == ' ') {
- string_right(args, size + 1);
- break;
- }
+ size_t cmd_len = strlen(infrared_cli_commands[i].cmd);
+ if(!strncmp(string_get_cstr(command), infrared_cli_commands[i].cmd, cmd_len)) {
+ break;
}
}
@@ -189,6 +345,8 @@ static void infrared_cli_start_ir(Cli* cli, string_t args, void* context) {
} else {
infrared_cli_print_usage();
}
+
+ string_clear(command);
}
void infrared_on_system_start() {
#ifdef SRV_CLI
diff --git a/applications/infrared/scenes/common/infrared_scene_universal_common.c b/applications/infrared/scenes/common/infrared_scene_universal_common.c
index 57ac81168..1072549ff 100644
--- a/applications/infrared/scenes/common/infrared_scene_universal_common.c
+++ b/applications/infrared/scenes/common/infrared_scene_universal_common.c
@@ -33,6 +33,8 @@ static void infrared_scene_universal_common_hide_popup(Infrared* infrared) {
void infrared_scene_universal_common_on_enter(void* context) {
Infrared* infrared = context;
+ infrared_brute_force_clear_records(infrared->brute_force);
+ button_panel_reset_selection(infrared->button_panel);
view_stack_add_view(infrared->view_stack, button_panel_get_view(infrared->button_panel));
}
diff --git a/applications/infrared/scenes/infrared_scene_config.h b/applications/infrared/scenes/infrared_scene_config.h
index 27eabe225..551485295 100644
--- a/applications/infrared/scenes/infrared_scene_config.h
+++ b/applications/infrared/scenes/infrared_scene_config.h
@@ -16,6 +16,7 @@ ADD_SCENE(infrared, remote_list, RemoteList)
ADD_SCENE(infrared, universal, Universal)
ADD_SCENE(infrared, universal_tv, UniversalTV)
ADD_SCENE(infrared, universal_ac, UniversalAC)
+ADD_SCENE(infrared, universal_fan, UniversalFan)
ADD_SCENE(infrared, universal_audio, UniversalAudio)
ADD_SCENE(infrared, universal_projector, UniversalProjector)
ADD_SCENE(infrared, debug, Debug)
diff --git a/applications/infrared/scenes/infrared_scene_learn.c b/applications/infrared/scenes/infrared_scene_learn.c
index 0edb74ca2..37f9b3e05 100644
--- a/applications/infrared/scenes/infrared_scene_learn.c
+++ b/applications/infrared/scenes/infrared_scene_learn.c
@@ -25,7 +25,6 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
if(event.type == SceneManagerEventTypeCustom) {
if(event.event == InfraredCustomEventTypeSignalReceived) {
- infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL);
infrared_play_notification_message(infrared, InfraredNotificationMessageSuccess);
scene_manager_next_scene(infrared->scene_manager, InfraredSceneLearnSuccess);
consumed = true;
@@ -38,6 +37,7 @@ bool infrared_scene_learn_on_event(void* context, SceneManagerEvent event) {
void infrared_scene_learn_on_exit(void* context) {
Infrared* infrared = context;
Popup* popup = infrared->popup;
+ infrared_worker_rx_set_received_signal_callback(infrared->worker, NULL, NULL);
infrared_worker_rx_stop(infrared->worker);
infrared_play_notification_message(infrared, InfraredNotificationMessageBlinkStop);
popup_set_icon(popup, 0, 0, NULL);
diff --git a/applications/infrared/scenes/infrared_scene_universal.c b/applications/infrared/scenes/infrared_scene_universal.c
index 36c7d86e1..b70ffbd5c 100644
--- a/applications/infrared/scenes/infrared_scene_universal.c
+++ b/applications/infrared/scenes/infrared_scene_universal.c
@@ -4,6 +4,7 @@ typedef enum {
SubmenuIndexUniversalTV,
SubmenuIndexUniversalAudio,
SubmenuIndexUniversalProjector,
+ SubmenuIndexUniversalFan,
SubmenuIndexUniversalAirConditioner,
} SubmenuIndex;
@@ -38,6 +39,13 @@ void infrared_scene_universal_on_enter(void* context) {
infrared_scene_universal_submenu_callback,
context);
+ submenu_add_item(
+ submenu,
+ "Fans",
+ SubmenuIndexUniversalFan,
+ infrared_scene_universal_submenu_callback,
+ context);
+
submenu_add_item(
submenu,
"ACs",
@@ -63,6 +71,9 @@ bool infrared_scene_universal_on_event(void* context, SceneManagerEvent event) {
} else if(event.event == SubmenuIndexUniversalProjector) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalProjector);
consumed = true;
+ } else if(event.event == SubmenuIndexUniversalFan) {
+ scene_manager_next_scene(scene_manager, InfraredSceneUniversalFan);
+ consumed = true;
} else if(event.event == SubmenuIndexUniversalAirConditioner) {
scene_manager_next_scene(scene_manager, InfraredSceneUniversalAC);
consumed = true;
diff --git a/applications/infrared/scenes/infrared_scene_universal_ac.c b/applications/infrared/scenes/infrared_scene_universal_ac.c
index 9e98a671e..68a6ea942 100644
--- a/applications/infrared/scenes/infrared_scene_universal_ac.c
+++ b/applications/infrared/scenes/infrared_scene_universal_ac.c
@@ -12,7 +12,7 @@ void infrared_scene_universal_ac_on_enter(void* context) {
infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/ac.ir"));
//TODO Improve A/C universal remote
- button_panel_reserve(button_panel, 2, 2);
+ button_panel_reserve(button_panel, 2, 3);
uint32_t i = 0;
button_panel_add_item(
button_panel,
@@ -44,7 +44,7 @@ void infrared_scene_universal_ac_on_enter(void* context) {
0,
1,
3,
- 69,
+ 66,
&I_Vol_up_25x27,
&I_Vol_up_hvr_25x27,
infrared_scene_universal_common_item_callback,
@@ -56,15 +56,39 @@ void infrared_scene_universal_ac_on_enter(void* context) {
1,
1,
36,
- 69,
+ 66,
&I_Vol_down_25x27,
&I_Vol_down_hvr_25x27,
infrared_scene_universal_common_item_callback,
context);
infrared_brute_force_add_record(brute_force, i++, "TEMP-");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 0,
+ 2,
+ 3,
+ 98,
+ &I_Swing_25x27,
+ &I_Swing_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "SWING");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 1,
+ 2,
+ 36,
+ 98,
+ &I_Timer_25x27,
+ &I_Timer_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "TIMER");
button_panel_add_label(button_panel, 6, 11, FontPrimary, "AC remote");
- button_panel_add_label(button_panel, 20, 66, FontSecondary, "Temp");
+ button_panel_add_label(button_panel, 20, 63, FontSecondary, "Temp");
button_panel_add_label(button_panel, 8, 23, FontSecondary, "Pwr");
button_panel_add_label(button_panel, 40, 23, FontSecondary, "Mod");
diff --git a/applications/infrared/scenes/infrared_scene_universal_fan.c b/applications/infrared/scenes/infrared_scene_universal_fan.c
new file mode 100644
index 000000000..37657ac3c
--- /dev/null
+++ b/applications/infrared/scenes/infrared_scene_universal_fan.c
@@ -0,0 +1,113 @@
+#include "../infrared_i.h"
+
+#include "common/infrared_scene_universal_common.h"
+
+void infrared_scene_universal_fan_on_enter(void* context) {
+ infrared_scene_universal_common_on_enter(context);
+
+ Infrared* infrared = context;
+ ButtonPanel* button_panel = infrared->button_panel;
+ InfraredBruteForce* brute_force = infrared->brute_force;
+
+ infrared_brute_force_set_db_filename(brute_force, EXT_PATH("infrared/assets/fans.ir"));
+
+ //TODO Improve Fan universal remote
+ button_panel_reserve(button_panel, 2, 3);
+ uint32_t i = 0;
+ button_panel_add_item(
+ button_panel,
+ i,
+ 0,
+ 0,
+ 3,
+ 24,
+ &I_Power_25x27,
+ &I_Power_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "POWER");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 1,
+ 0,
+ 36,
+ 24,
+ &I_Mode_25x27,
+ &I_Mode_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "MODE");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 0,
+ 1,
+ 3,
+ 66,
+ &I_Vol_up_25x27,
+ &I_Vol_up_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "SPEED+");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 1,
+ 1,
+ 36,
+ 66,
+ &I_Vol_down_25x27,
+ &I_Vol_down_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "SPEED-");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 0,
+ 2,
+ 3,
+ 98,
+ &I_Rotate_25x27,
+ &I_Rotate_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "ROTATE");
+ button_panel_add_item(
+ button_panel,
+ i,
+ 1,
+ 2,
+ 36,
+ 98,
+ &I_Timer_25x27,
+ &I_Timer_hvr_25x27,
+ infrared_scene_universal_common_item_callback,
+ context);
+ infrared_brute_force_add_record(brute_force, i++, "TIMER");
+
+ button_panel_add_label(button_panel, 5, 11, FontPrimary, "Fan remote");
+ button_panel_add_label(button_panel, 20, 63, FontSecondary, "Speed");
+ button_panel_add_label(button_panel, 8, 23, FontSecondary, "Pwr");
+ button_panel_add_label(button_panel, 40, 23, FontSecondary, "Mod");
+
+ view_set_orientation(view_stack_get_view(infrared->view_stack), ViewOrientationVertical);
+ view_dispatcher_switch_to_view(infrared->view_dispatcher, InfraredViewStack);
+
+ infrared_show_loading_popup(infrared, true);
+ bool success = infrared_brute_force_calculate_messages(brute_force);
+ infrared_show_loading_popup(infrared, false);
+
+ if(!success) {
+ scene_manager_next_scene(infrared->scene_manager, InfraredSceneErrorDatabases);
+ }
+}
+
+bool infrared_scene_universal_fan_on_event(void* context, SceneManagerEvent event) {
+ return infrared_scene_universal_common_on_event(context, event);
+}
+
+void infrared_scene_universal_fan_on_exit(void* context) {
+ infrared_scene_universal_common_on_exit(context);
+}
diff --git a/applications/lfrfid/application.fam b/applications/lfrfid/application.fam
index 8722bb4f8..425804a55 100644
--- a/applications/lfrfid/application.fam
+++ b/applications/lfrfid/application.fam
@@ -10,7 +10,7 @@ App(
],
provides=[
"lfrfid_start",
- "lfrfid_debug",
+ #"lfrfid_debug",
],
icon="A_125khz_14",
stack_size=2 * 1024,
diff --git a/applications/lfrfid/lfrfid.c b/applications/lfrfid/lfrfid.c
new file mode 100644
index 000000000..87332b1ac
--- /dev/null
+++ b/applications/lfrfid/lfrfid.c
@@ -0,0 +1,316 @@
+#include "lfrfid_i.h"
+
+static bool lfrfid_debug_custom_event_callback(void* context, uint32_t event) {
+ furi_assert(context);
+ LfRfid* app = context;
+ return scene_manager_handle_custom_event(app->scene_manager, event);
+}
+
+static bool lfrfid_debug_back_event_callback(void* context) {
+ furi_assert(context);
+ LfRfid* app = context;
+ return scene_manager_handle_back_event(app->scene_manager);
+}
+
+static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
+ furi_assert(context);
+ LfRfid* app = (LfRfid*)context;
+
+ if(rpc_event == RpcAppEventSessionClose) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcSessionClose);
+ // Detach RPC
+ rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
+ app->rpc_ctx = NULL;
+ } else if(rpc_event == RpcAppEventAppExit) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventExit);
+ } else if(rpc_event == RpcAppEventLoadFile) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventRpcLoadFile);
+ } else {
+ rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
+ }
+}
+
+static LfRfid* lfrfid_alloc() {
+ LfRfid* lfrfid = malloc(sizeof(LfRfid));
+
+ lfrfid->storage = furi_record_open(RECORD_STORAGE);
+ lfrfid->dialogs = furi_record_open(RECORD_DIALOGS);
+
+ string_init(lfrfid->file_name);
+ string_init(lfrfid->raw_file_name);
+ string_init_set_str(lfrfid->file_path, LFRFID_APP_FOLDER);
+
+ lfrfid->dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
+
+ size_t size = protocol_dict_get_max_data_size(lfrfid->dict);
+ lfrfid->new_key_data = (uint8_t*)malloc(size);
+ lfrfid->old_key_data = (uint8_t*)malloc(size);
+
+ lfrfid->lfworker = lfrfid_worker_alloc(lfrfid->dict);
+
+ lfrfid->view_dispatcher = view_dispatcher_alloc();
+ lfrfid->scene_manager = scene_manager_alloc(&lfrfid_scene_handlers, lfrfid);
+ view_dispatcher_enable_queue(lfrfid->view_dispatcher);
+ view_dispatcher_set_event_callback_context(lfrfid->view_dispatcher, lfrfid);
+ view_dispatcher_set_custom_event_callback(
+ lfrfid->view_dispatcher, lfrfid_debug_custom_event_callback);
+ view_dispatcher_set_navigation_event_callback(
+ lfrfid->view_dispatcher, lfrfid_debug_back_event_callback);
+
+ // Open GUI record
+ lfrfid->gui = furi_record_open(RECORD_GUI);
+
+ // Open Notification record
+ lfrfid->notifications = furi_record_open(RECORD_NOTIFICATION);
+
+ // Submenu
+ lfrfid->submenu = submenu_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewSubmenu, submenu_get_view(lfrfid->submenu));
+
+ // Dialog
+ lfrfid->dialog_ex = dialog_ex_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewDialogEx, dialog_ex_get_view(lfrfid->dialog_ex));
+
+ // Popup
+ lfrfid->popup = popup_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewPopup, popup_get_view(lfrfid->popup));
+
+ // Widget
+ lfrfid->widget = widget_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewWidget, widget_get_view(lfrfid->widget));
+
+ // Text Input
+ lfrfid->text_input = text_input_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewTextInput, text_input_get_view(lfrfid->text_input));
+
+ // Byte Input
+ lfrfid->byte_input = byte_input_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewByteInput, byte_input_get_view(lfrfid->byte_input));
+
+ // Read custom view
+ lfrfid->read_view = lfrfid_view_read_alloc();
+ view_dispatcher_add_view(
+ lfrfid->view_dispatcher, LfRfidViewRead, lfrfid_view_read_get_view(lfrfid->read_view));
+
+ return lfrfid;
+}
+
+static void lfrfid_free(LfRfid* lfrfid) {
+ furi_assert(lfrfid);
+
+ string_clear(lfrfid->raw_file_name);
+ string_clear(lfrfid->file_name);
+ string_clear(lfrfid->file_path);
+ protocol_dict_free(lfrfid->dict);
+
+ lfrfid_worker_free(lfrfid->lfworker);
+
+ if(lfrfid->rpc_ctx) {
+ rpc_system_app_set_callback(lfrfid->rpc_ctx, NULL, NULL);
+ rpc_system_app_send_exited(lfrfid->rpc_ctx);
+ }
+
+ free(lfrfid->new_key_data);
+ free(lfrfid->old_key_data);
+
+ // Submenu
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewSubmenu);
+ submenu_free(lfrfid->submenu);
+
+ // DialogEx
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewDialogEx);
+ dialog_ex_free(lfrfid->dialog_ex);
+
+ // Popup
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewPopup);
+ popup_free(lfrfid->popup);
+
+ // Widget
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewWidget);
+ widget_free(lfrfid->widget);
+
+ // TextInput
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewTextInput);
+ text_input_free(lfrfid->text_input);
+
+ // ByteInput
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewByteInput);
+ byte_input_free(lfrfid->byte_input);
+
+ // Read custom view
+ view_dispatcher_remove_view(lfrfid->view_dispatcher, LfRfidViewRead);
+ lfrfid_view_read_free(lfrfid->read_view);
+
+ // View Dispatcher
+ view_dispatcher_free(lfrfid->view_dispatcher);
+
+ // Scene Manager
+ scene_manager_free(lfrfid->scene_manager);
+
+ // GUI
+ furi_record_close(RECORD_GUI);
+ lfrfid->gui = NULL;
+
+ // Notifications
+ furi_record_close(RECORD_NOTIFICATION);
+ lfrfid->notifications = NULL;
+
+ furi_record_close(RECORD_STORAGE);
+ furi_record_close(RECORD_DIALOGS);
+
+ free(lfrfid);
+}
+
+int32_t lfrfid_app(void* p) {
+ LfRfid* app = lfrfid_alloc();
+ char* args = p;
+
+ lfrfid_make_app_folder(app);
+
+ if(args && strlen(args)) {
+ uint32_t rpc_ctx_ptr = 0;
+ if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
+ app->rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
+ rpc_system_app_set_callback(app->rpc_ctx, rpc_command_callback, app);
+ rpc_system_app_send_started(app->rpc_ctx);
+ view_dispatcher_attach_to_gui(
+ app->view_dispatcher, app->gui, ViewDispatcherTypeDesktop);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRpc);
+ } else {
+ string_set_str(app->file_path, args);
+ lfrfid_load_key_data(app, app->file_path, true);
+ view_dispatcher_attach_to_gui(
+ app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
+ }
+
+ } else {
+ view_dispatcher_attach_to_gui(
+ app->view_dispatcher, app->gui, ViewDispatcherTypeFullscreen);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneStart);
+ }
+
+ view_dispatcher_run(app->view_dispatcher);
+
+ lfrfid_free(app);
+
+ return 0;
+}
+
+bool lfrfid_save_key(LfRfid* app) {
+ furi_assert(app);
+
+ bool result = false;
+
+ lfrfid_make_app_folder(app);
+
+ if(string_end_with_str_p(app->file_path, LFRFID_APP_EXTENSION)) {
+ size_t filename_start = string_search_rchar(app->file_path, '/');
+ string_left(app->file_path, filename_start);
+ }
+
+ string_cat_printf(
+ app->file_path, "/%s%s", string_get_cstr(app->file_name), LFRFID_APP_EXTENSION);
+
+ result = lfrfid_save_key_data(app, app->file_path);
+ return result;
+}
+
+bool lfrfid_load_key_from_file_select(LfRfid* app) {
+ furi_assert(app);
+
+ bool result = dialog_file_browser_show(
+ app->dialogs,
+ app->file_path,
+ app->file_path,
+ LFRFID_APP_EXTENSION,
+ true,
+ &I_125_10px,
+ true);
+
+ if(result) {
+ result = lfrfid_load_key_data(app, app->file_path, true);
+ }
+
+ return result;
+}
+
+bool lfrfid_delete_key(LfRfid* app) {
+ furi_assert(app);
+
+ return storage_simply_remove(app->storage, string_get_cstr(app->file_path));
+}
+
+bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog) {
+ bool result = false;
+
+ do {
+ app->protocol_id = lfrfid_dict_file_load(app->dict, string_get_cstr(path));
+ if(app->protocol_id == PROTOCOL_NO) break;
+
+ path_extract_filename(path, app->file_name, true);
+ result = true;
+ } while(0);
+
+ if((!result) && (show_dialog)) {
+ dialog_message_show_storage_error(app->dialogs, "Cannot load\nkey file");
+ }
+
+ return result;
+}
+
+bool lfrfid_save_key_data(LfRfid* app, string_t path) {
+ bool result = lfrfid_dict_file_save(app->dict, app->protocol_id, string_get_cstr(path));
+
+ if(!result) {
+ dialog_message_show_storage_error(app->dialogs, "Cannot save\nkey file");
+ }
+
+ return result;
+}
+
+void lfrfid_make_app_folder(LfRfid* app) {
+ furi_assert(app);
+
+ if(!storage_simply_mkdir(app->storage, LFRFID_APP_FOLDER)) {
+ dialog_message_show_storage_error(app->dialogs, "Cannot create\napp folder");
+ }
+}
+
+void lfrfid_text_store_set(LfRfid* app, const char* text, ...) {
+ furi_assert(app);
+ va_list args;
+ va_start(args, text);
+
+ vsnprintf(app->text_store, LFRFID_TEXT_STORE_SIZE, text, args);
+
+ va_end(args);
+}
+
+void lfrfid_text_store_clear(LfRfid* app) {
+ furi_assert(app);
+ memset(app->text_store, 0, sizeof(app->text_store));
+}
+
+void lfrfid_popup_timeout_callback(void* context) {
+ LfRfid* app = context;
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventPopupClosed);
+}
+
+void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context) {
+ LfRfid* app = context;
+ if(type == InputTypeShort) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, result);
+ }
+}
+
+void lfrfid_text_input_callback(void* context) {
+ LfRfid* app = context;
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventNext);
+}
\ No newline at end of file
diff --git a/applications/lfrfid/lfrfid_app.cpp b/applications/lfrfid/lfrfid_app.cpp
deleted file mode 100644
index 9373ca8c7..000000000
--- a/applications/lfrfid/lfrfid_app.cpp
+++ /dev/null
@@ -1,218 +0,0 @@
-#include "lfrfid_app.h"
-#include "assets_icons.h"
-#include
-#include "m-string.h"
-#include "scene/lfrfid_app_scene_start.h"
-#include "scene/lfrfid_app_scene_read.h"
-#include "scene/lfrfid_app_scene_read_success.h"
-#include "scene/lfrfid_app_scene_retry_confirm.h"
-#include "scene/lfrfid_app_scene_exit_confirm.h"
-#include "scene/lfrfid_app_scene_read_menu.h"
-#include "scene/lfrfid_app_scene_write.h"
-#include "scene/lfrfid_app_scene_write_success.h"
-#include "scene/lfrfid_app_scene_emulate.h"
-#include "scene/lfrfid_app_scene_save_name.h"
-#include "scene/lfrfid_app_scene_save_success.h"
-#include "scene/lfrfid_app_scene_select_key.h"
-#include "scene/lfrfid_app_scene_saved_key_menu.h"
-#include "scene/lfrfid_app_scene_save_data.h"
-#include "scene/lfrfid_app_scene_save_type.h"
-#include "scene/lfrfid_app_scene_saved_info.h"
-#include "scene/lfrfid_app_scene_delete_confirm.h"
-#include "scene/lfrfid_app_scene_delete_success.h"
-#include "scene/lfrfid_app_scene_rpc.h"
-#include "scene/lfrfid_app_scene_extra_actions.h"
-#include "scene/lfrfid_app_scene_raw_info.h"
-#include "scene/lfrfid_app_scene_raw_name.h"
-#include "scene/lfrfid_app_scene_raw_read.h"
-#include "scene/lfrfid_app_scene_raw_success.h"
-
-#include
-#include
-
-#include
-
-const char* LfRfidApp::app_folder = ANY_PATH("lfrfid");
-const char* LfRfidApp::app_sd_folder = EXT_PATH("lfrfid");
-const char* LfRfidApp::app_extension = ".rfid";
-const char* LfRfidApp::app_filetype = "Flipper RFID key";
-
-LfRfidApp::LfRfidApp()
- : scene_controller{this}
- , notification{RECORD_NOTIFICATION}
- , storage{RECORD_STORAGE}
- , dialogs{RECORD_DIALOGS}
- , text_store(40) {
- string_init(file_name);
- string_init(raw_file_name);
- string_init_set_str(file_path, app_folder);
-
- dict = protocol_dict_alloc(lfrfid_protocols, LFRFIDProtocolMax);
-
- size_t size = protocol_dict_get_max_data_size(dict);
- new_key_data = (uint8_t*)malloc(size);
- old_key_data = (uint8_t*)malloc(size);
-
- lfworker = lfrfid_worker_alloc(dict);
-}
-
-LfRfidApp::~LfRfidApp() {
- string_clear(raw_file_name);
- string_clear(file_name);
- string_clear(file_path);
- protocol_dict_free(dict);
-
- lfrfid_worker_free(lfworker);
-
- if(rpc_ctx) {
- rpc_system_app_set_callback(rpc_ctx, NULL, NULL);
- rpc_system_app_send_exited(rpc_ctx);
- }
-
- free(new_key_data);
- free(old_key_data);
-}
-
-static void rpc_command_callback(RpcAppSystemEvent rpc_event, void* context) {
- furi_assert(context);
- LfRfidApp* app = static_cast(context);
-
- if(rpc_event == RpcAppEventSessionClose) {
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::RpcSessionClose;
- app->view_controller.send_event(&event);
- // Detach RPC
- rpc_system_app_set_callback(app->rpc_ctx, NULL, NULL);
- app->rpc_ctx = NULL;
- } else if(rpc_event == RpcAppEventAppExit) {
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Exit;
- app->view_controller.send_event(&event);
- } else if(rpc_event == RpcAppEventLoadFile) {
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::RpcLoadFile;
- app->view_controller.send_event(&event);
- } else {
- rpc_system_app_confirm(app->rpc_ctx, rpc_event, false);
- }
-}
-
-void LfRfidApp::run(void* _args) {
- const char* args = reinterpret_cast(_args);
-
- make_app_folder();
-
- if(args && strlen(args)) {
- uint32_t rpc_ctx_ptr = 0;
- if(sscanf(args, "RPC %lX", &rpc_ctx_ptr) == 1) {
- rpc_ctx = (RpcAppSystem*)rpc_ctx_ptr;
- rpc_system_app_set_callback(rpc_ctx, rpc_command_callback, this);
- rpc_system_app_send_started(rpc_ctx);
- view_controller.attach_to_gui(ViewDispatcherTypeDesktop);
- scene_controller.add_scene(SceneType::Rpc, new LfRfidAppSceneRpc());
- scene_controller.process(100, SceneType::Rpc);
- } else {
- string_set_str(file_path, args);
- load_key_data(file_path, true);
- view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
- scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
- scene_controller.process(100, SceneType::Emulate);
- }
-
- } else {
- view_controller.attach_to_gui(ViewDispatcherTypeFullscreen);
- scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart());
- scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead());
- scene_controller.add_scene(SceneType::RetryConfirm, new LfRfidAppSceneRetryConfirm());
- scene_controller.add_scene(SceneType::ExitConfirm, new LfRfidAppSceneExitConfirm());
- scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess());
- scene_controller.add_scene(SceneType::ReadKeyMenu, new LfRfidAppSceneReadKeyMenu());
- scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite());
- scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess());
- scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate());
- scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName());
- scene_controller.add_scene(SceneType::SaveSuccess, new LfRfidAppSceneSaveSuccess());
- scene_controller.add_scene(SceneType::SelectKey, new LfRfidAppSceneSelectKey());
- scene_controller.add_scene(SceneType::SavedKeyMenu, new LfRfidAppSceneSavedKeyMenu());
- scene_controller.add_scene(SceneType::SaveData, new LfRfidAppSceneSaveData());
- scene_controller.add_scene(SceneType::SaveType, new LfRfidAppSceneSaveType());
- scene_controller.add_scene(SceneType::SavedInfo, new LfRfidAppSceneSavedInfo());
- scene_controller.add_scene(SceneType::DeleteConfirm, new LfRfidAppSceneDeleteConfirm());
- scene_controller.add_scene(SceneType::DeleteSuccess, new LfRfidAppSceneDeleteSuccess());
- scene_controller.add_scene(SceneType::ExtraActions, new LfRfidAppSceneExtraActions());
- scene_controller.add_scene(SceneType::RawInfo, new LfRfidAppSceneRawInfo());
- scene_controller.add_scene(SceneType::RawName, new LfRfidAppSceneRawName());
- scene_controller.add_scene(SceneType::RawRead, new LfRfidAppSceneRawRead());
- scene_controller.add_scene(SceneType::RawSuccess, new LfRfidAppSceneRawSuccess());
- scene_controller.process(100);
- }
-}
-
-bool LfRfidApp::save_key() {
- bool result = false;
-
- make_app_folder();
-
- if(string_end_with_str_p(file_path, app_extension)) {
- size_t filename_start = string_search_rchar(file_path, '/');
- string_left(file_path, filename_start);
- }
-
- string_cat_printf(file_path, "/%s%s", string_get_cstr(file_name), app_extension);
-
- result = save_key_data(file_path);
- return result;
-}
-
-bool LfRfidApp::load_key_from_file_select(bool need_restore) {
- if(!need_restore) {
- string_set_str(file_path, app_folder);
- }
-
- bool result = dialog_file_browser_show(
- dialogs, file_path, file_path, app_extension, true, &I_125_10px, true);
-
- if(result) {
- result = load_key_data(file_path, true);
- }
-
- return result;
-}
-
-bool LfRfidApp::delete_key() {
- return storage_simply_remove(storage, string_get_cstr(file_path));
-}
-
-bool LfRfidApp::load_key_data(string_t path, bool show_dialog) {
- bool result = false;
-
- do {
- protocol_id = lfrfid_dict_file_load(dict, string_get_cstr(path));
- if(protocol_id == PROTOCOL_NO) break;
-
- path_extract_filename(path, file_name, true);
- result = true;
- } while(0);
-
- if((!result) && (show_dialog)) {
- dialog_message_show_storage_error(dialogs, "Cannot load\nkey file");
- }
-
- return result;
-}
-
-bool LfRfidApp::save_key_data(string_t path) {
- bool result = lfrfid_dict_file_save(dict, protocol_id, string_get_cstr(path));
-
- if(!result) {
- dialog_message_show_storage_error(dialogs, "Cannot save\nkey file");
- }
-
- return result;
-}
-
-void LfRfidApp::make_app_folder() {
- if(!storage_simply_mkdir(storage, app_folder)) {
- dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
- }
-}
diff --git a/applications/lfrfid/lfrfid_app.h b/applications/lfrfid/lfrfid_app.h
deleted file mode 100644
index 153218dbd..000000000
--- a/applications/lfrfid/lfrfid_app.h
+++ /dev/null
@@ -1,137 +0,0 @@
-#pragma once
-#include "m-string.h"
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-
-#include
-#include
-#include
-#include
-#include
-#include "view/container_vm.h"
-
-#include
-#include
-#include
-
-#include "rpc/rpc_app.h"
-
-#include
-#include
-#include
-#include
-
-#define LFRFID_KEY_NAME_SIZE 22
-
-class LfRfidApp {
-public:
- enum class EventType : uint8_t {
- GENERIC_EVENT_ENUM_VALUES,
- Next,
- MenuSelected,
- Stay,
- Retry,
- Exit,
- ReadEventSenseStart,
- ReadEventSenseEnd,
- ReadEventSenseCardStart,
- ReadEventSenseCardEnd,
- ReadEventStartASK,
- ReadEventStartPSK,
- ReadEventDone,
- ReadEventOverrun,
- ReadEventError,
- WriteEventOK,
- WriteEventProtocolCannotBeWritten,
- WriteEventFobCannotBeWritten,
- WriteEventTooLongToWrite,
- RpcLoadFile,
- RpcSessionClose,
- };
-
- enum class SceneType : uint8_t {
- GENERIC_SCENE_ENUM_VALUES,
- Read,
- ReadSuccess,
- RetryConfirm,
- ExitConfirm,
- ReadKeyMenu,
- Write,
- WriteSuccess,
- Emulate,
- SaveName,
- SaveSuccess,
- SelectKey,
- SavedKeyMenu,
- SaveData,
- SaveType,
- SavedInfo,
- DeleteConfirm,
- DeleteSuccess,
- Rpc,
- ExtraActions,
- RawInfo,
- RawName,
- RawRead,
- RawSuccess,
- };
-
- class Event {
- public:
- union {
- int32_t signed_int;
- } payload;
-
- EventType type;
- };
-
- SceneController, LfRfidApp> scene_controller;
- ViewController
- view_controller;
-
- ~LfRfidApp();
- LfRfidApp();
-
- RecordController notification;
- RecordController storage;
- RecordController dialogs;
-
- TextStore text_store;
-
- string_t file_path;
-
- RpcAppSystem* rpc_ctx;
-
- void run(void* args);
-
- static const char* app_folder;
- static const char* app_sd_folder;
- static const char* app_extension;
- static const char* app_filetype;
-
- bool save_key();
- bool load_key_from_file_select(bool need_restore);
- bool delete_key();
-
- bool load_key_data(string_t path, bool show_dialog);
- bool save_key_data(string_t path);
-
- void make_app_folder();
-
- ProtocolDict* dict;
- LFRFIDWorker* lfworker;
- string_t file_name;
- ProtocolId protocol_id;
- LFRFIDWorkerReadType read_type;
-
- uint8_t* old_key_data;
- uint8_t* new_key_data;
-
- string_t raw_file_name;
-};
diff --git a/applications/lfrfid/lfrfid_app_launcher.cpp b/applications/lfrfid/lfrfid_app_launcher.cpp
deleted file mode 100644
index 2855850f5..000000000
--- a/applications/lfrfid/lfrfid_app_launcher.cpp
+++ /dev/null
@@ -1,10 +0,0 @@
-#include "lfrfid_app.h"
-
-// app enter function
-extern "C" int32_t lfrfid_app(void* args) {
- LfRfidApp* app = new LfRfidApp();
- app->run(args);
- delete app;
-
- return 0;
-}
diff --git a/applications/lfrfid/lfrfid_cli.c b/applications/lfrfid/lfrfid_cli.c
index 9a6930a67..281a0e963 100644
--- a/applications/lfrfid/lfrfid_cli.c
+++ b/applications/lfrfid/lfrfid_cli.c
@@ -114,7 +114,7 @@ static void lfrfid_cli_read(Cli* cli, string_t args) {
string_t info;
string_init(info);
protocol_dict_render_data(dict, info, context.protocol);
- if(string_size(info) > 0) {
+ if(!string_empty_p(info)) {
printf("%s\r\n", string_get_cstr(info));
}
string_clear(info);
diff --git a/applications/lfrfid/lfrfid_i.h b/applications/lfrfid/lfrfid_i.h
new file mode 100644
index 000000000..77e872527
--- /dev/null
+++ b/applications/lfrfid/lfrfid_i.h
@@ -0,0 +1,145 @@
+#pragma once
+
+#include "m-string.h"
+
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+
+#define LFRFID_KEY_NAME_SIZE 22
+#define LFRFID_TEXT_STORE_SIZE 40
+
+#define LFRFID_APP_FOLDER ANY_PATH("lfrfid")
+#define LFRFID_SD_FOLDER EXT_PATH("lfrfid")
+#define LFRFID_APP_EXTENSION ".rfid"
+#define LFRFID_APP_SHADOW_EXTENSION ".shd"
+
+#define LFRFID_APP_RAW_ASK_EXTENSION ".ask.raw"
+#define LFRFID_APP_RAW_PSK_EXTENSION ".psk.raw"
+
+enum LfRfidCustomEvent {
+ LfRfidEventNext = 100,
+ LfRfidEventExit,
+ LfRfidEventPopupClosed,
+ LfRfidEventReadSenseStart,
+ LfRfidEventReadSenseEnd,
+ LfRfidEventReadSenseCardStart,
+ LfRfidEventReadSenseCardEnd,
+ LfRfidEventReadStartASK,
+ LfRfidEventReadStartPSK,
+ LfRfidEventReadDone,
+ LfRfidEventReadOverrun,
+ LfRfidEventReadError,
+ LfRfidEventWriteOK,
+ LfRfidEventWriteProtocolCannotBeWritten,
+ LfRfidEventWriteFobCannotBeWritten,
+ LfRfidEventWriteTooLongToWrite,
+ LfRfidEventRpcLoadFile,
+ LfRfidEventRpcSessionClose,
+};
+
+typedef enum {
+ LfRfidRpcStateIdle,
+ LfRfidRpcStateEmulating,
+} LfRfidRpcState;
+
+typedef struct LfRfid LfRfid;
+
+struct LfRfid {
+ LFRFIDWorker* lfworker;
+ ViewDispatcher* view_dispatcher;
+ Gui* gui;
+ NotificationApp* notifications;
+ SceneManager* scene_manager;
+ Storage* storage;
+ DialogsApp* dialogs;
+ Widget* widget;
+
+ char text_store[LFRFID_TEXT_STORE_SIZE + 1];
+ string_t file_path;
+ string_t file_name;
+ string_t raw_file_name;
+
+ ProtocolDict* dict;
+ ProtocolId protocol_id;
+ ProtocolId protocol_id_next;
+ LFRFIDWorkerReadType read_type;
+
+ uint8_t* old_key_data;
+ uint8_t* new_key_data;
+
+ RpcAppSystem* rpc_ctx;
+ LfRfidRpcState rpc_state;
+
+ // Common Views
+ Submenu* submenu;
+ DialogEx* dialog_ex;
+ Popup* popup;
+ TextInput* text_input;
+ ByteInput* byte_input;
+
+ // Custom views
+ LfRfidReadView* read_view;
+};
+
+typedef enum {
+ LfRfidViewSubmenu,
+ LfRfidViewDialogEx,
+ LfRfidViewPopup,
+ LfRfidViewWidget,
+ LfRfidViewTextInput,
+ LfRfidViewByteInput,
+ LfRfidViewRead,
+} LfRfidView;
+
+bool lfrfid_save_key(LfRfid* app);
+
+bool lfrfid_load_key_from_file_select(LfRfid* app);
+
+bool lfrfid_delete_key(LfRfid* app);
+
+bool lfrfid_load_key_data(LfRfid* app, string_t path, bool show_dialog);
+
+bool lfrfid_save_key_data(LfRfid* app, string_t path);
+
+void lfrfid_make_app_folder(LfRfid* app);
+
+void lfrfid_text_store_set(LfRfid* app, const char* text, ...);
+
+void lfrfid_text_store_clear(LfRfid* app);
+
+void lfrfid_popup_timeout_callback(void* context);
+
+void lfrfid_widget_callback(GuiButtonType result, InputType type, void* context);
+
+void lfrfid_text_input_callback(void* context);
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp
deleted file mode 100644
index 58ff4dcdf..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
-#include "lfrfid_app_scene_delete_confirm.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneDeleteConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
- string_init(string_data);
- string_init(string_header);
-
- auto container = app->view_controller.get();
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Left, "Back");
- button->set_callback(app, LfRfidAppSceneDeleteConfirm::back_callback);
-
- button = container->add();
- button->set_type(ButtonElement::Type::Right, "Delete");
- button->set_callback(app, LfRfidAppSceneDeleteConfirm::delete_callback);
-
- auto line_1 = container->add();
- auto line_2 = container->add();
- auto line_3 = container->add();
-
- size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
- uint8_t* data = (uint8_t*)malloc(size);
- protocol_dict_get_data(app->dict, app->protocol_id, data, size);
- for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
- if(i != 0) {
- string_cat_printf(string_data, " ");
- }
-
- string_cat_printf(string_data, "%02X", data[i]);
- }
- free(data);
-
- string_printf(string_header, "Delete %s?", string_get_cstr(app->file_name));
- line_1->set_text(
- string_get_cstr(string_header), 64, 0, 128 - 2, AlignCenter, AlignTop, FontPrimary);
- line_2->set_text(
- string_get_cstr(string_data), 64, 19, 0, AlignCenter, AlignTop, FontSecondary);
- line_3->set_text(
- protocol_dict_get_name(app->dict, app->protocol_id),
- 64,
- 49,
- 0,
- AlignCenter,
- AlignBottom,
- FontSecondary);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneDeleteConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- app->delete_key();
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteSuccess);
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Stay) {
- app->scene_controller.switch_to_previous_scene();
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Back) {
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneDeleteConfirm::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
- string_clear(string_data);
- string_clear(string_header);
-}
-
-void LfRfidAppSceneDeleteConfirm::back_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Stay;
- app->view_controller.send_event(&event);
-}
-
-void LfRfidAppSceneDeleteConfirm::delete_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h
deleted file mode 100644
index f9daed543..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_delete_confirm.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneDeleteConfirm : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void back_callback(void* context);
- static void delete_callback(void* context);
-
- string_t string_header;
- string_t string_data;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp
deleted file mode 100644
index 9820338d1..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "lfrfid_app_scene_delete_success.h"
-
-void LfRfidAppSceneDeleteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto popup = app->view_controller.get();
-
- popup->set_icon(0, 2, &I_DolphinMafia_115x62);
- popup->set_header("Deleted", 83, 19, AlignLeft, AlignBottom);
- popup->set_context(app);
- popup->set_callback(LfRfidAppSceneDeleteSuccess::timeout_callback);
- popup->set_timeout(1500);
- popup->enable_timeout();
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneDeleteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Back) {
- app->scene_controller.search_and_switch_to_previous_scene(
- {LfRfidApp::SceneType::SelectKey});
-
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneDeleteSuccess::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneDeleteSuccess::timeout_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Back;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h b/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h
deleted file mode 100644
index 009b9f25d..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_delete_success.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneDeleteSuccess : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void timeout_callback(void* context);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp b/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp
deleted file mode 100644
index 02cb011d1..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-#include "lfrfid_app_scene_emulate.h"
-#include
-#include
-
-void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool /* need_restore */) {
- DOLPHIN_DEED(DolphinDeedRfidEmulate);
- auto popup = app->view_controller.get();
-
- popup->set_header("Emulating", 89, 30, AlignCenter, AlignTop);
- if(string_size(app->file_name)) {
- popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
- } else {
- popup->set_text(
- protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
- }
- popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
-
- app->view_controller.switch_to();
- lfrfid_worker_start_thread(app->lfworker);
- lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
- notification_message(app->notification, &sequence_blink_start_magenta);
-}
-
-bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- UNUSED(app);
- UNUSED(event);
- bool consumed = false;
- return consumed;
-}
-
-void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
- lfrfid_worker_stop(app->lfworker);
- lfrfid_worker_stop_thread(app->lfworker);
- notification_message(app->notification, &sequence_blink_stop);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h b/applications/lfrfid/scene/lfrfid_app_scene_emulate.h
deleted file mode 100644
index 13d2b857d..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_emulate.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneEmulate : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp
deleted file mode 100644
index be070b40e..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "lfrfid_app_scene_exit_confirm.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneExitConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto container = app->view_controller.get();
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Left, "Exit");
- button->set_callback(app, LfRfidAppSceneExitConfirm::exit_callback);
-
- button = container->add();
- button->set_type(ButtonElement::Type::Right, "Stay");
- button->set_callback(app, LfRfidAppSceneExitConfirm::stay_callback);
-
- auto line_1 = container->add();
- auto line_2 = container->add();
-
- line_1->set_text("Exit to RFID Menu?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
- line_2->set_text(
- "All unsaved data will be lost!", 64, 31, 0, AlignCenter, AlignBottom, FontSecondary);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneExitConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start});
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Stay) {
- app->scene_controller.switch_to_previous_scene();
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Back) {
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneExitConfirm::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneExitConfirm::exit_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
-
-void LfRfidAppSceneExitConfirm::stay_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Stay;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h
deleted file mode 100644
index a0a102325..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_exit_confirm.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneExitConfirm : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void exit_callback(void* context);
- static void stay_callback(void* context);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp b/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp
deleted file mode 100644
index ea4f03dbb..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.cpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#include "lfrfid_app_scene_extra_actions.h"
-
-typedef enum {
- SubmenuASK,
- SubmenuPSK,
- SubmenuRAW,
-} SubmenuIndex;
-
-void LfRfidAppSceneExtraActions::on_enter(LfRfidApp* app, bool need_restore) {
- auto submenu = app->view_controller.get();
-
- 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();
-}
-
-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()->clean();
-}
-
-void LfRfidAppSceneExtraActions::submenu_callback(void* context, uint32_t index) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
-
- event.type = LfRfidApp::EventType::MenuSelected;
- event.payload.signed_int = index;
-
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h b/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h
deleted file mode 100644
index dcd746146..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_extra_actions.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneExtraActions : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp
deleted file mode 100644
index ce3634b2a..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.cpp
+++ /dev/null
@@ -1,77 +0,0 @@
-#include "lfrfid_app_scene_raw_info.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-static void ok_callback(void* context) {
- LfRfidApp* app = static_cast(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(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();
-
- bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
- if(!sd_exist) {
- auto icon = container->add();
- icon->set_icon(0, 0, &I_SDQuestion_35x43);
- auto line = container->add();
- 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();
- 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();
- line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Center, "OK");
- button->set_callback(app, ok_callback);
- }
-
- app->view_controller.switch_to();
-}
-
-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()->clean();
- string_clear(string_info);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h
deleted file mode 100644
index eecca1436..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_info.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRawInfo : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp
deleted file mode 100644
index 0ad346198..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.cpp
+++ /dev/null
@@ -1,46 +0,0 @@
-
-#include "lfrfid_app_scene_raw_name.h"
-#include "m-string.h"
-#include
-#include
-
-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();
- 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();
-}
-
-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()->clean();
-}
-
-void LfRfidAppSceneRawName::save_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h
deleted file mode 100644
index 225d135e5..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_name.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRawName : public GenericScene {
-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);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp
deleted file mode 100644
index 0d04e6bc7..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-#include "lfrfid_app_scene_raw_read.h"
-#include
-
-#define RAW_READ_TIME 5000
-
-static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* ctx) {
- LfRfidApp* app = static_cast(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(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();
- popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
- app->view_controller.switch_to();
- 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();
-
- 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()->clean();
- lfrfid_worker_stop(app->lfworker);
- lfrfid_worker_stop_thread(app->lfworker);
- furi_timer_free(timer);
- string_clear(string_file_name);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h
deleted file mode 100644
index 09ef74639..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_read.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRawRead : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp
deleted file mode 100644
index 227ab580a..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "lfrfid_app_scene_raw_success.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneRawSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
- string_init(string_info);
-
- string_printf(string_info, "RAW RFID read success!\r\n");
- string_cat_printf(string_info, "Now you can analyze files\r\n");
- string_cat_printf(string_info, "Or send them to developers");
-
- auto container = app->view_controller.get();
-
- auto line = container->add();
- line->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Center, "OK");
- button->set_callback(app, LfRfidAppSceneRawSuccess::ok_callback);
-
- app->view_controller.switch_to();
-}
-
-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()->clean();
- string_clear(string_info);
-}
-
-void LfRfidAppSceneRawSuccess::ok_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h b/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h
deleted file mode 100644
index 0a0b0116b..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_raw_success.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRawSuccess : public GenericScene {
-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);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read.cpp
deleted file mode 100644
index 120eb1a07..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read.cpp
+++ /dev/null
@@ -1,100 +0,0 @@
-#include "lfrfid_app_scene_read.h"
-#include
-
-static void lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* ctx) {
- LfRfidApp* app = static_cast(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();
-
- DOLPHIN_DEED(DolphinDeedRfidRead);
- if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
- popup->set_header("Reading\nLF RFID\nPSK", 89, 30, AlignCenter, AlignTop);
- } else {
- popup->set_header("Reading\nLF RFID\nASK", 89, 30, AlignCenter, AlignTop);
- }
-
- popup->set_icon(0, 3, &I_RFIDDolphinReceive_97x61);
-
- app->view_controller.switch_to();
- lfrfid_worker_start_thread(app->lfworker);
- lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app);
-
- notification_message(app->notification, &sequence_blink_start_cyan);
-}
-
-bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = true;
- auto popup = app->view_controller.get();
-
- 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()->clean();
- lfrfid_worker_stop(app->lfworker);
- lfrfid_worker_stop_thread(app->lfworker);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read.h b/applications/lfrfid/scene/lfrfid_app_scene_read.h
deleted file mode 100644
index b5035b72a..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRead : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp
deleted file mode 100644
index aa3b3f1fb..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.cpp
+++ /dev/null
@@ -1,60 +0,0 @@
-#include "lfrfid_app_scene_read_menu.h"
-
-typedef enum {
- SubmenuSave,
- SubmenuEmulate,
- SubmenuWrite,
-} SubmenuIndex;
-
-void LfRfidAppSceneReadKeyMenu::on_enter(LfRfidApp* app, bool need_restore) {
- auto submenu = app->view_controller.get();
-
- submenu->add_item("Save", SubmenuSave, submenu_callback, app);
- submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
- submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
-
- if(need_restore) {
- submenu->set_selected_item(submenu_item_selected);
- }
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneReadKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::MenuSelected) {
- submenu_item_selected = event->payload.signed_int;
- switch(event->payload.signed_int) {
- case SubmenuWrite:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
- break;
- case SubmenuSave:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
- break;
- case SubmenuEmulate:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
- break;
- }
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Back) {
- app->scene_controller.switch_to_previous_scene();
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneReadKeyMenu::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneReadKeyMenu::submenu_callback(void* context, uint32_t index) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
-
- event.type = LfRfidApp::EventType::MenuSelected;
- event.payload.signed_int = index;
-
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h
deleted file mode 100644
index 2b50b96f9..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read_menu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneReadKeyMenu : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp
deleted file mode 100644
index 277b43a3e..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.cpp
+++ /dev/null
@@ -1,96 +0,0 @@
-#include "lfrfid_app_scene_read_success.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
- string_init(string_info);
- string_init(string_header);
-
- string_init_printf(
- string_header,
- "%s[%s]",
- protocol_dict_get_name(app->dict, app->protocol_id),
- protocol_dict_get_manufacturer(app->dict, app->protocol_id));
-
- size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
- uint8_t* data = (uint8_t*)malloc(size);
- protocol_dict_get_data(app->dict, app->protocol_id, data, size);
- for(uint8_t i = 0; i < size; i++) {
- if(i != 0) {
- string_cat_printf(string_info, " ");
- }
-
- if(i >= 9) {
- string_cat_printf(string_info, "...");
- break;
- } else {
- string_cat_printf(string_info, "%02X", data[i]);
- }
- }
- free(data);
-
- string_t render_data;
- string_init(render_data);
- protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
- string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
- string_clear(render_data);
-
- auto container = app->view_controller.get();
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Left, "Retry");
- button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback);
-
- button = container->add();
- button->set_type(ButtonElement::Type::Right, "More");
- button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback);
-
- auto header = container->add();
- header->set_text(string_get_cstr(string_header), 0, 2, 0, AlignLeft, AlignTop, FontPrimary);
-
- auto text = container->add();
- text->set_text(string_get_cstr(string_info), 0, 16, 0, AlignLeft, AlignTop, FontSecondary);
-
- app->view_controller.switch_to();
-
- notification_message_block(app->notification, &sequence_set_green_255);
-}
-
-bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadKeyMenu);
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Retry) {
- app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::RetryConfirm});
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Back) {
- app->scene_controller.switch_to_next_scene({LfRfidApp::SceneType::ExitConfirm});
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) {
- notification_message_block(app->notification, &sequence_reset_green);
- app->view_controller.get()->clean();
- string_clear(string_info);
- string_clear(string_header);
-}
-
-void LfRfidAppSceneReadSuccess::back_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Retry;
- app->view_controller.send_event(&event);
-}
-
-void LfRfidAppSceneReadSuccess::more_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h b/applications/lfrfid/scene/lfrfid_app_scene_read_success.h
deleted file mode 100644
index 6d90f6310..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_read_success.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneReadSuccess : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void back_callback(void* context);
- static void more_callback(void* context);
-
- string_t string_header;
- string_t string_info;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp
deleted file mode 100644
index c18122323..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.cpp
+++ /dev/null
@@ -1,59 +0,0 @@
-#include "lfrfid_app_scene_retry_confirm.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneRetryConfirm::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto container = app->view_controller.get();
-
- auto button = container->add();
- button->set_type(ButtonElement::Type::Left, "Exit");
- button->set_callback(app, LfRfidAppSceneRetryConfirm::exit_callback);
-
- button = container->add();
- button->set_type(ButtonElement::Type::Right, "Stay");
- button->set_callback(app, LfRfidAppSceneRetryConfirm::stay_callback);
-
- auto line_1 = container->add();
- auto line_2 = container->add();
-
- line_1->set_text("Return to Reading?", 64, 19, 128 - 2, AlignCenter, AlignBottom, FontPrimary);
- line_2->set_text(
- "All unsaved data will be lost!", 64, 29, 0, AlignCenter, AlignBottom, FontSecondary);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneRetryConfirm::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Read});
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Stay) {
- app->scene_controller.switch_to_previous_scene();
- consumed = true;
- } else if(event->type == LfRfidApp::EventType::Back) {
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneRetryConfirm::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneRetryConfirm::exit_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
-
-void LfRfidAppSceneRetryConfirm::stay_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Stay;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h b/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h
deleted file mode 100644
index 01b7329c9..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_retry_confirm.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRetryConfirm : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void exit_callback(void* context);
- static void stay_callback(void* context);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp b/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp
deleted file mode 100644
index c2e5ec2a6..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.cpp
+++ /dev/null
@@ -1,66 +0,0 @@
-#include "lfrfid_app_scene_rpc.h"
-#include
-#include
-#include
-
-void LfRfidAppSceneRpc::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto popup = app->view_controller.get();
-
- popup->set_header("LF RFID", 89, 42, AlignCenter, AlignBottom);
- popup->set_text("RPC mode", 89, 44, AlignCenter, AlignTop);
- popup->set_icon(0, 12, &I_RFIDDolphinSend_97x61);
-
- app->view_controller.switch_to();
-
- notification_message(app->notification, &sequence_display_backlight_on);
-}
-
-bool LfRfidAppSceneRpc::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- UNUSED(app);
- UNUSED(event);
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Exit) {
- consumed = true;
- LfRfidApp::Event view_event;
- view_event.type = LfRfidApp::EventType::Back;
- app->view_controller.send_event(&view_event);
- rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
- } else if(event->type == LfRfidApp::EventType::RpcSessionClose) {
- consumed = true;
- LfRfidApp::Event view_event;
- view_event.type = LfRfidApp::EventType::Back;
- app->view_controller.send_event(&view_event);
- } else if(event->type == LfRfidApp::EventType::RpcLoadFile) {
- const char* arg = rpc_system_app_get_data(app->rpc_ctx);
- consumed = true;
- bool result = false;
- if(arg && !emulating) {
- string_set_str(app->file_path, arg);
- if(app->load_key_data(app->file_path, false)) {
- lfrfid_worker_start_thread(app->lfworker);
- lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
- emulating = true;
-
- auto popup = app->view_controller.get();
- app->text_store.set("emulating\n%s", string_get_cstr(app->file_name));
- popup->set_text(app->text_store.text, 89, 44, AlignCenter, AlignTop);
-
- notification_message(app->notification, &sequence_blink_start_magenta);
- result = true;
- }
- }
- rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneRpc::on_exit(LfRfidApp* app) {
- if(emulating) {
- lfrfid_worker_stop(app->lfworker);
- lfrfid_worker_stop_thread(app->lfworker);
- notification_message(app->notification, &sequence_blink_stop);
- }
- app->view_controller.get()->clean();
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_rpc.h b/applications/lfrfid/scene/lfrfid_app_scene_rpc.h
deleted file mode 100644
index f630dfd35..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_rpc.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneRpc : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- bool emulating = false;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp
deleted file mode 100644
index c506cd729..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_data.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "lfrfid_app_scene_save_data.h"
-#include
-
-void LfRfidAppSceneSaveData::on_enter(LfRfidApp* app, bool need_restore) {
- auto byte_input = app->view_controller.get();
- size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
-
- if(need_restore) {
- protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
- } else {
- protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
- }
-
- protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
-
- byte_input->set_header_text("Enter the data in hex");
-
- byte_input->set_result_callback(save_callback, NULL, app, app->new_key_data, size);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneSaveData::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
- protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
- DOLPHIN_DEED(DolphinDeedRfidAdd);
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName);
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneSaveData::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneSaveData::save_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h b/applications/lfrfid/scene/lfrfid_app_scene_save_data.h
deleted file mode 100644
index d03cae125..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_data.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSaveData : public GenericScene {
-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);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
deleted file mode 100644
index ed58b6453..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.cpp
+++ /dev/null
@@ -1,72 +0,0 @@
-#include "lfrfid_app_scene_save_name.h"
-#include "m-string.h"
-#include
-#include
-
-void LfRfidAppSceneSaveName::on_enter(LfRfidApp* app, bool /* need_restore */) {
- const char* key_name = string_get_cstr(app->file_name);
-
- bool key_name_empty = (string_size(app->file_name) == 0);
- if(key_name_empty) {
- string_set_str(app->file_path, app->app_folder);
- set_random_name(app->text_store.text, app->text_store.text_size);
- } else {
- app->text_store.set("%s", key_name);
- }
-
- auto text_input = app->view_controller.get();
- text_input->set_header_text("Name the card");
-
- text_input->set_result_callback(
- save_callback, app, app->text_store.text, LFRFID_KEY_NAME_SIZE, key_name_empty);
-
- string_t folder_path;
- string_init(folder_path);
-
- path_extract_dirname(string_get_cstr(app->file_path), folder_path);
-
- ValidatorIsFile* validator_is_file =
- validator_is_file_alloc_init(string_get_cstr(folder_path), app->app_extension, key_name);
- text_input->set_validator(validator_is_file_callback, validator_is_file);
-
- string_clear(folder_path);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneSaveName::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Next) {
- if(string_size(app->file_name) > 0) {
- app->delete_key();
- }
-
- string_set_str(app->file_name, app->text_store.text);
-
- if(app->save_key()) {
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveSuccess);
- } else {
- app->scene_controller.search_and_switch_to_previous_scene(
- {LfRfidApp::SceneType::ReadKeyMenu});
- }
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneSaveName::on_exit(LfRfidApp* app) {
- void* validator_context =
- app->view_controller.get()->get_validator_callback_context();
- app->view_controller.get()->set_validator(NULL, NULL);
- validator_is_file_free((ValidatorIsFile*)validator_context);
-
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneSaveName::save_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Next;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h b/applications/lfrfid/scene/lfrfid_app_scene_save_name.h
deleted file mode 100644
index ced42cc0e..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_name.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSaveName : public GenericScene {
-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);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp
deleted file mode 100644
index 64efafa73..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.cpp
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "lfrfid_app_scene_save_success.h"
-#include
-#include
-#include
-
-void LfRfidAppSceneSaveSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto popup = app->view_controller.get();
-
- DOLPHIN_DEED(DolphinDeedRfidSave);
- popup->set_icon(32, 5, &I_DolphinNice_96x59);
- popup->set_header("Saved!", 5, 7, AlignLeft, AlignTop);
- popup->set_context(app);
- popup->set_callback(LfRfidAppSceneSaveSuccess::timeout_callback);
- popup->set_timeout(1500);
- popup->enable_timeout();
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneSaveSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Back) {
- bool result = app->scene_controller.has_previous_scene(
- {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
-
- if(result) {
- app->scene_controller.search_and_switch_to_previous_scene(
- {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
- } else {
- app->scene_controller.search_and_switch_to_another_scene(
- {LfRfidApp::SceneType::SaveType}, LfRfidApp::SceneType::SelectKey);
- }
-
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneSaveSuccess::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneSaveSuccess::timeout_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Back;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h b/applications/lfrfid/scene/lfrfid_app_scene_save_success.h
deleted file mode 100644
index 62273a76b..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_success.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSaveSuccess : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void timeout_callback(void* context);
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp b/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp
deleted file mode 100644
index b017e7b05..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_type.cpp
+++ /dev/null
@@ -1,53 +0,0 @@
-#include "lfrfid_app_scene_save_type.h"
-
-void LfRfidAppSceneSaveType::on_enter(LfRfidApp* app, bool need_restore) {
- auto submenu = app->view_controller.get();
-
- for(uint8_t i = 0; i < keys_count; i++) {
- string_init_printf(
- submenu_name[i],
- "%s %s",
- protocol_dict_get_manufacturer(app->dict, i),
- protocol_dict_get_name(app->dict, i));
- submenu->add_item(string_get_cstr(submenu_name[i]), i, submenu_callback, app);
- }
-
- if(need_restore) {
- submenu->set_selected_item(submenu_item_selected);
- }
-
- app->view_controller.switch_to();
-
- // clear key name
- string_reset(app->file_name);
-}
-
-bool LfRfidAppSceneSaveType::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::MenuSelected) {
- submenu_item_selected = event->payload.signed_int;
- app->protocol_id = event->payload.signed_int;
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData);
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneSaveType::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
- for(uint8_t i = 0; i < keys_count; i++) {
- string_clear(submenu_name[i]);
- }
-}
-
-void LfRfidAppSceneSaveType::submenu_callback(void* context, uint32_t index) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
-
- event.type = LfRfidApp::EventType::MenuSelected;
- event.payload.signed_int = index;
-
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h b/applications/lfrfid/scene/lfrfid_app_scene_save_type.h
deleted file mode 100644
index e4c1be3e6..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_save_type.h
+++ /dev/null
@@ -1,15 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSaveType : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void submenu_callback(void* context, uint32_t index);
- uint32_t submenu_item_selected = 0;
- static const uint8_t keys_count = static_cast(LFRFIDProtocol::LFRFIDProtocolMax);
- string_t submenu_name[keys_count];
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp
deleted file mode 100644
index 614dd505c..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.cpp
+++ /dev/null
@@ -1,48 +0,0 @@
-#include "lfrfid_app_scene_saved_info.h"
-#include "../view/elements/button_element.h"
-#include "../view/elements/icon_element.h"
-#include "../view/elements/string_element.h"
-
-void LfRfidAppSceneSavedInfo::on_enter(LfRfidApp* app, bool /* need_restore */) {
- string_init(string_info);
-
- string_printf(
- string_info,
- "%s [%s]\r\n",
- string_get_cstr(app->file_name),
- protocol_dict_get_name(app->dict, app->protocol_id));
-
- size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
- uint8_t* data = (uint8_t*)malloc(size);
- protocol_dict_get_data(app->dict, app->protocol_id, data, size);
- for(uint8_t i = 0; i < size; i++) {
- if(i != 0) {
- string_cat_printf(string_info, " ");
- }
-
- string_cat_printf(string_info, "%02X", data[i]);
- }
- free(data);
-
- string_t render_data;
- string_init(render_data);
- protocol_dict_render_data(app->dict, render_data, app->protocol_id);
- string_cat_printf(string_info, "\r\n%s", string_get_cstr(render_data));
- string_clear(render_data);
-
- auto container = app->view_controller.get();
-
- auto line_1 = container->add();
- line_1->set_text(string_get_cstr(string_info), 0, 1, 0, AlignLeft, AlignTop, FontSecondary);
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneSavedInfo::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) {
- return false;
-}
-
-void LfRfidAppSceneSavedInfo::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
- string_clear(string_info);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h
deleted file mode 100644
index b0b588bcb..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_saved_info.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSavedInfo : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp
deleted file mode 100644
index e7a38d8ad..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "lfrfid_app_scene_saved_key_menu.h"
-
-typedef enum {
- SubmenuEmulate,
- SubmenuWrite,
- SubmenuEdit,
- SubmenuDelete,
- SubmenuInfo,
-} SubmenuIndex;
-
-void LfRfidAppSceneSavedKeyMenu::on_enter(LfRfidApp* app, bool need_restore) {
- auto submenu = app->view_controller.get();
-
- submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app);
- submenu->add_item("Write", SubmenuWrite, submenu_callback, app);
- submenu->add_item("Edit", SubmenuEdit, submenu_callback, app);
- submenu->add_item("Delete", SubmenuDelete, submenu_callback, app);
- submenu->add_item("Info", SubmenuInfo, submenu_callback, app);
-
- if(need_restore) {
- submenu->set_selected_item(submenu_item_selected);
- }
-
- app->view_controller.switch_to();
-}
-
-bool LfRfidAppSceneSavedKeyMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::MenuSelected) {
- submenu_item_selected = event->payload.signed_int;
- switch(event->payload.signed_int) {
- case SubmenuEmulate:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate);
- break;
- case SubmenuWrite:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write);
- break;
- case SubmenuEdit:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveData);
- break;
- case SubmenuDelete:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::DeleteConfirm);
- break;
- case SubmenuInfo:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedInfo);
- break;
- }
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneSavedKeyMenu::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneSavedKeyMenu::submenu_callback(void* context, uint32_t index) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
-
- event.type = LfRfidApp::EventType::MenuSelected;
- event.payload.signed_int = index;
-
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h b/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h
deleted file mode 100644
index 69a6e5e58..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_saved_key_menu.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSavedKeyMenu : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp b/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp
deleted file mode 100644
index 6d5df73cb..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.cpp
+++ /dev/null
@@ -1,16 +0,0 @@
-#include "lfrfid_app_scene_select_key.h"
-
-void LfRfidAppSceneSelectKey::on_enter(LfRfidApp* app, bool need_restore) {
- if(app->load_key_from_file_select(need_restore)) {
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SavedKeyMenu);
- } else {
- app->scene_controller.switch_to_previous_scene();
- }
-}
-
-bool LfRfidAppSceneSelectKey::on_event(LfRfidApp* /* app */, LfRfidApp::Event* /* event */) {
- return false;
-}
-
-void LfRfidAppSceneSelectKey::on_exit(LfRfidApp* /* app */) {
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h b/applications/lfrfid/scene/lfrfid_app_scene_select_key.h
deleted file mode 100644
index be565a91c..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_select_key.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneSelectKey : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_start.cpp b/applications/lfrfid/scene/lfrfid_app_scene_start.cpp
deleted file mode 100644
index 5005c9afb..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_start.cpp
+++ /dev/null
@@ -1,67 +0,0 @@
-#include "lfrfid_app_scene_start.h"
-
-typedef enum {
- SubmenuRead,
- SubmenuSaved,
- SubmenuAddManually,
- SubmenuExtraActions,
-} SubmenuIndex;
-
-void LfRfidAppSceneStart::on_enter(LfRfidApp* app, bool need_restore) {
- auto submenu = app->view_controller.get();
-
- submenu->add_item("Read", SubmenuRead, submenu_callback, app);
- submenu->add_item("Saved", SubmenuSaved, submenu_callback, app);
- submenu->add_item("Add Manually", SubmenuAddManually, submenu_callback, app);
- submenu->add_item("Extra Actions", SubmenuExtraActions, submenu_callback, app);
-
- if(need_restore) {
- submenu->set_selected_item(submenu_item_selected);
- }
-
- app->view_controller.switch_to();
-
- // clear key
- string_reset(app->file_name);
- app->protocol_id = PROTOCOL_NO;
- app->read_type = LFRFIDWorkerReadTypeAuto;
-}
-
-bool LfRfidAppSceneStart::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::MenuSelected) {
- submenu_item_selected = event->payload.signed_int;
- switch(event->payload.signed_int) {
- case SubmenuRead:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Read);
- break;
- case SubmenuSaved:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SelectKey);
- break;
- case SubmenuAddManually:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveType);
- break;
- case SubmenuExtraActions:
- app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ExtraActions);
- break;
- }
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneStart::on_exit(LfRfidApp* app) {
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneStart::submenu_callback(void* context, uint32_t index) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
-
- event.type = LfRfidApp::EventType::MenuSelected;
- event.payload.signed_int = index;
-
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_start.h b/applications/lfrfid/scene/lfrfid_app_scene_start.h
deleted file mode 100644
index 255590d6a..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_start.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneStart : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write.cpp
deleted file mode 100644
index 8e04d8e8d..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_write.cpp
+++ /dev/null
@@ -1,79 +0,0 @@
-#include "lfrfid_app_scene_write.h"
-
-static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* ctx) {
- LfRfidApp* app = static_cast(ctx);
- LfRfidApp::Event event;
-
- switch(result) {
- case LFRFIDWorkerWriteOK:
- event.type = LfRfidApp::EventType::WriteEventOK;
- break;
- case LFRFIDWorkerWriteProtocolCannotBeWritten:
- event.type = LfRfidApp::EventType::WriteEventProtocolCannotBeWritten;
- break;
- case LFRFIDWorkerWriteFobCannotBeWritten:
- event.type = LfRfidApp::EventType::WriteEventFobCannotBeWritten;
- break;
- case LFRFIDWorkerWriteTooLongToWrite:
- event.type = LfRfidApp::EventType::WriteEventTooLongToWrite;
- break;
- }
-
- app->view_controller.send_event(&event);
-}
-
-void LfRfidAppSceneWrite::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto popup = app->view_controller.get();
-
- popup->set_header("Writing", 89, 30, AlignCenter, AlignTop);
- if(string_size(app->file_name)) {
- popup->set_text(string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
- } else {
- popup->set_text(
- protocol_dict_get_name(app->dict, app->protocol_id), 89, 43, AlignCenter, AlignTop);
- }
- popup->set_icon(0, 3, &I_RFIDDolphinSend_97x61);
-
- app->view_controller.switch_to();
- lfrfid_worker_start_thread(app->lfworker);
- lfrfid_worker_write_start(
- app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app);
- notification_message(app->notification, &sequence_blink_start_magenta);
-}
-
-bool LfRfidAppSceneWrite::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = true;
- auto popup = app->view_controller.get();
-
- 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()->clean();
- lfrfid_worker_stop(app->lfworker);
- lfrfid_worker_stop_thread(app->lfworker);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write.h b/applications/lfrfid/scene/lfrfid_app_scene_write.h
deleted file mode 100644
index 7564eff9d..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_write.h
+++ /dev/null
@@ -1,9 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneWrite : public GenericScene {
-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;
-};
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp b/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp
deleted file mode 100644
index 3cf00183d..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.cpp
+++ /dev/null
@@ -1,38 +0,0 @@
-#include "lfrfid_app_scene_write_success.h"
-
-void LfRfidAppSceneWriteSuccess::on_enter(LfRfidApp* app, bool /* need_restore */) {
- auto popup = app->view_controller.get();
- popup->set_header("Successfully\nwritten!", 94, 3, AlignCenter, AlignTop);
- popup->set_icon(0, 6, &I_RFIDDolphinSuccess_108x57);
- popup->set_context(app);
- popup->set_callback(LfRfidAppSceneWriteSuccess::timeout_callback);
- popup->set_timeout(1500);
- popup->enable_timeout();
-
- app->view_controller.switch_to();
- notification_message_block(app->notification, &sequence_set_green_255);
-}
-
-bool LfRfidAppSceneWriteSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) {
- bool consumed = false;
-
- if(event->type == LfRfidApp::EventType::Back) {
- app->scene_controller.search_and_switch_to_previous_scene(
- {LfRfidApp::SceneType::ReadKeyMenu, LfRfidApp::SceneType::SelectKey});
- consumed = true;
- }
-
- return consumed;
-}
-
-void LfRfidAppSceneWriteSuccess::on_exit(LfRfidApp* app) {
- notification_message_block(app->notification, &sequence_reset_green);
- app->view_controller.get()->clean();
-}
-
-void LfRfidAppSceneWriteSuccess::timeout_callback(void* context) {
- LfRfidApp* app = static_cast(context);
- LfRfidApp::Event event;
- event.type = LfRfidApp::EventType::Back;
- app->view_controller.send_event(&event);
-}
diff --git a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h b/applications/lfrfid/scene/lfrfid_app_scene_write_success.h
deleted file mode 100644
index 4ac9f0892..000000000
--- a/applications/lfrfid/scene/lfrfid_app_scene_write_success.h
+++ /dev/null
@@ -1,12 +0,0 @@
-#pragma once
-#include "../lfrfid_app.h"
-
-class LfRfidAppSceneWriteSuccess : public GenericScene {
-public:
- void on_enter(LfRfidApp* app, bool need_restore) final;
- bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final;
- void on_exit(LfRfidApp* app) final;
-
-private:
- static void timeout_callback(void* context);
-};
diff --git a/applications/lfrfid/scenes/lfrfid_scene.c b/applications/lfrfid/scenes/lfrfid_scene.c
new file mode 100644
index 000000000..0de5ec36b
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene.c
@@ -0,0 +1,30 @@
+#include "lfrfid_scene.h"
+
+// Generate scene on_enter handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
+void (*const lfrfid_on_enter_handlers[])(void*) = {
+#include "lfrfid_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_event handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
+bool (*const lfrfid_on_event_handlers[])(void* context, SceneManagerEvent event) = {
+#include "lfrfid_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers array
+#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
+void (*const lfrfid_on_exit_handlers[])(void* context) = {
+#include "lfrfid_scene_config.h"
+};
+#undef ADD_SCENE
+
+// Initialize scene handlers configuration structure
+const SceneManagerHandlers lfrfid_scene_handlers = {
+ .on_enter_handlers = lfrfid_on_enter_handlers,
+ .on_event_handlers = lfrfid_on_event_handlers,
+ .on_exit_handlers = lfrfid_on_exit_handlers,
+ .scene_num = LfRfidSceneNum,
+};
diff --git a/applications/lfrfid/scenes/lfrfid_scene.h b/applications/lfrfid/scenes/lfrfid_scene.h
new file mode 100644
index 000000000..8ce7da09c
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include
+
+// Generate scene id and total number
+#define ADD_SCENE(prefix, name, id) LfRfidScene##id,
+typedef enum {
+#include "lfrfid_scene_config.h"
+ LfRfidSceneNum,
+} LfRfidScene;
+#undef ADD_SCENE
+
+extern const SceneManagerHandlers lfrfid_scene_handlers;
+
+// Generate scene on_enter handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
+#include "lfrfid_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_event handlers declaration
+#define ADD_SCENE(prefix, name, id) \
+ bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
+#include "lfrfid_scene_config.h"
+#undef ADD_SCENE
+
+// Generate scene on_exit handlers declaration
+#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
+#include "lfrfid_scene_config.h"
+#undef ADD_SCENE
diff --git a/applications/lfrfid/scenes/lfrfid_scene_config.h b/applications/lfrfid/scenes/lfrfid_scene_config.h
new file mode 100644
index 000000000..b77ade82f
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_config.h
@@ -0,0 +1,24 @@
+ADD_SCENE(lfrfid, start, Start)
+ADD_SCENE(lfrfid, read, Read)
+ADD_SCENE(lfrfid, read_success, ReadSuccess)
+ADD_SCENE(lfrfid, retry_confirm, RetryConfirm)
+ADD_SCENE(lfrfid, exit_confirm, ExitConfirm)
+ADD_SCENE(lfrfid, delete_confirm, DeleteConfirm)
+ADD_SCENE(lfrfid, read_key_menu, ReadKeyMenu)
+ADD_SCENE(lfrfid, write, Write)
+ADD_SCENE(lfrfid, write_success, WriteSuccess)
+ADD_SCENE(lfrfid, emulate, Emulate)
+ADD_SCENE(lfrfid, save_name, SaveName)
+ADD_SCENE(lfrfid, save_success, SaveSuccess)
+ADD_SCENE(lfrfid, select_key, SelectKey)
+ADD_SCENE(lfrfid, saved_key_menu, SavedKeyMenu)
+ADD_SCENE(lfrfid, save_data, SaveData)
+ADD_SCENE(lfrfid, save_type, SaveType)
+ADD_SCENE(lfrfid, saved_info, SavedInfo)
+ADD_SCENE(lfrfid, delete_success, DeleteSuccess)
+ADD_SCENE(lfrfid, extra_actions, ExtraActions)
+ADD_SCENE(lfrfid, raw_info, RawInfo)
+ADD_SCENE(lfrfid, raw_name, RawName)
+ADD_SCENE(lfrfid, raw_read, RawRead)
+ADD_SCENE(lfrfid, raw_success, RawSuccess)
+ADD_SCENE(lfrfid, rpc, Rpc)
diff --git a/applications/lfrfid/scenes/lfrfid_scene_delete_confirm.c b/applications/lfrfid/scenes/lfrfid_scene_delete_confirm.c
new file mode 100644
index 000000000..dc1c3df26
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_delete_confirm.c
@@ -0,0 +1,68 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_delete_confirm_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ string_t tmp_string;
+ string_init(tmp_string);
+
+ widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app);
+ widget_add_button_element(widget, GuiButtonTypeRight, "Delete", lfrfid_widget_callback, app);
+
+ string_printf(tmp_string, "Delete %s?", string_get_cstr(app->file_name));
+ widget_add_string_element(
+ widget, 64, 0, AlignCenter, AlignTop, FontPrimary, string_get_cstr(tmp_string));
+
+ string_reset(tmp_string);
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ uint8_t* data = (uint8_t*)malloc(size);
+ protocol_dict_get_data(app->dict, app->protocol_id, data, size);
+ for(uint8_t i = 0; i < MIN(size, (size_t)8); i++) {
+ if(i != 0) {
+ string_cat_printf(tmp_string, " ");
+ }
+
+ string_cat_printf(tmp_string, "%02X", data[i]);
+ }
+ free(data);
+
+ widget_add_string_element(
+ widget, 64, 19, AlignCenter, AlignTop, FontSecondary, string_get_cstr(tmp_string));
+ widget_add_string_element(
+ widget,
+ 64,
+ 49,
+ AlignCenter,
+ AlignBottom,
+ FontSecondary,
+ protocol_dict_get_name(app->dict, app->protocol_id));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+ string_clear(tmp_string);
+}
+
+bool lfrfid_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeBack) {
+ consumed = true; // Ignore Back button presses
+ } else if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeLeft) {
+ scene_manager_previous_scene(scene_manager);
+ } else if(event.event == GuiButtonTypeRight) {
+ lfrfid_delete_key(app);
+ scene_manager_next_scene(scene_manager, LfRfidSceneDeleteSuccess);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_delete_confirm_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_delete_success.c b/applications/lfrfid/scenes/lfrfid_scene_delete_success.c
new file mode 100644
index 000000000..f940b9bd4
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_delete_success.c
@@ -0,0 +1,35 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_delete_success_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
+ popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
+ popup_set_context(popup, app);
+ popup_set_callback(popup, lfrfid_popup_timeout_callback);
+ popup_set_timeout(popup, 1500);
+ popup_enable_timeout(popup);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+}
+
+bool lfrfid_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if((event.type == SceneManagerEventTypeBack) ||
+ ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
+ scene_manager_search_and_switch_to_previous_scene(
+ app->scene_manager, LfRfidSceneSelectKey);
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_delete_success_on_exit(void* context) {
+ LfRfid* app = context;
+
+ popup_reset(app->popup);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_emulate.c b/applications/lfrfid/scenes/lfrfid_scene_emulate.c
new file mode 100644
index 000000000..70cc2418c
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_emulate.c
@@ -0,0 +1,44 @@
+#include "../lfrfid_i.h"
+#include
+
+void lfrfid_scene_emulate_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ DOLPHIN_DEED(DolphinDeedRfidEmulate);
+
+ popup_set_header(popup, "Emulating", 89, 30, AlignCenter, AlignTop);
+ if(!string_empty_p(app->file_name)) {
+ popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
+ } else {
+ popup_set_text(
+ popup,
+ protocol_dict_get_name(app->dict, app->protocol_id),
+ 89,
+ 43,
+ AlignCenter,
+ AlignTop);
+ }
+ popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
+
+ lfrfid_worker_start_thread(app->lfworker);
+ lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
+ notification_message(app->notifications, &sequence_blink_start_magenta);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+}
+
+bool lfrfid_scene_emulate_on_event(void* context, SceneManagerEvent event) {
+ UNUSED(context);
+ UNUSED(event);
+ bool consumed = false;
+ return consumed;
+}
+
+void lfrfid_scene_emulate_on_exit(void* context) {
+ LfRfid* app = context;
+ notification_message(app->notifications, &sequence_blink_stop);
+ popup_reset(app->popup);
+ lfrfid_worker_stop(app->lfworker);
+ lfrfid_worker_stop_thread(app->lfworker);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_exit_confirm.c b/applications/lfrfid/scenes/lfrfid_scene_exit_confirm.c
new file mode 100644
index 000000000..e8ab481c6
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_exit_confirm.c
@@ -0,0 +1,39 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_exit_confirm_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app);
+ widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app);
+ widget_add_string_element(
+ widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to RFID Menu?");
+ widget_add_string_element(
+ widget, 64, 31, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+}
+
+bool lfrfid_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeBack) {
+ consumed = true; // Ignore Back button presses
+ } else if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeLeft) {
+ scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneStart);
+ } else if(event.event == GuiButtonTypeRight) {
+ scene_manager_previous_scene(scene_manager);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_exit_confirm_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_extra_actions.c b/applications/lfrfid/scenes/lfrfid_scene_extra_actions.c
new file mode 100644
index 000000000..58082cf10
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_extra_actions.c
@@ -0,0 +1,79 @@
+#include "../lfrfid_i.h"
+
+typedef enum {
+ SubmenuIndexASK,
+ SubmenuIndexPSK,
+ SubmenuIndexRAW,
+} SubmenuIndex;
+
+static void lfrfid_scene_extra_actions_submenu_callback(void* context, uint32_t index) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void lfrfid_scene_extra_actions_on_enter(void* context) {
+ LfRfid* app = context;
+ Submenu* submenu = app->submenu;
+
+ submenu_add_item(
+ submenu,
+ "Read ASK (FDX,Regular)",
+ SubmenuIndexASK,
+ lfrfid_scene_extra_actions_submenu_callback,
+ app);
+ submenu_add_item(
+ submenu,
+ "Read PSK (Indala)",
+ SubmenuIndexPSK,
+ lfrfid_scene_extra_actions_submenu_callback,
+ app);
+
+ if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
+ submenu_add_item(
+ submenu,
+ "Read RAW RFID data",
+ SubmenuIndexRAW,
+ lfrfid_scene_extra_actions_submenu_callback,
+ app);
+ }
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneExtraActions));
+
+ // clear key
+ string_reset(app->file_name);
+ app->protocol_id = PROTOCOL_NO;
+ app->read_type = LFRFIDWorkerReadTypeAuto;
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
+}
+
+bool lfrfid_scene_extra_actions_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == SubmenuIndexASK) {
+ app->read_type = LFRFIDWorkerReadTypeASKOnly;
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
+ consumed = true;
+ } else if(event.event == SubmenuIndexPSK) {
+ app->read_type = LFRFIDWorkerReadTypePSKOnly;
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
+ consumed = true;
+ } else if(event.event == SubmenuIndexRAW) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRawName);
+ consumed = true;
+ }
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneExtraActions, event.event);
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_extra_actions_on_exit(void* context) {
+ LfRfid* app = context;
+
+ submenu_reset(app->submenu);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_raw_info.c b/applications/lfrfid/scenes/lfrfid_scene_raw_info.c
new file mode 100644
index 000000000..f60dd6243
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_raw_info.c
@@ -0,0 +1,64 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_raw_info_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ // string_t tmp_string;
+ // string_init(tmp_string);
+
+ bool sd_exist = storage_sd_status(app->storage) == FSE_OK;
+ if(!sd_exist) {
+ widget_add_icon_element(widget, 0, 0, &I_SDQuestion_35x43);
+ widget_add_string_multiline_element(
+ widget,
+ 81,
+ 4,
+ AlignCenter,
+ AlignTop,
+ FontSecondary,
+ "No SD card found.\nThis function will not\nwork without\nSD card.");
+
+ widget_add_button_element(widget, GuiButtonTypeLeft, "Back", lfrfid_widget_callback, app);
+ } else {
+ widget_add_string_multiline_element(
+ widget,
+ 0,
+ 1,
+ AlignLeft,
+ AlignTop,
+ FontSecondary,
+ "RAW RFID data reader\n1) Put the Flipper on your card\n2) Press OK\n3) Wait until data is read");
+
+ widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app);
+ }
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+ //string_clear(tmp_string);
+}
+
+bool lfrfid_scene_raw_info_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeBack) {
+ consumed = true;
+ scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneExtraActions);
+ } else if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeCenter) {
+ scene_manager_next_scene(scene_manager, LfRfidSceneRawRead);
+ } else if(event.event == GuiButtonTypeLeft) {
+ scene_manager_search_and_switch_to_previous_scene(
+ scene_manager, LfRfidSceneExtraActions);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_raw_info_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_raw_name.c b/applications/lfrfid/scenes/lfrfid_scene_raw_name.c
new file mode 100644
index 000000000..512f9ee4c
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_raw_name.c
@@ -0,0 +1,58 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_raw_name_on_enter(void* context) {
+ LfRfid* app = context;
+ TextInput* text_input = app->text_input;
+
+ const char* key_name = string_get_cstr(app->raw_file_name);
+
+ bool key_name_is_empty = string_empty_p(app->file_name);
+ if(key_name_is_empty) {
+ lfrfid_text_store_set(app, "RfidRecord");
+ } else {
+ lfrfid_text_store_set(app, "%s", key_name);
+ }
+
+ text_input_set_header_text(text_input, "Name the raw file");
+
+ text_input_set_result_callback(
+ text_input,
+ lfrfid_text_input_callback,
+ app,
+ app->text_store,
+ LFRFID_KEY_NAME_SIZE,
+ key_name_is_empty);
+
+ ValidatorIsFile* validator_is_file =
+ validator_is_file_alloc_init(LFRFID_SD_FOLDER, LFRFID_APP_RAW_ASK_EXTENSION, NULL);
+ text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput);
+}
+
+bool lfrfid_scene_raw_name_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventNext) {
+ consumed = true;
+ string_set_str(app->raw_file_name, app->text_store);
+ scene_manager_next_scene(scene_manager, LfRfidSceneRawInfo);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_raw_name_on_exit(void* context) {
+ LfRfid* app = context;
+ TextInput* text_input = app->text_input;
+
+ void* validator_context = text_input_get_validator_callback_context(text_input);
+ text_input_set_validator(text_input, NULL, NULL);
+ validator_is_file_free((ValidatorIsFile*)validator_context);
+
+ text_input_reset(text_input);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_raw_read.c b/applications/lfrfid/scenes/lfrfid_scene_raw_read.c
new file mode 100644
index 000000000..d0c03ffa9
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_raw_read.c
@@ -0,0 +1,126 @@
+#include "../lfrfid_i.h"
+
+#define RAW_READ_TIME 5000
+
+typedef struct {
+ string_t string_file_name;
+ FuriTimer* timer;
+ bool is_psk;
+ bool error;
+} LfRfidReadRawState;
+
+static void lfrfid_read_callback(LFRFIDWorkerReadRawResult result, void* context) {
+ LfRfid* app = context;
+
+ if(result == LFRFIDWorkerReadRawFileError) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadError);
+ } else if(result == LFRFIDWorkerReadRawOverrun) {
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadOverrun);
+ }
+}
+
+static void timer_callback(void* context) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, LfRfidEventReadDone);
+}
+
+void lfrfid_scene_raw_read_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ LfRfidReadRawState* state = malloc(sizeof(LfRfidReadRawState));
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneRawRead, (uint32_t)state);
+ string_init(state->string_file_name);
+
+ popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+ lfrfid_worker_start_thread(app->lfworker);
+ lfrfid_make_app_folder(app);
+
+ state->timer = furi_timer_alloc(timer_callback, FuriTimerTypeOnce, app);
+ furi_timer_start(state->timer, RAW_READ_TIME);
+ string_printf(
+ state->string_file_name,
+ "%s/%s%s",
+ LFRFID_SD_FOLDER,
+ string_get_cstr(app->raw_file_name),
+ LFRFID_APP_RAW_ASK_EXTENSION);
+ popup_set_header(popup, "Reading\nRAW RFID\nASK", 89, 30, AlignCenter, AlignTop);
+ lfrfid_worker_read_raw_start(
+ app->lfworker,
+ string_get_cstr(state->string_file_name),
+ LFRFIDWorkerReadTypeASKOnly,
+ lfrfid_read_callback,
+ app);
+
+ notification_message(app->notifications, &sequence_blink_start_cyan);
+
+ state->is_psk = false;
+ state->error = false;
+}
+
+bool lfrfid_scene_raw_read_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+ LfRfidReadRawState* state =
+ (LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead);
+ bool consumed = false;
+
+ furi_assert(state);
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventReadError) {
+ consumed = true;
+ state->error = true;
+ popup_set_header(
+ popup, "Reading\nRAW RFID\nFile error", 89, 30, AlignCenter, AlignTop);
+ notification_message(app->notifications, &sequence_blink_start_red);
+ furi_timer_stop(state->timer);
+ } else if(event.event == LfRfidEventReadDone) {
+ consumed = true;
+ if(!state->error) {
+ if(state->is_psk) {
+ notification_message(app->notifications, &sequence_success);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRawSuccess);
+ } else {
+ popup_set_header(
+ popup, "Reading\nRAW RFID\nPSK", 89, 30, AlignCenter, AlignTop);
+ notification_message(app->notifications, &sequence_blink_start_yellow);
+ lfrfid_worker_stop(app->lfworker);
+ string_printf(
+ state->string_file_name,
+ "%s/%s%s",
+ LFRFID_SD_FOLDER,
+ string_get_cstr(app->raw_file_name),
+ LFRFID_APP_RAW_PSK_EXTENSION);
+ lfrfid_worker_read_raw_start(
+ app->lfworker,
+ string_get_cstr(state->string_file_name),
+ LFRFIDWorkerReadTypePSKOnly,
+ lfrfid_read_callback,
+ app);
+ furi_timer_start(state->timer, RAW_READ_TIME);
+ state->is_psk = true;
+ }
+ }
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_raw_read_on_exit(void* context) {
+ LfRfid* app = context;
+ LfRfidReadRawState* state =
+ (LfRfidReadRawState*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneRawRead);
+
+ notification_message(app->notifications, &sequence_blink_stop);
+ popup_reset(app->popup);
+ lfrfid_worker_stop(app->lfworker);
+ lfrfid_worker_stop_thread(app->lfworker);
+ furi_timer_free(state->timer);
+
+ string_clear(state->string_file_name);
+ free(state);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_raw_success.c b/applications/lfrfid/scenes/lfrfid_scene_raw_success.c
new file mode 100644
index 000000000..09a005298
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_raw_success.c
@@ -0,0 +1,39 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_raw_success_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ widget_add_button_element(widget, GuiButtonTypeCenter, "OK", lfrfid_widget_callback, app);
+
+ widget_add_string_multiline_element(
+ widget,
+ 0,
+ 1,
+ AlignLeft,
+ AlignTop,
+ FontSecondary,
+ "RAW RFID read success!\nNow you can analyze files\nOr send them to developers");
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+}
+
+bool lfrfid_scene_raw_success_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeCenter) {
+ scene_manager_search_and_switch_to_previous_scene(
+ scene_manager, LfRfidSceneExtraActions);
+ }
+ }
+ return consumed;
+}
+
+void lfrfid_scene_raw_success_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_read.c b/applications/lfrfid/scenes/lfrfid_scene_read.c
new file mode 100644
index 000000000..661680381
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_read.c
@@ -0,0 +1,109 @@
+#include "../lfrfid_i.h"
+#include
+
+static const NotificationSequence sequence_blink_set_yellow = {
+ &message_blink_set_color_yellow,
+ NULL,
+};
+
+static const NotificationSequence sequence_blink_set_green = {
+ &message_blink_set_color_green,
+ NULL,
+};
+
+static const NotificationSequence sequence_blink_set_cyan = {
+ &message_blink_set_color_cyan,
+ NULL,
+};
+
+static void
+ lfrfid_read_callback(LFRFIDWorkerReadResult result, ProtocolId protocol, void* context) {
+ LfRfid* app = context;
+ uint32_t event = 0;
+
+ if(result == LFRFIDWorkerReadSenseStart) {
+ event = LfRfidEventReadSenseStart;
+ } else if(result == LFRFIDWorkerReadSenseEnd) {
+ event = LfRfidEventReadSenseEnd;
+ } else if(result == LFRFIDWorkerReadSenseCardStart) {
+ event = LfRfidEventReadSenseCardStart;
+ } else if(result == LFRFIDWorkerReadSenseCardEnd) {
+ event = LfRfidEventReadSenseCardEnd;
+ } else if(result == LFRFIDWorkerReadDone) {
+ event = LfRfidEventReadDone;
+ app->protocol_id_next = protocol;
+ } else if(result == LFRFIDWorkerReadStartASK) {
+ event = LfRfidEventReadStartASK;
+ } else if(result == LFRFIDWorkerReadStartPSK) {
+ event = LfRfidEventReadStartPSK;
+ } else {
+ return;
+ }
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, event);
+}
+
+void lfrfid_scene_read_on_enter(void* context) {
+ LfRfid* app = context;
+
+ DOLPHIN_DEED(DolphinDeedRfidRead);
+ if(app->read_type == LFRFIDWorkerReadTypePSKOnly) {
+ lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPskOnly);
+ } else if(app->read_type == LFRFIDWorkerReadTypeASKOnly) {
+ lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAskOnly);
+ }
+
+ lfrfid_worker_start_thread(app->lfworker);
+ lfrfid_worker_read_start(app->lfworker, app->read_type, lfrfid_read_callback, app);
+
+ notification_message(app->notifications, &sequence_blink_start_cyan);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewRead);
+}
+
+bool lfrfid_scene_read_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventReadSenseStart) {
+ notification_message(app->notifications, &sequence_blink_set_yellow);
+ consumed = true;
+ } else if(event.event == LfRfidEventReadSenseCardStart) {
+ notification_message(app->notifications, &sequence_blink_set_green);
+ consumed = true;
+ } else if(
+ (event.event == LfRfidEventReadSenseEnd) ||
+ (event.event == LfRfidEventReadSenseCardEnd)) {
+ notification_message(app->notifications, &sequence_blink_set_cyan);
+ consumed = true;
+ } else if(event.event == LfRfidEventReadDone) {
+ app->protocol_id = app->protocol_id_next;
+ DOLPHIN_DEED(DolphinDeedRfidReadSuccess);
+ notification_message(app->notifications, &sequence_success);
+ string_reset(app->file_name);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneReadSuccess);
+ consumed = true;
+ } else if(event.event == LfRfidEventReadStartPSK) {
+ if(app->read_type == LFRFIDWorkerReadTypeAuto) {
+ lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadPsk);
+ }
+ consumed = true;
+ } else if(event.event == LfRfidEventReadStartASK) {
+ if(app->read_type == LFRFIDWorkerReadTypeAuto) {
+ lfrfid_view_read_set_read_mode(app->read_view, LfRfidReadAsk);
+ }
+ consumed = true;
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_read_on_exit(void* context) {
+ LfRfid* app = context;
+ notification_message(app->notifications, &sequence_blink_stop);
+ popup_reset(app->popup);
+ lfrfid_worker_stop(app->lfworker);
+ lfrfid_worker_stop_thread(app->lfworker);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_read_key_menu.c b/applications/lfrfid/scenes/lfrfid_scene_read_key_menu.c
new file mode 100644
index 000000000..221cc0084
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_read_key_menu.c
@@ -0,0 +1,58 @@
+#include "../lfrfid_i.h"
+
+typedef enum {
+ SubmenuIndexSave,
+ SubmenuIndexEmulate,
+ SubmenuIndexWrite,
+} SubmenuIndex;
+
+void lfrfid_scene_read_key_menu_submenu_callback(void* context, uint32_t index) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void lfrfid_scene_read_key_menu_on_enter(void* context) {
+ LfRfid* app = context;
+ Submenu* submenu = app->submenu;
+
+ submenu_add_item(
+ submenu, "Save", SubmenuIndexSave, lfrfid_scene_read_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_read_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Write", SubmenuIndexWrite, lfrfid_scene_read_key_menu_submenu_callback, app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
+}
+
+bool lfrfid_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == SubmenuIndexWrite) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
+ consumed = true;
+ } else if(event.event == SubmenuIndexSave) {
+ string_reset(app->file_name);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveName);
+ consumed = true;
+ } else if(event.event == SubmenuIndexEmulate) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
+ consumed = true;
+ }
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneReadKeyMenu, event.event);
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_read_key_menu_on_exit(void* context) {
+ LfRfid* app = context;
+
+ submenu_reset(app->submenu);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_read_success.c b/applications/lfrfid/scenes/lfrfid_scene_read_success.c
new file mode 100644
index 000000000..c250fe4ea
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_read_success.c
@@ -0,0 +1,80 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_read_success_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ string_t tmp_string;
+ string_init(tmp_string);
+
+ widget_add_button_element(widget, GuiButtonTypeLeft, "Retry", lfrfid_widget_callback, app);
+ widget_add_button_element(widget, GuiButtonTypeRight, "More", lfrfid_widget_callback, app);
+
+ string_printf(
+ tmp_string,
+ "%s[%s]",
+ protocol_dict_get_name(app->dict, app->protocol_id),
+ protocol_dict_get_manufacturer(app->dict, app->protocol_id));
+
+ widget_add_string_element(
+ widget, 16, 3, AlignLeft, AlignTop, FontPrimary, string_get_cstr(tmp_string));
+
+ string_reset(tmp_string);
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ uint8_t* data = (uint8_t*)malloc(size);
+ protocol_dict_get_data(app->dict, app->protocol_id, data, size);
+ for(uint8_t i = 0; i < size; i++) {
+ if(i >= 9) {
+ string_cat_printf(tmp_string, "..");
+ break;
+ } else {
+ if(i != 0) {
+ string_cat_printf(tmp_string, ":");
+ }
+ string_cat_printf(tmp_string, "%02X", data[i]);
+ }
+ }
+ free(data);
+
+ string_t render_data;
+ string_init(render_data);
+ protocol_dict_render_brief_data(app->dict, render_data, app->protocol_id);
+ string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data));
+ string_clear(render_data);
+
+ widget_add_string_multiline_element(
+ widget, 0, 16, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string));
+
+ widget_add_icon_element(app->widget, 0, 0, &I_RFIDSmallChip_14x14);
+
+ notification_message_block(app->notifications, &sequence_set_green_255);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+ string_clear(tmp_string);
+}
+
+bool lfrfid_scene_read_success_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeBack) {
+ scene_manager_next_scene(scene_manager, LfRfidSceneExitConfirm);
+ consumed = true;
+ } else if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeLeft) {
+ scene_manager_next_scene(scene_manager, LfRfidSceneRetryConfirm);
+ } else if(event.event == GuiButtonTypeRight) {
+ scene_manager_next_scene(scene_manager, LfRfidSceneReadKeyMenu);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_read_success_on_exit(void* context) {
+ LfRfid* app = context;
+ notification_message_block(app->notifications, &sequence_reset_green);
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_retry_confirm.c b/applications/lfrfid/scenes/lfrfid_scene_retry_confirm.c
new file mode 100644
index 000000000..f639f0ae1
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_retry_confirm.c
@@ -0,0 +1,39 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_retry_confirm_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", lfrfid_widget_callback, app);
+ widget_add_button_element(widget, GuiButtonTypeRight, "Stay", lfrfid_widget_callback, app);
+ widget_add_string_element(
+ widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
+ widget_add_string_element(
+ widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost!");
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+}
+
+bool lfrfid_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeBack) {
+ consumed = true; // Ignore Back button presses
+ } else if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == GuiButtonTypeLeft) {
+ scene_manager_search_and_switch_to_previous_scene(scene_manager, LfRfidSceneRead);
+ } else if(event.event == GuiButtonTypeRight) {
+ scene_manager_previous_scene(scene_manager);
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_retry_confirm_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_rpc.c b/applications/lfrfid/scenes/lfrfid_scene_rpc.c
new file mode 100644
index 000000000..a69d6453a
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_rpc.c
@@ -0,0 +1,67 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_rpc_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ popup_set_header(popup, "LF RFID", 89, 42, AlignCenter, AlignBottom);
+ popup_set_text(popup, "RPC mode", 89, 44, AlignCenter, AlignTop);
+ popup_set_icon(popup, 0, 12, &I_RFIDDolphinSend_97x61);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+
+ notification_message(app->notifications, &sequence_display_backlight_on);
+
+ app->rpc_state = LfRfidRpcStateIdle;
+}
+
+bool lfrfid_scene_rpc_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+ UNUSED(event);
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ consumed = true;
+ if(event.event == LfRfidEventExit) {
+ rpc_system_app_confirm(app->rpc_ctx, RpcAppEventAppExit, true);
+ scene_manager_stop(app->scene_manager);
+ view_dispatcher_stop(app->view_dispatcher);
+ } else if(event.event == LfRfidEventRpcSessionClose) {
+ scene_manager_stop(app->scene_manager);
+ view_dispatcher_stop(app->view_dispatcher);
+ } else if(event.event == LfRfidEventRpcLoadFile) {
+ const char* arg = rpc_system_app_get_data(app->rpc_ctx);
+ bool result = false;
+ if(arg && (app->rpc_state == LfRfidRpcStateIdle)) {
+ string_set_str(app->file_path, arg);
+ if(lfrfid_load_key_data(app, app->file_path, false)) {
+ lfrfid_worker_start_thread(app->lfworker);
+ lfrfid_worker_emulate_start(app->lfworker, (LFRFIDProtocol)app->protocol_id);
+ app->rpc_state = LfRfidRpcStateEmulating;
+
+ lfrfid_text_store_set(app, "emulating\n%s", string_get_cstr(app->file_name));
+ popup_set_text(popup, app->text_store, 89, 44, AlignCenter, AlignTop);
+
+ notification_message(app->notifications, &sequence_blink_start_magenta);
+ result = true;
+ }
+ }
+ rpc_system_app_confirm(app->rpc_ctx, RpcAppEventLoadFile, result);
+ }
+ }
+ return consumed;
+}
+
+void lfrfid_scene_rpc_on_exit(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ if(app->rpc_state == LfRfidRpcStateEmulating) {
+ lfrfid_worker_stop(app->lfworker);
+ lfrfid_worker_stop_thread(app->lfworker);
+ notification_message(app->notifications, &sequence_blink_stop);
+ }
+
+ popup_reset(popup);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_save_data.c b/applications/lfrfid/scenes/lfrfid_scene_save_data.c
new file mode 100644
index 000000000..2ca1bb433
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_save_data.c
@@ -0,0 +1,51 @@
+#include "../lfrfid_i.h"
+#include
+
+void lfrfid_scene_save_data_on_enter(void* context) {
+ LfRfid* app = context;
+ ByteInput* byte_input = app->byte_input;
+
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+
+ bool need_restore = scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveData);
+
+ if(need_restore) {
+ protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
+ } else {
+ protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
+ }
+
+ protocol_dict_get_data(app->dict, app->protocol_id, app->new_key_data, size);
+
+ byte_input_set_header_text(byte_input, "Enter the data in hex");
+
+ byte_input_set_result_callback(
+ byte_input, lfrfid_text_input_callback, NULL, app, app->new_key_data, size);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewByteInput);
+}
+
+bool lfrfid_scene_save_data_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventNext) {
+ consumed = true;
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ protocol_dict_set_data(app->dict, app->protocol_id, app->new_key_data, size);
+ DOLPHIN_DEED(DolphinDeedRfidAdd);
+ scene_manager_next_scene(scene_manager, LfRfidSceneSaveName);
+ scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 1);
+ }
+ } else if(event.type == SceneManagerEventTypeBack) {
+ scene_manager_set_scene_state(scene_manager, LfRfidSceneSaveData, 0);
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_save_data_on_exit(void* context) {
+ UNUSED(context);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_save_name.c b/applications/lfrfid/scenes/lfrfid_scene_save_name.c
new file mode 100644
index 000000000..febf30a41
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_save_name.c
@@ -0,0 +1,76 @@
+#include "m-string.h"
+#include
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_save_name_on_enter(void* context) {
+ LfRfid* app = context;
+ TextInput* text_input = app->text_input;
+ string_t folder_path;
+ string_init(folder_path);
+
+ bool key_name_is_empty = string_empty_p(app->file_name);
+ if(key_name_is_empty) {
+ string_set_str(app->file_path, LFRFID_APP_FOLDER);
+ set_random_name(app->text_store, LFRFID_TEXT_STORE_SIZE);
+ string_set_str(folder_path, LFRFID_APP_FOLDER);
+ } else {
+ lfrfid_text_store_set(app, "%s", string_get_cstr(app->file_name));
+ path_extract_dirname(string_get_cstr(app->file_path), folder_path);
+ }
+
+ text_input_set_header_text(text_input, "Name the card");
+ text_input_set_result_callback(
+ text_input,
+ lfrfid_text_input_callback,
+ app,
+ app->text_store,
+ LFRFID_KEY_NAME_SIZE,
+ key_name_is_empty);
+
+ FURI_LOG_I("", "%s %s", string_get_cstr(folder_path), app->text_store);
+
+ ValidatorIsFile* validator_is_file = validator_is_file_alloc_init(
+ string_get_cstr(folder_path), LFRFID_APP_EXTENSION, string_get_cstr(app->file_name));
+ text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
+
+ string_clear(folder_path);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewTextInput);
+}
+
+bool lfrfid_scene_save_name_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ SceneManager* scene_manager = app->scene_manager;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventNext) {
+ consumed = true;
+ if(!string_empty_p(app->file_name)) {
+ lfrfid_delete_key(app);
+ }
+
+ string_set_str(app->file_name, app->text_store);
+
+ if(lfrfid_save_key(app)) {
+ scene_manager_next_scene(scene_manager, LfRfidSceneSaveSuccess);
+ } else {
+ scene_manager_search_and_switch_to_previous_scene(
+ scene_manager, LfRfidSceneReadKeyMenu);
+ }
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_save_name_on_exit(void* context) {
+ LfRfid* app = context;
+ TextInput* text_input = app->text_input;
+
+ void* validator_context = text_input_get_validator_callback_context(text_input);
+ text_input_set_validator(text_input, NULL, NULL);
+ validator_is_file_free((ValidatorIsFile*)validator_context);
+
+ text_input_reset(text_input);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_save_success.c b/applications/lfrfid/scenes/lfrfid_scene_save_success.c
new file mode 100644
index 000000000..830ef3368
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_save_success.c
@@ -0,0 +1,43 @@
+#include "../lfrfid_i.h"
+#include
+
+void lfrfid_scene_save_success_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ DOLPHIN_DEED(DolphinDeedRfidSave);
+ popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
+ popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
+ popup_set_context(popup, app);
+ popup_set_callback(popup, lfrfid_popup_timeout_callback);
+ popup_set_timeout(popup, 1500);
+ popup_enable_timeout(popup);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+}
+
+bool lfrfid_scene_save_success_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey};
+
+ if((event.type == SceneManagerEventTypeBack) ||
+ ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
+ bool result = scene_manager_search_and_switch_to_previous_scene_one_of(
+ app->scene_manager, prev_scenes, COUNT_OF(prev_scenes));
+ if(!result) {
+ scene_manager_search_and_switch_to_another_scene(
+ app->scene_manager, LfRfidSceneSelectKey);
+ }
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_save_success_on_exit(void* context) {
+ LfRfid* app = context;
+
+ popup_reset(app->popup);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_save_type.c b/applications/lfrfid/scenes/lfrfid_scene_save_type.c
new file mode 100644
index 000000000..827e6d151
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_save_type.c
@@ -0,0 +1,87 @@
+#include "../lfrfid_i.h"
+
+typedef struct {
+ string_t menu_item_name[LFRFIDProtocolMax];
+ uint32_t line_sel;
+} SaveTypeCtx;
+
+static void lfrfid_scene_save_type_submenu_callback(void* context, uint32_t index) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void lfrfid_scene_save_type_on_enter(void* context) {
+ LfRfid* app = context;
+ Submenu* submenu = app->submenu;
+
+ SaveTypeCtx* state = malloc(sizeof(SaveTypeCtx));
+ for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
+ if((strcmp(
+ protocol_dict_get_manufacturer(app->dict, i),
+ protocol_dict_get_name(app->dict, i)) != 0) &&
+ (strcmp(protocol_dict_get_manufacturer(app->dict, i), "N/A") != 0)) {
+ string_init_printf(
+ state->menu_item_name[i],
+ "%s %s",
+ protocol_dict_get_manufacturer(app->dict, i),
+ protocol_dict_get_name(app->dict, i));
+ } else {
+ string_init_printf(
+ state->menu_item_name[i], "%s", protocol_dict_get_name(app->dict, i));
+ }
+ submenu_add_item(
+ submenu,
+ string_get_cstr(state->menu_item_name[i]),
+ i,
+ lfrfid_scene_save_type_submenu_callback,
+ app);
+ }
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType));
+
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, (uint32_t)state);
+
+ // clear key name
+ string_reset(app->file_name);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
+}
+
+bool lfrfid_scene_save_type_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ SaveTypeCtx* state =
+ (SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType);
+ furi_check(state);
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ app->protocol_id = event.event;
+ state->line_sel = event.event;
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_save_type_on_exit(void* context) {
+ LfRfid* app = context;
+ SaveTypeCtx* state =
+ (SaveTypeCtx*)scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSaveType);
+ furi_check(state);
+
+ submenu_reset(app->submenu);
+
+ for(uint8_t i = 0; i < LFRFIDProtocolMax; i++) {
+ string_clear(state->menu_item_name[i]);
+ }
+
+ uint32_t line_sel = state->line_sel;
+
+ free(state);
+
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSaveType, line_sel);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_saved_info.c b/applications/lfrfid/scenes/lfrfid_scene_saved_info.c
new file mode 100644
index 000000000..7e376ca01
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_saved_info.c
@@ -0,0 +1,51 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_saved_info_on_enter(void* context) {
+ LfRfid* app = context;
+ Widget* widget = app->widget;
+
+ string_t tmp_string;
+ string_init(tmp_string);
+
+ string_printf(
+ tmp_string,
+ "%s [%s]\r\n",
+ string_get_cstr(app->file_name),
+ protocol_dict_get_name(app->dict, app->protocol_id));
+
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ uint8_t* data = (uint8_t*)malloc(size);
+ protocol_dict_get_data(app->dict, app->protocol_id, data, size);
+ for(uint8_t i = 0; i < size; i++) {
+ if(i != 0) {
+ string_cat_printf(tmp_string, ":");
+ }
+
+ string_cat_printf(tmp_string, "%02X", data[i]);
+ }
+ free(data);
+
+ string_t render_data;
+ string_init(render_data);
+ protocol_dict_render_data(app->dict, render_data, app->protocol_id);
+ string_cat_printf(tmp_string, "\r\n%s", string_get_cstr(render_data));
+ string_clear(render_data);
+
+ widget_add_string_multiline_element(
+ widget, 0, 1, AlignLeft, AlignTop, FontSecondary, string_get_cstr(tmp_string));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewWidget);
+ string_clear(tmp_string);
+}
+
+bool lfrfid_scene_saved_info_on_event(void* context, SceneManagerEvent event) {
+ UNUSED(context);
+ UNUSED(event);
+ bool consumed = false;
+ return consumed;
+}
+
+void lfrfid_scene_saved_info_on_exit(void* context) {
+ LfRfid* app = context;
+ widget_reset(app->widget);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_saved_key_menu.c b/applications/lfrfid/scenes/lfrfid_scene_saved_key_menu.c
new file mode 100644
index 000000000..040b31f10
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_saved_key_menu.c
@@ -0,0 +1,69 @@
+#include "../lfrfid_i.h"
+
+typedef enum {
+ SubmenuIndexEmulate,
+ SubmenuIndexWrite,
+ SubmenuIndexEdit,
+ SubmenuIndexDelete,
+ SubmenuIndexInfo,
+} SubmenuIndex;
+
+static void lfrfid_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void lfrfid_scene_saved_key_menu_on_enter(void* context) {
+ LfRfid* app = context;
+ Submenu* submenu = app->submenu;
+
+ submenu_add_item(
+ submenu, "Emulate", SubmenuIndexEmulate, lfrfid_scene_saved_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Write", SubmenuIndexWrite, lfrfid_scene_saved_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Edit", SubmenuIndexEdit, lfrfid_scene_saved_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Delete", SubmenuIndexDelete, lfrfid_scene_saved_key_menu_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Info", SubmenuIndexInfo, lfrfid_scene_saved_key_menu_submenu_callback, app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu));
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
+}
+
+bool lfrfid_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == SubmenuIndexEmulate) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneEmulate);
+ consumed = true;
+ } else if(event.event == SubmenuIndexWrite) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneWrite);
+ consumed = true;
+ } else if(event.event == SubmenuIndexEdit) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveData);
+ consumed = true;
+ } else if(event.event == SubmenuIndexDelete) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneDeleteConfirm);
+ consumed = true;
+ } else if(event.event == SubmenuIndexInfo) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedInfo);
+ consumed = true;
+ }
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneSavedKeyMenu, event.event);
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_saved_key_menu_on_exit(void* context) {
+ LfRfid* app = context;
+
+ submenu_reset(app->submenu);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_select_key.c b/applications/lfrfid/scenes/lfrfid_scene_select_key.c
new file mode 100644
index 000000000..2a9cc1c63
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_select_key.c
@@ -0,0 +1,22 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_select_key_on_enter(void* context) {
+ LfRfid* app = context;
+
+ if(lfrfid_load_key_from_file_select(app)) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSavedKeyMenu);
+ } else {
+ scene_manager_previous_scene(app->scene_manager);
+ }
+}
+
+bool lfrfid_scene_select_key_on_event(void* context, SceneManagerEvent event) {
+ UNUSED(context);
+ UNUSED(event);
+ bool consumed = false;
+ return consumed;
+}
+
+void lfrfid_scene_select_key_on_exit(void* context) {
+ UNUSED(context);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_start.c b/applications/lfrfid/scenes/lfrfid_scene_start.c
new file mode 100644
index 000000000..9074e859b
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_start.c
@@ -0,0 +1,72 @@
+#include "../lfrfid_i.h"
+
+typedef enum {
+ SubmenuIndexRead,
+ SubmenuIndexSaved,
+ SubmenuIndexAddManually,
+ SubmenuIndexExtraActions,
+} SubmenuIndex;
+
+static void lfrfid_scene_start_submenu_callback(void* context, uint32_t index) {
+ LfRfid* app = context;
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, index);
+}
+
+void lfrfid_scene_start_on_enter(void* context) {
+ LfRfid* app = context;
+ Submenu* submenu = app->submenu;
+
+ submenu_add_item(submenu, "Read", SubmenuIndexRead, lfrfid_scene_start_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Saved", SubmenuIndexSaved, lfrfid_scene_start_submenu_callback, app);
+ submenu_add_item(
+ submenu, "Add Manually", SubmenuIndexAddManually, lfrfid_scene_start_submenu_callback, app);
+ submenu_add_item(
+ submenu,
+ "Extra Actions",
+ SubmenuIndexExtraActions,
+ lfrfid_scene_start_submenu_callback,
+ app);
+
+ submenu_set_selected_item(
+ submenu, scene_manager_get_scene_state(app->scene_manager, LfRfidSceneStart));
+
+ // clear key
+ string_reset(app->file_name);
+ app->protocol_id = PROTOCOL_NO;
+ app->read_type = LFRFIDWorkerReadTypeAuto;
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewSubmenu);
+}
+
+bool lfrfid_scene_start_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == SubmenuIndexRead) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneRead);
+ consumed = true;
+ } else if(event.event == SubmenuIndexSaved) {
+ string_set_str(app->file_path, LFRFID_APP_FOLDER);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSelectKey);
+ consumed = true;
+ } else if(event.event == SubmenuIndexAddManually) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneSaveType);
+ consumed = true;
+ } else if(event.event == SubmenuIndexExtraActions) {
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneExtraActions);
+ consumed = true;
+ }
+ scene_manager_set_scene_state(app->scene_manager, LfRfidSceneStart, event.event);
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_start_on_exit(void* context) {
+ LfRfid* app = context;
+
+ submenu_reset(app->submenu);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_write.c b/applications/lfrfid/scenes/lfrfid_scene_write.c
new file mode 100644
index 000000000..4b03bac15
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_write.c
@@ -0,0 +1,96 @@
+#include "../lfrfid_i.h"
+
+static void lfrfid_write_callback(LFRFIDWorkerWriteResult result, void* context) {
+ LfRfid* app = context;
+ uint32_t event = 0;
+
+ if(result == LFRFIDWorkerWriteOK) {
+ event = LfRfidEventWriteOK;
+ } else if(result == LFRFIDWorkerWriteProtocolCannotBeWritten) {
+ event = LfRfidEventWriteProtocolCannotBeWritten;
+ } else if(result == LFRFIDWorkerWriteFobCannotBeWritten) {
+ event = LfRfidEventWriteFobCannotBeWritten;
+ } else if(result == LFRFIDWorkerWriteTooLongToWrite) {
+ event = LfRfidEventWriteTooLongToWrite;
+ }
+
+ view_dispatcher_send_custom_event(app->view_dispatcher, event);
+}
+
+void lfrfid_scene_write_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ popup_set_header(popup, "Writing", 89, 30, AlignCenter, AlignTop);
+ if(!string_empty_p(app->file_name)) {
+ popup_set_text(popup, string_get_cstr(app->file_name), 89, 43, AlignCenter, AlignTop);
+ } else {
+ popup_set_text(
+ popup,
+ protocol_dict_get_name(app->dict, app->protocol_id),
+ 89,
+ 43,
+ AlignCenter,
+ AlignTop);
+ }
+ popup_set_icon(popup, 0, 3, &I_RFIDDolphinSend_97x61);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ app->old_key_data = (uint8_t*)malloc(size);
+ protocol_dict_get_data(app->dict, app->protocol_id, app->old_key_data, size);
+
+ lfrfid_worker_start_thread(app->lfworker);
+ lfrfid_worker_write_start(
+ app->lfworker, (LFRFIDProtocol)app->protocol_id, lfrfid_write_callback, app);
+ notification_message(app->notifications, &sequence_blink_start_magenta);
+}
+
+bool lfrfid_scene_write_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+ bool consumed = false;
+
+ if(event.type == SceneManagerEventTypeCustom) {
+ if(event.event == LfRfidEventWriteOK) {
+ notification_message(app->notifications, &sequence_success);
+ scene_manager_next_scene(app->scene_manager, LfRfidSceneWriteSuccess);
+ consumed = true;
+ } else if(event.event == LfRfidEventWriteProtocolCannotBeWritten) {
+ popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
+ popup_set_header(popup, "Error", 64, 3, AlignCenter, AlignTop);
+ popup_set_text(popup, "This protocol\ncannot be written", 3, 17, AlignLeft, AlignTop);
+ notification_message(app->notifications, &sequence_blink_start_red);
+ consumed = true;
+ } else if(
+ (event.event == LfRfidEventWriteFobCannotBeWritten) ||
+ (event.event == LfRfidEventWriteTooLongToWrite)) {
+ popup_set_icon(popup, 72, 17, &I_DolphinCommon_56x48);
+ popup_set_header(popup, "Still trying to write...", 64, 3, AlignCenter, AlignTop);
+ popup_set_text(
+ popup,
+ "Make sure this\ncard is writable\nand not\nprotected.",
+ 3,
+ 17,
+ AlignLeft,
+ AlignTop);
+ notification_message(app->notifications, &sequence_blink_start_yellow);
+ consumed = true;
+ }
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_write_on_exit(void* context) {
+ LfRfid* app = context;
+ notification_message(app->notifications, &sequence_blink_stop);
+ popup_reset(app->popup);
+ lfrfid_worker_stop(app->lfworker);
+ lfrfid_worker_stop_thread(app->lfworker);
+
+ size_t size = protocol_dict_get_data_size(app->dict, app->protocol_id);
+ protocol_dict_set_data(app->dict, app->protocol_id, app->old_key_data, size);
+ free(app->old_key_data);
+}
diff --git a/applications/lfrfid/scenes/lfrfid_scene_write_success.c b/applications/lfrfid/scenes/lfrfid_scene_write_success.c
new file mode 100644
index 000000000..52e30d6b6
--- /dev/null
+++ b/applications/lfrfid/scenes/lfrfid_scene_write_success.c
@@ -0,0 +1,38 @@
+#include "../lfrfid_i.h"
+
+void lfrfid_scene_write_success_on_enter(void* context) {
+ LfRfid* app = context;
+ Popup* popup = app->popup;
+
+ popup_set_header(popup, "Successfully\nwritten!", 94, 3, AlignCenter, AlignTop);
+ popup_set_icon(popup, 0, 6, &I_RFIDDolphinSuccess_108x57);
+ popup_set_context(popup, app);
+ popup_set_callback(popup, lfrfid_popup_timeout_callback);
+ popup_set_timeout(popup, 1500);
+ popup_enable_timeout(popup);
+
+ view_dispatcher_switch_to_view(app->view_dispatcher, LfRfidViewPopup);
+ notification_message_block(app->notifications, &sequence_set_green_255);
+}
+
+bool lfrfid_scene_write_success_on_event(void* context, SceneManagerEvent event) {
+ LfRfid* app = context;
+ bool consumed = false;
+
+ const uint32_t prev_scenes[] = {LfRfidSceneReadKeyMenu, LfRfidSceneSelectKey};
+
+ if((event.type == SceneManagerEventTypeBack) ||
+ ((event.type == SceneManagerEventTypeCustom) && (event.event == LfRfidEventPopupClosed))) {
+ scene_manager_search_and_switch_to_previous_scene_one_of(
+ app->scene_manager, prev_scenes, COUNT_OF(prev_scenes));
+ consumed = true;
+ }
+
+ return consumed;
+}
+
+void lfrfid_scene_write_success_on_exit(void* context) {
+ LfRfid* app = context;
+ notification_message_block(app->notifications, &sequence_reset_green);
+ popup_reset(app->popup);
+}
diff --git a/applications/lfrfid/view/container_vm.cpp b/applications/lfrfid/view/container_vm.cpp
deleted file mode 100644
index 3c01ba304..000000000
--- a/applications/lfrfid/view/container_vm.cpp
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "container_vm.h"
-#include "elements/generic_element.h"
-#include "elements/string_element.h"
-#include "elements/icon_element.h"
-#include "elements/button_element.h"
-#include
-
-class ContainerVMData {
-public:
- ContainerVMData(){};
-
- ~ContainerVMData() {
- for(auto& it : elements) delete it;
- };
-
- std::list elements;
-
- template T add(const T element, View* view) {
- elements.push_back(element);
- element->set_parent_view(view);
- return element;
- }
-
- void clean() {
- for(auto& it : elements) delete it;
- elements.clear();
- }
-};
-
-struct ContainerVMModel {
- ContainerVMData* data;
-};
-
-ContainerVM::ContainerVM() {
- view = view_alloc();
- view_set_context(view, this);
- view_allocate_model(view, ViewModelTypeLocking, sizeof(ContainerVMModel));
-
- with_view_model_cpp(view, ContainerVMModel, model, {
- model->data = new ContainerVMData();
- return true;
- });
-
- view_set_draw_callback(view, view_draw_callback);
- view_set_input_callback(view, view_input_callback);
-}
-
-ContainerVM::~ContainerVM() {
- with_view_model_cpp(view, ContainerVMModel, model, {
- delete model->data;
- model->data = NULL;
- return false;
- });
-
- view_free(view);
-}
-
-View* ContainerVM::get_view() {
- return view;
-}
-
-void ContainerVM::clean() {
- with_view_model_cpp(view, ContainerVMModel, model, {
- model->data->clean();
- return true;
- });
-}
-
-template