New LF-RFID app (#534)
* Hal lfrfid: add read timer pulse and period config fns * New debug application for lfrfid subsystem * New lfrfid: app, fix naming * App lfrfid: assets * Container view module * App ibutton: remove unused header * App lfrfid scenes * App notification, add yield to blocking operations, add speaker volume control * App lfrfid: reading key scene * Assets: placeholder icon * App lfrfid: reworked container view module * App lfrfid: new scenes * App lfrfid: write scene * App lfrfid: write hid * App lfrfid: emulate scene * App lfrfid: save name scene * App lfrfid: add missing file
This commit is contained in:
		
							parent
							
								
									5d746234e9
								
							
						
					
					
						commit
						22e1ecb642
					
				| @ -16,7 +16,6 @@ int32_t gui_task(void* p); | ||||
| int32_t backlight_control(void* p); | ||||
| int32_t irda(void* p); | ||||
| int32_t app_loader(void* p); | ||||
| int32_t app_lfrfid(void* p); | ||||
| int32_t nfc_task(void* p); | ||||
| int32_t dolphin_task(void* p); | ||||
| int32_t power_task(void* p); | ||||
| @ -40,6 +39,8 @@ int32_t internal_storage_task(void* p); | ||||
| int32_t app_archive(void* p); | ||||
| int32_t notification_app(void* p); | ||||
| int32_t scened_app(void* p); | ||||
| int32_t lfrfid_app(void* p); | ||||
| int32_t lfrfid_debug_app(void* p); | ||||
| 
 | ||||
| // On system start hooks declaration
 | ||||
| void irda_cli_init(); | ||||
| @ -104,7 +105,8 @@ const FlipperApplication FLIPPER_SERVICES[] = { | ||||
| #endif | ||||
| 
 | ||||
| #ifdef SRV_LF_RFID | ||||
|     {.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
|     // TODO: fix stack size when sd api will be in separate thread
 | ||||
|     {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef SRV_IRDA | ||||
| @ -186,7 +188,8 @@ const FlipperApplication FLIPPER_APPS[] = { | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_LF_RFID | ||||
|     {.app = app_lfrfid, .name = "125 kHz RFID", .stack_size = 1024, .icon = A_125khz_14}, | ||||
|     // TODO: fix stack size when sd api will be in separate thread
 | ||||
|     {.app = lfrfid_app, .name = "125 kHz RFID", .stack_size = 4096, .icon = A_125khz_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_IRDA | ||||
| @ -302,6 +305,10 @@ const FlipperApplication FLIPPER_DEBUG_APPS[] = { | ||||
| #ifdef APP_SCENED | ||||
|     {.app = scened_app, .name = "Templated Scene", .stack_size = 1024, .icon = A_Plugins_14}, | ||||
| #endif | ||||
| 
 | ||||
| #ifdef APP_LF_RFID | ||||
|     {.app = lfrfid_debug_app, .name = "LF-RFID Debug", .stack_size = 1024, .icon = A_125khz_14}, | ||||
| #endif | ||||
| }; | ||||
| 
 | ||||
| const size_t FLIPPER_DEBUG_APPS_COUNT = sizeof(FLIPPER_DEBUG_APPS) / sizeof(FlipperApplication); | ||||
|  | ||||
| @ -39,8 +39,7 @@ static void dialog_ex_view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| 
 | ||||
|     // TODO other criteria for the draw
 | ||||
|     if(model->icon.x >= 0 && model->icon.y >= 0) { | ||||
|     if(model->icon.name != I_Empty_1x1) { | ||||
|         canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name); | ||||
|     } | ||||
| 
 | ||||
| @ -135,10 +134,9 @@ DialogEx* dialog_ex_alloc() { | ||||
|             model->text.horizontal = AlignLeft; | ||||
|             model->text.vertical = AlignBottom; | ||||
| 
 | ||||
|             // TODO other criteria for the draw
 | ||||
|             model->icon.x = -1; | ||||
|             model->icon.y = -1; | ||||
|             model->icon.name = I_ButtonCenter_7x7; | ||||
|             model->icon.x = 0; | ||||
|             model->icon.y = 0; | ||||
|             model->icon.name = I_Empty_1x1; | ||||
| 
 | ||||
|             model->left_text = NULL; | ||||
|             model->center_text = NULL; | ||||
| @ -208,7 +206,7 @@ void dialog_ex_set_text( | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name) { | ||||
| void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name) { | ||||
|     furi_assert(dialog_ex); | ||||
|     with_view_model( | ||||
|         dialog_ex->view, (DialogExModel * model) { | ||||
|  | ||||
| @ -84,7 +84,7 @@ void dialog_ex_set_text( | ||||
|  * @param x, y - icon position | ||||
|  * @param name - icon to be shown | ||||
|  */ | ||||
| void dialog_ex_set_icon(DialogEx* dialog_ex, int8_t x, int8_t y, IconName name); | ||||
| void dialog_ex_set_icon(DialogEx* dialog_ex, uint8_t x, uint8_t y, IconName name); | ||||
| 
 | ||||
| /* Set left button text
 | ||||
|  * If text is null, left button will not be rendered and processed | ||||
|  | ||||
| @ -21,8 +21,8 @@ typedef struct { | ||||
| } TextElement; | ||||
| 
 | ||||
| typedef struct { | ||||
|     int8_t x; | ||||
|     int8_t y; | ||||
|     uint8_t x; | ||||
|     uint8_t y; | ||||
|     IconName name; | ||||
| } IconElement; | ||||
| 
 | ||||
| @ -39,8 +39,7 @@ static void popup_view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| 
 | ||||
|     // TODO other criteria for the draw
 | ||||
|     if(model->icon.x >= 0 && model->icon.y >= 0) { | ||||
|     if(model->icon.name != I_Empty_1x1) { | ||||
|         canvas_draw_icon_name(canvas, model->icon.x, model->icon.y, model->icon.name); | ||||
|     } | ||||
| 
 | ||||
| @ -137,10 +136,9 @@ Popup* popup_alloc() { | ||||
|             model->text.horizontal = AlignLeft; | ||||
|             model->text.vertical = AlignBottom; | ||||
| 
 | ||||
|             // TODO other criteria for the draw
 | ||||
|             model->icon.x = -1; | ||||
|             model->icon.y = -1; | ||||
|             model->icon.name = I_ButtonCenter_7x7; | ||||
|             model->icon.x = 0; | ||||
|             model->icon.y = 0; | ||||
|             model->icon.name = I_Empty_1x1; | ||||
|             return true; | ||||
|         }); | ||||
|     return popup; | ||||
| @ -206,7 +204,7 @@ void popup_set_text( | ||||
|         }); | ||||
| } | ||||
| 
 | ||||
| void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name) { | ||||
| void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name) { | ||||
|     furi_assert(popup); | ||||
|     with_view_model( | ||||
|         popup->view, (PopupModel * model) { | ||||
|  | ||||
| @ -77,7 +77,7 @@ void popup_set_text( | ||||
|  * @param x, y - icon position | ||||
|  * @param name - icon to be shown | ||||
|  */ | ||||
| void popup_set_icon(Popup* popup, int8_t x, int8_t y, IconName name); | ||||
| void popup_set_icon(Popup* popup, uint8_t x, uint8_t y, IconName name); | ||||
| 
 | ||||
| /* Set popup timeout
 | ||||
|  * @param popup - Popup instance | ||||
|  | ||||
| @ -27,7 +27,6 @@ | ||||
| 
 | ||||
| #include <sd-card-api.h> | ||||
| #include <filesystem-api.h> | ||||
| #include "../cli/cli.h" | ||||
| 
 | ||||
| #include "one_wire_master.h" | ||||
| #include "maxim_crc.h" | ||||
|  | ||||
| @ -36,7 +36,7 @@ void iButtonSceneDeleteSuccess::on_exit(iButtonApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| 
 | ||||
|     popup_disable_timeout(popup); | ||||
|     popup_set_context(popup, NULL); | ||||
|  | ||||
| @ -89,5 +89,5 @@ void iButtonSceneEmulate::on_exit(iButtonApp* app) { | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| } | ||||
| @ -74,7 +74,7 @@ void iButtonSceneReadSuccess::on_exit(iButtonApp* app) { | ||||
|     dialog_ex_set_right_button_text(dialog_ex, NULL); | ||||
|     dialog_ex_set_result_callback(dialog_ex, NULL); | ||||
|     dialog_ex_set_context(dialog_ex, NULL); | ||||
|     dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7); | ||||
|     dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1); | ||||
| 
 | ||||
|     app->notify_green_off(); | ||||
| } | ||||
|  | ||||
| @ -49,5 +49,5 @@ void iButtonSceneRead::on_exit(iButtonApp* app) { | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| } | ||||
| @ -39,7 +39,7 @@ void iButtonSceneSaveSuccess::on_exit(iButtonApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| 
 | ||||
|     popup_disable_timeout(popup); | ||||
|     popup_set_context(popup, NULL); | ||||
|  | ||||
| @ -40,7 +40,7 @@ void iButtonSceneWriteSuccess::on_exit(iButtonApp* app) { | ||||
|     Popup* popup = app->get_view_manager()->get_popup(); | ||||
| 
 | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| 
 | ||||
|     popup_disable_timeout(popup); | ||||
|     popup_set_context(popup, NULL); | ||||
|  | ||||
| @ -92,7 +92,7 @@ void iButtonSceneWrite::on_exit(iButtonApp* app) { | ||||
| 
 | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
|     popup_set_icon(popup, -1, -1, I_DolphinWait_61x59); | ||||
|     popup_set_icon(popup, 0, 0, I_Empty_1x1); | ||||
| 
 | ||||
|     app->get_key_worker()->stop_write(); | ||||
| } | ||||
| @ -41,7 +41,7 @@ void IrdaAppSceneEditDelete::on_enter(IrdaApp* app) { | ||||
|     } | ||||
| 
 | ||||
|     dialog_ex_set_text(dialog_ex, app->get_text_store(0), 64, 32, AlignCenter, AlignCenter); | ||||
|     dialog_ex_set_icon(dialog_ex, -1, -1, I_ButtonCenter_7x7); | ||||
|     dialog_ex_set_icon(dialog_ex, 0, 0, I_Empty_1x1); | ||||
|     dialog_ex_set_left_button_text(dialog_ex, "Back"); | ||||
|     dialog_ex_set_right_button_text(dialog_ex, "Delete"); | ||||
|     dialog_ex_set_result_callback(dialog_ex, dialog_result_callback); | ||||
|  | ||||
| @ -1,140 +0,0 @@ | ||||
| #include "lf-rfid-app.h" | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| #include <stdarg.h> | ||||
| 
 | ||||
| void LfrfidApp::run(void) { | ||||
|     LfrfidEvent event; | ||||
|     bool consumed; | ||||
|     bool exit = false; | ||||
| 
 | ||||
|     scenes[current_scene]->on_enter(this); | ||||
| 
 | ||||
|     while(!exit) { | ||||
|         view.receive_event(&event); | ||||
| 
 | ||||
|         consumed = scenes[current_scene]->on_event(this, &event); | ||||
| 
 | ||||
|         if(!consumed) { | ||||
|             if(event.type == LfrfidEvent::Type::Back) { | ||||
|                 exit = switch_to_previous_scene(); | ||||
|             } | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|     scenes[current_scene]->on_exit(this); | ||||
| } | ||||
| 
 | ||||
| LfrfidApp::LfrfidApp() { | ||||
|     api_hal_power_insomnia_enter(); | ||||
|     notification = static_cast<NotificationApp*>(furi_record_open("notification")); | ||||
| } | ||||
| 
 | ||||
| LfrfidApp::~LfrfidApp() { | ||||
|     for(std::map<Scene, LfrfidScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) { | ||||
|         delete it->second; | ||||
|         scenes.erase(it); | ||||
|     } | ||||
| 
 | ||||
|     furi_record_close("notification"); | ||||
| 
 | ||||
|     api_hal_power_insomnia_exit(); | ||||
| } | ||||
| 
 | ||||
| LfrfidAppViewManager* LfrfidApp::get_view_manager() { | ||||
|     return &view; | ||||
| } | ||||
| 
 | ||||
| void LfrfidApp::switch_to_next_scene(Scene next_scene) { | ||||
|     previous_scenes_list.push_front(current_scene); | ||||
| 
 | ||||
|     if(next_scene != Scene::Exit) { | ||||
|         scenes[current_scene]->on_exit(this); | ||||
|         current_scene = next_scene; | ||||
|         scenes[current_scene]->on_enter(this); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void LfrfidApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) { | ||||
|     Scene previous_scene = Scene::Start; | ||||
|     bool scene_found = false; | ||||
| 
 | ||||
|     while(!scene_found) { | ||||
|         previous_scene = get_previous_scene(); | ||||
|         for(Scene element : scenes_list) { | ||||
|             if(previous_scene == element || previous_scene == Scene::Start) { | ||||
|                 scene_found = true; | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     scenes[current_scene]->on_exit(this); | ||||
|     current_scene = previous_scene; | ||||
|     scenes[current_scene]->on_enter(this); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidApp::switch_to_previous_scene(uint8_t count) { | ||||
|     Scene previous_scene = Scene::Start; | ||||
| 
 | ||||
|     for(uint8_t i = 0; i < count; i++) { | ||||
|         previous_scene = get_previous_scene(); | ||||
|         if(previous_scene == Scene::Exit) break; | ||||
|     } | ||||
| 
 | ||||
|     if(previous_scene == Scene::Exit) { | ||||
|         return true; | ||||
|     } else { | ||||
|         scenes[current_scene]->on_exit(this); | ||||
|         current_scene = previous_scene; | ||||
|         scenes[current_scene]->on_enter(this); | ||||
|         return false; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| LfrfidApp::Scene LfrfidApp::get_previous_scene() { | ||||
|     Scene scene = previous_scenes_list.front(); | ||||
|     previous_scenes_list.pop_front(); | ||||
|     return scene; | ||||
| } | ||||
| 
 | ||||
| /***************************** NOTIFY *******************************/ | ||||
| 
 | ||||
| void LfrfidApp::notify_green_blink() { | ||||
|     notification_message(notification, &sequence_blink_green_10); | ||||
| } | ||||
| 
 | ||||
| void LfrfidApp::notify_success() { | ||||
|     notification_message(notification, &sequence_success); | ||||
| } | ||||
| 
 | ||||
| /*************************** TEXT STORE *****************************/ | ||||
| 
 | ||||
| char* LfrfidApp::get_text_store() { | ||||
|     return text_store; | ||||
| } | ||||
| 
 | ||||
| uint8_t LfrfidApp::get_text_store_size() { | ||||
|     return text_store_size; | ||||
| } | ||||
| 
 | ||||
| void LfrfidApp::set_text_store(const char* text...) { | ||||
|     va_list args; | ||||
|     va_start(args, text); | ||||
| 
 | ||||
|     vsnprintf(text_store, text_store_size, text, args); | ||||
| 
 | ||||
|     va_end(args); | ||||
| } | ||||
| 
 | ||||
| RfidReader* LfrfidApp::get_reader() { | ||||
|     return &reader; | ||||
| } | ||||
| 
 | ||||
| RfidTimerEmulator* LfrfidApp::get_emulator() { | ||||
|     return &emulator; | ||||
| } | ||||
| 
 | ||||
| RfidWriter* LfrfidApp::get_writer() { | ||||
|     return &writer; | ||||
| } | ||||
| @ -1,79 +0,0 @@ | ||||
| #pragma once | ||||
| #include <map> | ||||
| #include <list> | ||||
| #include "lf-rfid-view-manager.h" | ||||
| 
 | ||||
| #include "scene/lf-rfid-scene-start.h" | ||||
| #include "scene/lf-rfid-scene-emulate-indala.h" | ||||
| #include "scene/lf-rfid-scene-emulate-hid.h" | ||||
| #include "scene/lf-rfid-scene-emulate-emmarine.h" | ||||
| #include "scene/lf-rfid-scene-read-normal.h" | ||||
| #include "scene/lf-rfid-scene-read-indala.h" | ||||
| #include "scene/lf-rfid-scene-tune.h" | ||||
| #include "scene/lf-rfid-scene-write.h" | ||||
| 
 | ||||
| #include "helpers/rfid-reader.h" | ||||
| #include "helpers/rfid-timer-emulator.h" | ||||
| 
 | ||||
| #include <notification/notification-messages.h> | ||||
| 
 | ||||
| class LfrfidApp { | ||||
| public: | ||||
|     void run(void); | ||||
| 
 | ||||
|     LfrfidApp(); | ||||
|     ~LfrfidApp(); | ||||
| 
 | ||||
|     enum class Scene : uint8_t { | ||||
|         Exit, | ||||
|         Start, | ||||
|         ReadNormal, | ||||
|         ReadIndala, | ||||
|         EmulateIndala, | ||||
|         EmulateHID, | ||||
|         EmulateEM, | ||||
|         Tune, | ||||
|         Write, | ||||
|     }; | ||||
| 
 | ||||
|     LfrfidAppViewManager* get_view_manager(); | ||||
|     void switch_to_next_scene(Scene index); | ||||
|     void search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list); | ||||
|     bool switch_to_previous_scene(uint8_t count = 1); | ||||
|     Scene get_previous_scene(); | ||||
| 
 | ||||
|     void notify_green_blink(); | ||||
|     void notify_success(); | ||||
| 
 | ||||
|     char* get_text_store(); | ||||
|     uint8_t get_text_store_size(); | ||||
|     void set_text_store(const char* text...); | ||||
| 
 | ||||
|     RfidReader* get_reader(); | ||||
|     RfidTimerEmulator* get_emulator(); | ||||
|     RfidWriter* get_writer(); | ||||
| 
 | ||||
| private: | ||||
|     std::list<Scene> previous_scenes_list = {Scene::Exit}; | ||||
|     Scene current_scene = Scene::Start; | ||||
|     LfrfidAppViewManager view; | ||||
| 
 | ||||
|     std::map<Scene, LfrfidScene*> scenes = { | ||||
|         {Scene::Start, new LfrfidSceneStart()}, | ||||
|         {Scene::ReadNormal, new LfrfidSceneReadNormal()}, | ||||
|         {Scene::ReadIndala, new LfrfidSceneReadIndala()}, | ||||
|         {Scene::EmulateIndala, new LfrfidSceneEmulateIndala()}, | ||||
|         {Scene::EmulateHID, new LfrfidSceneEmulateHID()}, | ||||
|         {Scene::EmulateEM, new LfrfidSceneEmulateEMMarine()}, | ||||
|         {Scene::Tune, new LfrfidSceneTune()}, | ||||
|         {Scene::Write, new LfrfidSceneWrite()}, | ||||
|     }; | ||||
| 
 | ||||
|     static const uint8_t text_store_size = 128; | ||||
|     char text_store[text_store_size + 1]; | ||||
| 
 | ||||
|     NotificationApp* notification; | ||||
|     RfidReader reader; | ||||
|     RfidTimerEmulator emulator; | ||||
|     RfidWriter writer; | ||||
| }; | ||||
| @ -1,21 +0,0 @@ | ||||
| #pragma once | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| class LfrfidEvent { | ||||
| public: | ||||
|     // events enum
 | ||||
|     enum class Type : uint8_t { | ||||
|         Tick, | ||||
|         Back, | ||||
|         MenuSelected, | ||||
|         NextScene, | ||||
|     }; | ||||
| 
 | ||||
|     // payload
 | ||||
|     union { | ||||
|         uint32_t menu_index; | ||||
|     } payload; | ||||
| 
 | ||||
|     // event type
 | ||||
|     Type type; | ||||
| }; | ||||
| @ -1,90 +0,0 @@ | ||||
| #include "lf-rfid-view-manager.h" | ||||
| #include "lf-rfid-event.h" | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| LfrfidAppViewManager::LfrfidAppViewManager() { | ||||
|     event_queue = osMessageQueueNew(10, sizeof(LfrfidEvent), NULL); | ||||
| 
 | ||||
|     view_dispatcher = view_dispatcher_alloc(); | ||||
|     auto callback = cbc::obtain_connector(this, &LfrfidAppViewManager::previous_view_callback); | ||||
| 
 | ||||
|     // allocate views
 | ||||
|     submenu = submenu_alloc(); | ||||
|     add_view(ViewType::Submenu, submenu_get_view(submenu)); | ||||
| 
 | ||||
|     popup = popup_alloc(); | ||||
|     add_view(ViewType::Popup, popup_get_view(popup)); | ||||
| 
 | ||||
|     tune = new LfRfidViewTune(); | ||||
|     add_view(ViewType::Tune, tune->get_view()); | ||||
| 
 | ||||
|     gui = static_cast<Gui*>(furi_record_open("gui")); | ||||
|     view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen); | ||||
| 
 | ||||
|     // set previous view callback for all views
 | ||||
|     view_set_previous_callback(submenu_get_view(submenu), callback); | ||||
|     view_set_previous_callback(popup_get_view(popup), callback); | ||||
|     view_set_previous_callback(tune->get_view(), callback); | ||||
| } | ||||
| 
 | ||||
| LfrfidAppViewManager::~LfrfidAppViewManager() { | ||||
|     // remove views
 | ||||
|     view_dispatcher_remove_view( | ||||
|         view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Submenu)); | ||||
|     view_dispatcher_remove_view( | ||||
|         view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Popup)); | ||||
|     view_dispatcher_remove_view( | ||||
|         view_dispatcher, static_cast<uint32_t>(LfrfidAppViewManager::ViewType::Tune)); | ||||
| 
 | ||||
|     // free view modules
 | ||||
|     submenu_free(submenu); | ||||
|     popup_free(popup); | ||||
|     delete tune; | ||||
| 
 | ||||
|     // free dispatcher
 | ||||
|     view_dispatcher_free(view_dispatcher); | ||||
| 
 | ||||
|     // free event queue
 | ||||
|     osMessageQueueDelete(event_queue); | ||||
| } | ||||
| 
 | ||||
| void LfrfidAppViewManager::switch_to(ViewType type) { | ||||
|     view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type)); | ||||
| } | ||||
| 
 | ||||
| Submenu* LfrfidAppViewManager::get_submenu() { | ||||
|     return submenu; | ||||
| } | ||||
| 
 | ||||
| Popup* LfrfidAppViewManager::get_popup() { | ||||
|     return popup; | ||||
| } | ||||
| 
 | ||||
| LfRfidViewTune* LfrfidAppViewManager::get_tune() { | ||||
|     return tune; | ||||
| } | ||||
| 
 | ||||
| void LfrfidAppViewManager::receive_event(LfrfidEvent* event) { | ||||
|     if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) { | ||||
|         event->type = LfrfidEvent::Type::Tick; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void LfrfidAppViewManager::send_event(LfrfidEvent* event) { | ||||
|     osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0); | ||||
|     furi_check(result == osOK); | ||||
| } | ||||
| 
 | ||||
| uint32_t LfrfidAppViewManager::previous_view_callback(void* context) { | ||||
|     if(event_queue != NULL) { | ||||
|         LfrfidEvent event; | ||||
|         event.type = LfrfidEvent::Type::Back; | ||||
|         send_event(&event); | ||||
|     } | ||||
| 
 | ||||
|     return VIEW_IGNORE; | ||||
| } | ||||
| 
 | ||||
| void LfrfidAppViewManager::add_view(ViewType view_type, View* view) { | ||||
|     view_dispatcher_add_view(view_dispatcher, static_cast<uint32_t>(view_type), view); | ||||
| } | ||||
| @ -1,42 +0,0 @@ | ||||
| #pragma once | ||||
| #include <furi.h> | ||||
| #include <gui/view_dispatcher.h> | ||||
| #include <gui/modules/submenu.h> | ||||
| #include <gui/modules/popup.h> | ||||
| #include "lf-rfid-event.h" | ||||
| #include "view/lf-rfid-view-tune.h" | ||||
| 
 | ||||
| class LfrfidAppViewManager { | ||||
| public: | ||||
|     enum class ViewType : uint8_t { | ||||
|         Submenu, | ||||
|         Popup, | ||||
|         Tune, | ||||
|     }; | ||||
| 
 | ||||
|     osMessageQueueId_t event_queue; | ||||
| 
 | ||||
|     LfrfidAppViewManager(); | ||||
|     ~LfrfidAppViewManager(); | ||||
| 
 | ||||
|     void switch_to(ViewType type); | ||||
| 
 | ||||
|     void receive_event(LfrfidEvent* event); | ||||
|     void send_event(LfrfidEvent* event); | ||||
| 
 | ||||
|     Submenu* get_submenu(); | ||||
|     Popup* get_popup(); | ||||
|     LfRfidViewTune* get_tune(); | ||||
| 
 | ||||
| private: | ||||
|     ViewDispatcher* view_dispatcher; | ||||
|     Gui* gui; | ||||
| 
 | ||||
|     uint32_t previous_view_callback(void* context); | ||||
|     void add_view(ViewType view_type, View* view); | ||||
| 
 | ||||
|     // view elements
 | ||||
|     Submenu* submenu; | ||||
|     Popup* popup; | ||||
|     LfRfidViewTune* tune; | ||||
| }; | ||||
| @ -1,10 +0,0 @@ | ||||
| #include "lf-rfid-app.h" | ||||
| 
 | ||||
| // app enter function
 | ||||
| extern "C" int32_t app_lfrfid(void* p) { | ||||
|     LfrfidApp* app = new LfrfidApp(); | ||||
|     app->run(); | ||||
|     delete app; | ||||
| 
 | ||||
|     return 255; | ||||
| } | ||||
| @ -1,34 +0,0 @@ | ||||
| #include "lf-rfid-scene-emulate-emmarine.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneEmulateEMMarine::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("EM emulation"); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
|     app->get_emulator()->start(LfrfidKeyType::KeyEM4100, data, 5); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneEmulateEMMarine::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneEmulateEMMarine::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     app->get_emulator()->stop(); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| class LfrfidSceneEmulateEMMarine : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     const uint8_t data[5] = {0x53, 0x00, 0x5F, 0xB3, 0xC2}; | ||||
| }; | ||||
| @ -1,34 +0,0 @@ | ||||
| #include "lf-rfid-scene-emulate-hid.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneEmulateHID::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("HID H10301 emulation"); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
|     app->get_emulator()->start(LfrfidKeyType::KeyH10301, data, 3); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneEmulateHID::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneEmulateHID::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     app->get_emulator()->stop(); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| class LfrfidSceneEmulateHID : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     const uint8_t data[3] = {0xED, 0x87, 0x70}; | ||||
| }; | ||||
| @ -1,34 +0,0 @@ | ||||
| #include "lf-rfid-scene-emulate-indala.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneEmulateIndala::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("Indala 40134 emulation"); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
|     app->get_emulator()->start(LfrfidKeyType::KeyI40134, data, 3); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneEmulateIndala::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneEmulateIndala::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     app->get_emulator()->stop(); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| class LfrfidSceneEmulateIndala : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     const uint8_t data[3] = {0x1F, 0x2E, 0x3D}; | ||||
| }; | ||||
| @ -1,14 +0,0 @@ | ||||
| #pragma once | ||||
| #include "../lf-rfid-event.h" | ||||
| 
 | ||||
| class LfrfidApp; | ||||
| 
 | ||||
| class LfrfidScene { | ||||
| public: | ||||
|     virtual void on_enter(LfrfidApp* app) = 0; | ||||
|     virtual bool on_event(LfrfidApp* app, LfrfidEvent* event) = 0; | ||||
|     virtual void on_exit(LfrfidApp* app) = 0; | ||||
|     virtual ~LfrfidScene(){}; | ||||
| 
 | ||||
| private: | ||||
| }; | ||||
| @ -1,34 +0,0 @@ | ||||
| #include "lf-rfid-scene-read-indala.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneReadIndala::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID read Indala", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("[decoder not implemented]"); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
|     app->get_reader()->start(RfidReader::Type::Indala); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneReadIndala::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneReadIndala::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     app->get_reader()->stop(); | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| class LfrfidSceneReadIndala : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint32_t success_reads = 0; | ||||
|     static const uint8_t data_size = LFRFID_KEY_SIZE; | ||||
|     uint8_t last_data[data_size] = {0}; | ||||
| }; | ||||
| @ -1,89 +0,0 @@ | ||||
| #include "lf-rfid-scene-read-normal.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneReadNormal::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID read EM & HID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("waiting..."); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
|     app->get_reader()->start(RfidReader::Type::Normal); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneReadNormal::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfrfidEvent::Type::Tick) { | ||||
|         uint8_t data[data_size]; | ||||
|         LfrfidKeyType type; | ||||
| 
 | ||||
|         if(app->get_reader()->read(&type, data, data_size)) { | ||||
|             if(memcmp(last_data, data, data_size) == 0) { | ||||
|                 success_reads++; | ||||
|                 app->notify_green_blink(); | ||||
|             } else { | ||||
|                 success_reads = 1; | ||||
|                 memcpy(last_data, data, data_size); | ||||
|                 app->notify_success(); | ||||
|             } | ||||
| 
 | ||||
|             switch(type) { | ||||
|             case LfrfidKeyType::KeyEM4100: | ||||
|                 app->set_text_store( | ||||
|                     "[EM] %02X %02X %02X %02X %02X\n" | ||||
|                     "count: %u", | ||||
|                     data[0], | ||||
|                     data[1], | ||||
|                     data[2], | ||||
|                     data[3], | ||||
|                     data[4], | ||||
|                     success_reads); | ||||
|                 break; | ||||
|             case LfrfidKeyType::KeyH10301: | ||||
|                 app->set_text_store( | ||||
|                     "[HID26] %02X %02X %02X\n" | ||||
|                     "count: %u", | ||||
|                     data[0], | ||||
|                     data[1], | ||||
|                     data[2], | ||||
|                     success_reads); | ||||
|                 break; | ||||
|             case LfrfidKeyType::KeyI40134: | ||||
|                 app->set_text_store( | ||||
|                     "[IND] %02X %02X %02X\n" | ||||
|                     "count: %u", | ||||
|                     data[0], | ||||
|                     data[1], | ||||
|                     data[2], | ||||
|                     success_reads); | ||||
|                 break; | ||||
|             } | ||||
|             popup_set_text( | ||||
|                 app->get_view_manager()->get_popup(), | ||||
|                 app->get_text_store(), | ||||
|                 64, | ||||
|                 22, | ||||
|                 AlignCenter, | ||||
|                 AlignTop); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneReadNormal::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     app->get_reader()->stop(); | ||||
| } | ||||
| @ -1,15 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| class LfrfidSceneReadNormal : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint32_t success_reads = 0; | ||||
|     static const uint8_t data_size = LFRFID_KEY_SIZE; | ||||
|     uint8_t last_data[data_size] = {0}; | ||||
| }; | ||||
| @ -1,82 +0,0 @@ | ||||
| #include "lf-rfid-scene-start.h" | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubmenuIndexWrite, | ||||
|     SubmenuIndexReadNormal, | ||||
|     SubmenuIndexReadIndala, | ||||
|     SubmenuIndexEmulateEM, | ||||
|     SubmenuIndexEmulateHID, | ||||
|     SubmenuIndexEmulateIndala, | ||||
|     SubmenuIndexTune | ||||
| } SubmenuIndex; | ||||
| 
 | ||||
| void LfrfidSceneStart::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Submenu* submenu = view_manager->get_submenu(); | ||||
|     auto callback = cbc::obtain_connector(this, &LfrfidSceneStart::submenu_callback); | ||||
| 
 | ||||
|     submenu_add_item(submenu, "Write T5577", SubmenuIndexWrite, callback, app); | ||||
|     submenu_add_item(submenu, "Read Normal", SubmenuIndexReadNormal, callback, app); | ||||
|     submenu_add_item(submenu, "Read Indala", SubmenuIndexReadIndala, callback, app); | ||||
|     submenu_add_item(submenu, "Emulate EM", SubmenuIndexEmulateEM, callback, app); | ||||
|     submenu_add_item(submenu, "Emulate HID", SubmenuIndexEmulateHID, callback, app); | ||||
|     submenu_add_item(submenu, "Emulate Indala", SubmenuIndexEmulateIndala, callback, app); | ||||
|     submenu_add_item(submenu, "Tune", SubmenuIndexTune, callback, app); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Submenu); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneStart::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfrfidEvent::Type::MenuSelected) { | ||||
|         switch(event->payload.menu_index) { | ||||
|         case SubmenuIndexWrite: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::Write); | ||||
|             break; | ||||
|         case SubmenuIndexReadNormal: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::ReadNormal); | ||||
|             break; | ||||
|         case SubmenuIndexReadIndala: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::ReadIndala); | ||||
|             break; | ||||
|         case SubmenuIndexEmulateEM: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::EmulateEM); | ||||
|             break; | ||||
|             break; | ||||
|         case SubmenuIndexEmulateHID: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::EmulateHID); | ||||
|             break; | ||||
|         case SubmenuIndexEmulateIndala: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::EmulateIndala); | ||||
|             break; | ||||
|         case SubmenuIndexTune: | ||||
|             app->switch_to_next_scene(LfrfidApp::Scene::Tune); | ||||
|             break; | ||||
|         } | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneStart::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
|     Submenu* submenu = view_manager->get_submenu(); | ||||
| 
 | ||||
|     submenu_clean(submenu); | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneStart::submenu_callback(void* context, uint32_t index) { | ||||
|     LfrfidApp* app = static_cast<LfrfidApp*>(context); | ||||
|     LfrfidEvent event; | ||||
| 
 | ||||
|     event.type = LfrfidEvent::Type::MenuSelected; | ||||
|     event.payload.menu_index = index; | ||||
| 
 | ||||
|     app->get_view_manager()->send_event(&event); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/rfid-timer-emulator.h" | ||||
| 
 | ||||
| class LfrfidSceneStart : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     void submenu_callback(void* context, uint32_t index); | ||||
| }; | ||||
| @ -1,35 +0,0 @@ | ||||
| #include "lf-rfid-scene-tune.h" | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include <callback-connector.h> | ||||
| 
 | ||||
| void LfrfidSceneTune::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
|     //LfRfidViewTune* tune = view_manager->get_tune();
 | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Tune); | ||||
| 
 | ||||
|     reader.start(RfidReader::Type::Indala); | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneTune::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfrfidEvent::Type::Tick) { | ||||
|         LfRfidViewTune* tune = app->get_view_manager()->get_tune(); | ||||
| 
 | ||||
|         if(tune->is_dirty()) { | ||||
|             LFRFID_TIM.Instance->ARR = tune->get_ARR(); | ||||
|             LFRFID_TIM.Instance->CCR1 = tune->get_CCR(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneTune::on_exit(LfrfidApp* app) { | ||||
|     //LfRfidViewTune* tune = app->get_view_manager()->get_tune();
 | ||||
| 
 | ||||
|     reader.stop(); | ||||
| } | ||||
| @ -1,13 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/rfid-reader.h" | ||||
| 
 | ||||
| class LfrfidSceneTune : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     RfidReader reader; | ||||
| }; | ||||
| @ -1,70 +0,0 @@ | ||||
| #include "lf-rfid-scene-write.h" | ||||
| 
 | ||||
| #include "../lf-rfid-app.h" | ||||
| #include "../lf-rfid-view-manager.h" | ||||
| #include "../lf-rfid-event.h" | ||||
| #include "../helpers/key-info.h" | ||||
| 
 | ||||
| void LfrfidSceneWrite::on_enter(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, "LF-RFID", 64, 16, AlignCenter, AlignBottom); | ||||
|     app->set_text_store("Writing..."); | ||||
|     popup_set_text(popup, app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     view_manager->switch_to(LfrfidAppViewManager::ViewType::Popup); | ||||
| 
 | ||||
|     timing_index = 0; | ||||
| } | ||||
| 
 | ||||
| bool LfrfidSceneWrite::on_event(LfrfidApp* app, LfrfidEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     // TODO move read\write logic to key worker
 | ||||
| 
 | ||||
|     bool readed = false; | ||||
|     uint8_t em_data[5] = {0x1A, 0x2B, 0xC3, 0xD4, 0xE5}; | ||||
| 
 | ||||
|     if(timing_index == 0) { | ||||
|         app->get_reader()->stop(); | ||||
|         app->get_writer()->start(); | ||||
|         app->get_writer()->write_em(em_data); | ||||
|         app->get_writer()->stop(); | ||||
|         delay(200); | ||||
|         app->get_reader()->start(RfidReader::Type::Normal); | ||||
|     } else { | ||||
|         uint8_t data[LFRFID_KEY_SIZE]; | ||||
|         LfrfidKeyType type; | ||||
| 
 | ||||
|         app->get_reader()->read(&type, data, LFRFID_KEY_SIZE); | ||||
|         if(type == LfrfidKeyType::KeyEM4100) { | ||||
|             if(memcmp(em_data, data, 5) == 0) { | ||||
|                 readed = true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     if(readed) { | ||||
|         app->set_text_store("Writed!"); | ||||
|         app->notify_green_blink(); | ||||
|     } else { | ||||
|         app->set_text_store("Writing [1A 2B C3 D4 E5]"); | ||||
|         timing_index++; | ||||
|         if(timing_index == 4) { | ||||
|             timing_index = 0; | ||||
|         } | ||||
|     } | ||||
|     popup_set_text( | ||||
|         app->get_view_manager()->get_popup(), app->get_text_store(), 64, 22, AlignCenter, AlignTop); | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfrfidSceneWrite::on_exit(LfrfidApp* app) { | ||||
|     LfrfidAppViewManager* view_manager = app->get_view_manager(); | ||||
| 
 | ||||
|     Popup* popup = view_manager->get_popup(); | ||||
|     popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom); | ||||
|     popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop); | ||||
| } | ||||
| @ -1,14 +0,0 @@ | ||||
| #pragma once | ||||
| #include "lf-rfid-scene-generic.h" | ||||
| #include "../helpers/key-info.h" | ||||
| #include "../helpers/rfid-writer.h" | ||||
| 
 | ||||
| class LfrfidSceneWrite : public LfrfidScene { | ||||
| public: | ||||
|     void on_enter(LfrfidApp* app) final; | ||||
|     bool on_event(LfrfidApp* app, LfrfidEvent* event) final; | ||||
|     void on_exit(LfrfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     uint8_t timing_index; | ||||
| }; | ||||
							
								
								
									
										10
									
								
								applications/lfrfid-debug/lfrfid-debug-app-launcher.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								applications/lfrfid-debug/lfrfid-debug-app-launcher.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #include "lfrfid-debug-app.h" | ||||
| 
 | ||||
| // app enter function
 | ||||
| extern "C" int32_t lfrfid_debug_app(void* p) { | ||||
|     LfRfidDebugApp* app = new LfRfidDebugApp(); | ||||
|     app->run(); | ||||
|     delete app; | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										16
									
								
								applications/lfrfid-debug/lfrfid-debug-app.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								applications/lfrfid-debug/lfrfid-debug-app.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,16 @@ | ||||
| #include "lfrfid-debug-app.h" | ||||
| #include "scene/lfrfid-debug-app-scene-start.h" | ||||
| #include "scene/lfrfid-debug-app-scene-tune.h" | ||||
| 
 | ||||
| LfRfidDebugApp::LfRfidDebugApp() | ||||
|     : scene_controller{this} { | ||||
| } | ||||
| 
 | ||||
| LfRfidDebugApp::~LfRfidDebugApp() { | ||||
| } | ||||
| 
 | ||||
| void LfRfidDebugApp::run() { | ||||
|     scene_controller.add_scene(SceneType::Start, new LfRfidDebugAppSceneStart()); | ||||
|     scene_controller.add_scene(SceneType::TuneScene, new LfRfidDebugAppSceneTune()); | ||||
|     scene_controller.process(100); | ||||
| } | ||||
							
								
								
									
										40
									
								
								applications/lfrfid-debug/lfrfid-debug-app.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								applications/lfrfid-debug/lfrfid-debug-app.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,40 @@ | ||||
| #pragma once | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| 
 | ||||
| #include <generic-scene.hpp> | ||||
| #include <scene-controller.hpp> | ||||
| #include <view-controller.hpp> | ||||
| 
 | ||||
| #include <view-modules/submenu-vm.h> | ||||
| #include "view-modules/lfrfid-view-tune-vm.h" | ||||
| 
 | ||||
| class LfRfidDebugApp { | ||||
| public: | ||||
|     enum class EventType : uint8_t { | ||||
|         GENERIC_EVENT_ENUM_VALUES, | ||||
|         MenuSelected, | ||||
|     }; | ||||
| 
 | ||||
|     enum class SceneType : uint8_t { | ||||
|         GENERIC_SCENE_ENUM_VALUES, | ||||
|         TuneScene, | ||||
|     }; | ||||
| 
 | ||||
|     class Event { | ||||
|     public: | ||||
|         union { | ||||
|             int32_t menu_index; | ||||
|         } payload; | ||||
| 
 | ||||
|         EventType type; | ||||
|     }; | ||||
| 
 | ||||
|     SceneController<GenericScene<LfRfidDebugApp>, LfRfidDebugApp> scene_controller; | ||||
|     ViewController<LfRfidDebugApp, SubmenuVM, LfRfidViewTuneVM> view_controller; | ||||
| 
 | ||||
|     ~LfRfidDebugApp(); | ||||
|     LfRfidDebugApp(); | ||||
| 
 | ||||
|     void run(); | ||||
| }; | ||||
| @ -0,0 +1,47 @@ | ||||
| #include "lfrfid-debug-app-scene-start.h" | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubmenuTune, | ||||
| } SubmenuIndex; | ||||
| 
 | ||||
| void LfRfidDebugAppSceneStart::on_enter(LfRfidDebugApp* app, bool need_restore) { | ||||
|     auto submenu = app->view_controller.get<SubmenuVM>(); | ||||
|     auto callback = cbc::obtain_connector(this, &LfRfidDebugAppSceneStart::submenu_callback); | ||||
| 
 | ||||
|     submenu->add_item("Tune", SubmenuTune, callback, app); | ||||
| 
 | ||||
|     if(need_restore) { | ||||
|         submenu->set_selected_item(submenu_item_selected); | ||||
|     } | ||||
|     app->view_controller.switch_to<SubmenuVM>(); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidDebugAppSceneStart::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfRfidDebugApp::EventType::MenuSelected) { | ||||
|         submenu_item_selected = event->payload.menu_index; | ||||
|         switch(event->payload.menu_index) { | ||||
|         case SubmenuTune: | ||||
|             app->scene_controller.switch_to_next_scene(LfRfidDebugApp::SceneType::TuneScene); | ||||
|             break; | ||||
|         } | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidDebugAppSceneStart::on_exit(LfRfidDebugApp* app) { | ||||
|     app->view_controller.get<SubmenuVM>()->clean(); | ||||
| } | ||||
| 
 | ||||
| void LfRfidDebugAppSceneStart::submenu_callback(void* context, uint32_t index) { | ||||
|     LfRfidDebugApp* app = static_cast<LfRfidDebugApp*>(context); | ||||
|     LfRfidDebugApp::Event event; | ||||
| 
 | ||||
|     event.type = LfRfidDebugApp::EventType::MenuSelected; | ||||
|     event.payload.menu_index = index; | ||||
| 
 | ||||
|     app->view_controller.send_event(&event); | ||||
| } | ||||
| @ -0,0 +1,13 @@ | ||||
| #pragma once | ||||
| #include "../lfrfid-debug-app.h" | ||||
| 
 | ||||
| class LfRfidDebugAppSceneStart : public GenericScene<LfRfidDebugApp> { | ||||
| public: | ||||
|     void on_enter(LfRfidDebugApp* app, bool need_restore) final; | ||||
|     bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final; | ||||
|     void on_exit(LfRfidDebugApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     void submenu_callback(void* context, uint32_t index); | ||||
|     uint32_t submenu_item_selected = 0; | ||||
| }; | ||||
| @ -0,0 +1,28 @@ | ||||
| #include "lfrfid-debug-app-scene-tune.h" | ||||
| 
 | ||||
| void LfRfidDebugAppSceneTune::on_enter(LfRfidDebugApp* app, bool need_restore) { | ||||
|     app->view_controller.switch_to<LfRfidViewTuneVM>(); | ||||
| 
 | ||||
|     api_hal_rfid_pins_read(); | ||||
|     api_hal_rfid_tim_read(125000, 0.5); | ||||
|     api_hal_rfid_tim_read_start(); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidDebugAppSceneTune::on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     LfRfidViewTuneVM* tune = app->view_controller; | ||||
| 
 | ||||
|     if(tune->is_dirty()) { | ||||
|         api_hal_rfid_set_read_period(tune->get_ARR()); | ||||
|         api_hal_rfid_set_read_pulse(tune->get_CCR()); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidDebugAppSceneTune::on_exit(LfRfidDebugApp* app) { | ||||
|     api_hal_rfid_tim_read_stop(); | ||||
|     api_hal_rfid_tim_reset(); | ||||
|     api_hal_rfid_pins_reset(); | ||||
| } | ||||
| @ -0,0 +1,9 @@ | ||||
| #pragma once | ||||
| #include "../lfrfid-debug-app.h" | ||||
| 
 | ||||
| class LfRfidDebugAppSceneTune : public GenericScene<LfRfidDebugApp> { | ||||
| public: | ||||
|     void on_enter(LfRfidDebugApp* app, bool need_restore) final; | ||||
|     bool on_event(LfRfidDebugApp* app, LfRfidDebugApp::Event* event) final; | ||||
|     void on_exit(LfRfidDebugApp* app) final; | ||||
| }; | ||||
| @ -1,10 +1,8 @@ | ||||
| #include "lf-rfid-view-tune.h" | ||||
| #include "lfrfid-view-tune-vm.h" | ||||
| #include <callback-connector.h> | ||||
| #include <gui/elements.h> | ||||
| #include <variant> | ||||
| #include <list> | ||||
| 
 | ||||
| struct LfRfidViewTuneModel { | ||||
| struct LfRfidViewTuneVMModel { | ||||
|     bool dirty; | ||||
|     bool fine; | ||||
|     uint32_t ARR; | ||||
| @ -12,8 +10,8 @@ struct LfRfidViewTuneModel { | ||||
|     int pos; | ||||
| }; | ||||
| 
 | ||||
| void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     LfRfidViewTuneModel* model = reinterpret_cast<LfRfidViewTuneModel*>(_model); | ||||
| void LfRfidViewTuneVM::view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     LfRfidViewTuneVMModel* model = reinterpret_cast<LfRfidViewTuneVMModel*>(_model); | ||||
|     canvas_clear(canvas); | ||||
|     canvas_set_color(canvas, ColorBlack); | ||||
| 
 | ||||
| @ -47,8 +45,8 @@ void LfRfidViewTune::view_draw_callback(Canvas* canvas, void* _model) { | ||||
|     elements_multiline_text_aligned(canvas, 2, 2, AlignLeft, AlignTop, buffer); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) { | ||||
|     LfRfidViewTune* _this = reinterpret_cast<LfRfidViewTune*>(context); | ||||
| bool LfRfidViewTuneVM::view_input_callback(InputEvent* event, void* context) { | ||||
|     LfRfidViewTuneVM* _this = reinterpret_cast<LfRfidViewTuneVM*>(context); | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     // Process key presses only
 | ||||
| @ -80,22 +78,22 @@ bool LfRfidViewTune::view_input_callback(InputEvent* event, void* context) { | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidViewTune::button_up() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
| void LfRfidViewTuneVM::button_up() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         if(model->pos > 0) model->pos--; | ||||
|         return true; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void LfRfidViewTune::button_down() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
| void LfRfidViewTuneVM::button_down() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         if(model->pos < 1) model->pos++; | ||||
|         return true; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void LfRfidViewTune::button_left() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
| void LfRfidViewTuneVM::button_left() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         if(model->pos == 0) { | ||||
|             if(model->fine) { | ||||
|                 model->ARR -= 1; | ||||
| @ -115,8 +113,8 @@ void LfRfidViewTune::button_left() { | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void LfRfidViewTune::button_right() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
| void LfRfidViewTuneVM::button_right() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         if(model->pos == 0) { | ||||
|             if(model->fine) { | ||||
|                 model->ARR += 1; | ||||
| @ -136,19 +134,19 @@ void LfRfidViewTune::button_right() { | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| void LfRfidViewTune::button_ok() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
| void LfRfidViewTuneVM::button_ok() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         model->fine = !model->fine; | ||||
|         return true; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| LfRfidViewTune::LfRfidViewTune() { | ||||
| LfRfidViewTuneVM::LfRfidViewTuneVM() { | ||||
|     view = view_alloc(); | ||||
|     view_set_context(view, this); | ||||
|     view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneModel)); | ||||
|     view_allocate_model(view, ViewModelTypeLocking, sizeof(LfRfidViewTuneVMModel)); | ||||
| 
 | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         model->dirty = true; | ||||
|         model->fine = false; | ||||
|         model->ARR = 511; | ||||
| @ -157,22 +155,34 @@ LfRfidViewTune::LfRfidViewTune() { | ||||
|         return true; | ||||
|     }); | ||||
| 
 | ||||
|     view_set_draw_callback(view, cbc::obtain_connector(this, &LfRfidViewTune::view_draw_callback)); | ||||
|     view_set_draw_callback( | ||||
|         view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_draw_callback)); | ||||
|     view_set_input_callback( | ||||
|         view, cbc::obtain_connector(this, &LfRfidViewTune::view_input_callback)); | ||||
|         view, cbc::obtain_connector(this, &LfRfidViewTuneVM::view_input_callback)); | ||||
| } | ||||
| 
 | ||||
| LfRfidViewTune::~LfRfidViewTune() { | ||||
| LfRfidViewTuneVM::~LfRfidViewTuneVM() { | ||||
|     view_free(view); | ||||
| } | ||||
| 
 | ||||
| View* LfRfidViewTune::get_view() { | ||||
| View* LfRfidViewTuneVM::get_view() { | ||||
|     return view; | ||||
| } | ||||
| 
 | ||||
| bool LfRfidViewTune::is_dirty() { | ||||
| void LfRfidViewTuneVM::clean() { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         model->dirty = true; | ||||
|         model->fine = false; | ||||
|         model->ARR = 511; | ||||
|         model->CCR = 255; | ||||
|         model->pos = 0; | ||||
|         return true; | ||||
|     }); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidViewTuneVM::is_dirty() { | ||||
|     bool result; | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         result = model->dirty; | ||||
|         model->dirty = false; | ||||
|         return false; | ||||
| @ -181,9 +191,9 @@ bool LfRfidViewTune::is_dirty() { | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| uint32_t LfRfidViewTune::get_ARR() { | ||||
| uint32_t LfRfidViewTuneVM::get_ARR() { | ||||
|     uint32_t result; | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         result = model->ARR; | ||||
|         return false; | ||||
|     }); | ||||
| @ -191,9 +201,9 @@ uint32_t LfRfidViewTune::get_ARR() { | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| uint32_t LfRfidViewTune::get_CCR() { | ||||
| uint32_t LfRfidViewTuneVM::get_CCR() { | ||||
|     uint32_t result; | ||||
|     with_view_model_cpp(view, LfRfidViewTuneModel, model, { | ||||
|     with_view_model_cpp(view, LfRfidViewTuneVMModel, model, { | ||||
|         result = model->CCR; | ||||
|         return false; | ||||
|     }); | ||||
| @ -1,12 +1,13 @@ | ||||
| #pragma once | ||||
| #include <gui/view.h> | ||||
| #include <view-modules/generic-view-module.h> | ||||
| 
 | ||||
| class LfRfidViewTune { | ||||
| class LfRfidViewTuneVM : public GenericViewModule { | ||||
| public: | ||||
|     LfRfidViewTune(); | ||||
|     ~LfRfidViewTune(); | ||||
| 
 | ||||
|     View* get_view(); | ||||
|     LfRfidViewTuneVM(); | ||||
|     ~LfRfidViewTuneVM() final; | ||||
|     View* get_view() final; | ||||
|     void clean() final; | ||||
| 
 | ||||
|     bool is_dirty(); | ||||
|     uint32_t get_ARR(); | ||||
| @ -2,6 +2,7 @@ | ||||
| #include <stdint.h> | ||||
| 
 | ||||
| static const uint8_t LFRFID_KEY_SIZE = 8; | ||||
| static const uint8_t LFRFID_KEY_NAME_SIZE = 22; | ||||
| 
 | ||||
| enum class LfrfidKeyType : uint8_t { | ||||
|     KeyEM4100, | ||||
							
								
								
									
										44
									
								
								applications/lfrfid/helpers/rfid-key.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								applications/lfrfid/helpers/rfid-key.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,44 @@ | ||||
| #include "rfid-key.h" | ||||
| #include <furi/check.h> | ||||
| 
 | ||||
| RfidKey::RfidKey() { | ||||
|     data.fill(0); | ||||
| 
 | ||||
|     for(uint8_t i = 0; i < (LFRFID_KEY_NAME_SIZE + 1); i++) { | ||||
|         name[i] = 0; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| RfidKey::~RfidKey() { | ||||
| } | ||||
| 
 | ||||
| void RfidKey::set_type(LfrfidKeyType _type) { | ||||
|     type = _type; | ||||
| } | ||||
| 
 | ||||
| void RfidKey::set_data(uint8_t* _data, const uint8_t _data_size) { | ||||
|     furi_assert(_data_size <= data.size()); | ||||
|     for(uint8_t i = 0; i < _data_size; i++) { | ||||
|         data[i] = _data[i]; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| LfrfidKeyType RfidKey::get_type() { | ||||
|     return type; | ||||
| } | ||||
| 
 | ||||
| uint8_t* RfidKey::get_data() { | ||||
|     return &data[0]; | ||||
| } | ||||
| 
 | ||||
| const char* RfidKey::get_type_text() { | ||||
|     return lfrfid_key_get_type_string(type); | ||||
| } | ||||
| 
 | ||||
| const uint8_t RfidKey::get_type_data_count() { | ||||
|     return lfrfid_key_get_type_data_count(type); | ||||
| } | ||||
| 
 | ||||
| char* RfidKey::get_name() { | ||||
|     return name; | ||||
| } | ||||
							
								
								
									
										25
									
								
								applications/lfrfid/helpers/rfid-key.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								applications/lfrfid/helpers/rfid-key.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| #pragma once | ||||
| #include "key-info.h" | ||||
| #include <array> | ||||
| 
 | ||||
| class RfidKey { | ||||
| public: | ||||
|     RfidKey(); | ||||
|     ~RfidKey(); | ||||
| 
 | ||||
|     void set_type(LfrfidKeyType type); | ||||
|     void set_data(uint8_t* data, const uint8_t data_size); | ||||
| 
 | ||||
|     LfrfidKeyType get_type(); | ||||
|     uint8_t* get_data(); | ||||
| 
 | ||||
|     const char* get_type_text(); | ||||
|     const uint8_t get_type_data_count(); | ||||
| 
 | ||||
|     char* get_name(); | ||||
| 
 | ||||
| private: | ||||
|     std::array<uint8_t, LFRFID_KEY_SIZE> data; | ||||
|     LfrfidKeyType type; | ||||
|     char name[LFRFID_KEY_NAME_SIZE + 1]; | ||||
| }; | ||||
							
								
								
									
										35
									
								
								applications/lfrfid/helpers/rfid-name-generator.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								applications/lfrfid/helpers/rfid-name-generator.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,35 @@ | ||||
| #include "rfid-name-generator.h" | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| 
 | ||||
| void rfid_generate_random_name(char* name, uint8_t max_name_size) { | ||||
|     const uint8_t prefix_size = 9; | ||||
|     const char* prefix[prefix_size] = { | ||||
|         "good", | ||||
|         "nice", | ||||
|         "best", | ||||
|         "some", | ||||
|         "strange", | ||||
|         "working", | ||||
|         "that", | ||||
|         "forgettable", | ||||
|         "easy", | ||||
|     }; | ||||
| 
 | ||||
|     const uint8_t suffix_size = 7; | ||||
|     const char* suffix[suffix_size] = { | ||||
|         "pass", | ||||
|         "card", | ||||
|         "key", | ||||
|         "fob", | ||||
|         "permit", | ||||
|         "pass", | ||||
|         "one", | ||||
|     }; | ||||
| 
 | ||||
|     sniprintf( | ||||
|         name, max_name_size, "%s_%s", prefix[rand() % prefix_size], suffix[rand() % suffix_size]); | ||||
| 
 | ||||
|     // to upper
 | ||||
|     name[0] = name[0] - ('a' - 'A'); | ||||
| } | ||||
							
								
								
									
										4
									
								
								applications/lfrfid/helpers/rfid-name-generator.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										4
									
								
								applications/lfrfid/helpers/rfid-name-generator.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,4 @@ | ||||
| #pragma once | ||||
| #include "stdint.h" | ||||
| 
 | ||||
| void rfid_generate_random_name(char* name, uint8_t max_name_size); | ||||
| @ -18,7 +18,7 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d | ||||
|     if(encoders.count(type)) { | ||||
|         current_encoder = encoders.find(type)->second; | ||||
| 
 | ||||
|         if(lfrfid_key_get_type_data_count(type) == data_size) { | ||||
|         if(data_size >= lfrfid_key_get_type_data_count(type)) { | ||||
|             current_encoder->init(data, data_size); | ||||
| 
 | ||||
|             api_hal_rfid_tim_emulate(125000); | ||||
| @ -26,14 +26,6 @@ void RfidTimerEmulator::start(LfrfidKeyType type, const uint8_t* data, uint8_t d | ||||
| 
 | ||||
|             api_interrupt_add(timer_update_callback, InterruptTypeTimerUpdate, this); | ||||
| 
 | ||||
|             // TODO make api for interrupts priority
 | ||||
|             for(size_t i = WWDG_IRQn; i <= DMAMUX1_OVR_IRQn; i++) { | ||||
|                 HAL_NVIC_SetPriority(static_cast<IRQn_Type>(i), 15, 0); | ||||
|             } | ||||
| 
 | ||||
|             HAL_NVIC_SetPriority(TIM1_UP_TIM16_IRQn, 5, 0); | ||||
|             HAL_NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); | ||||
| 
 | ||||
|             api_hal_rfid_tim_emulate_start(); | ||||
|         } | ||||
|     } else { | ||||
							
								
								
									
										111
									
								
								applications/lfrfid/helpers/rfid-worker.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								applications/lfrfid/helpers/rfid-worker.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,111 @@ | ||||
| #include "rfid-worker.h" | ||||
| 
 | ||||
| RfidWorker::RfidWorker() { | ||||
| } | ||||
| 
 | ||||
| RfidWorker::~RfidWorker() { | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::start_read() { | ||||
|     reader.start(RfidReader::Type::Normal); | ||||
| } | ||||
| 
 | ||||
| bool RfidWorker::read() { | ||||
|     static const uint8_t data_size = LFRFID_KEY_SIZE; | ||||
|     uint8_t data[data_size] = {0}; | ||||
|     LfrfidKeyType type; | ||||
| 
 | ||||
|     bool result = reader.read(&type, data, data_size); | ||||
| 
 | ||||
|     if(result) { | ||||
|         key.set_type(type); | ||||
|         key.set_data(data, data_size); | ||||
|     }; | ||||
| 
 | ||||
|     return result; | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::stop_read() { | ||||
|     reader.stop(); | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::start_write() { | ||||
|     write_result = WriteResult::Nothing; | ||||
|     write_sequence = new TickSequencer(); | ||||
|     validate_counts = 0; | ||||
| 
 | ||||
|     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write, this)); | ||||
|     write_sequence->do_after_tick(2, std::bind(&RfidWorker::sq_write_start_validate, this)); | ||||
|     write_sequence->do_after_tick(15, std::bind(&RfidWorker::sq_write_validate, this)); | ||||
|     write_sequence->do_every_tick(1, std::bind(&RfidWorker::sq_write_stop_validate, this)); | ||||
| } | ||||
| 
 | ||||
| RfidWorker::WriteResult RfidWorker::write() { | ||||
|     write_sequence->tick(); | ||||
|     return write_result; | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::stop_write() { | ||||
|     delete write_sequence; | ||||
|     reader.stop(); | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::start_emulate() { | ||||
|     emulator.start(key.get_type(), key.get_data(), key.get_type_data_count()); | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::stop_emulate() { | ||||
|     emulator.stop(); | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::sq_write() { | ||||
|     // TODO expand this
 | ||||
|     switch(key.get_type()) { | ||||
|     case LfrfidKeyType::KeyEM4100: | ||||
|         writer.start(); | ||||
|         writer.write_em(key.get_data()); | ||||
|         writer.stop(); | ||||
|         break; | ||||
|     case LfrfidKeyType::KeyH10301: | ||||
|         writer.start(); | ||||
|         writer.write_hid(key.get_data()); | ||||
|         writer.stop(); | ||||
|         break; | ||||
| 
 | ||||
|     default: | ||||
|         break; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::sq_write_start_validate() { | ||||
|     reader.start(RfidReader::Type::Normal); | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::sq_write_validate() { | ||||
|     static const uint8_t data_size = LFRFID_KEY_SIZE; | ||||
|     uint8_t data[data_size] = {0}; | ||||
|     LfrfidKeyType type; | ||||
| 
 | ||||
|     bool result = reader.read(&type, data, data_size); | ||||
| 
 | ||||
|     if(result) { | ||||
|         if(type == key.get_type()) { | ||||
|             if(memcmp(data, key.get_data(), key.get_type_data_count()) == 0) { | ||||
|                 write_result = WriteResult::Ok; | ||||
|                 validate_counts = 0; | ||||
|             } else { | ||||
|                 validate_counts++; | ||||
|             } | ||||
|         } else { | ||||
|             validate_counts++; | ||||
|         } | ||||
| 
 | ||||
|         if(validate_counts > 5) { | ||||
|             write_result = WriteResult::NotWritable; | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| void RfidWorker::sq_write_stop_validate() { | ||||
|     reader.stop(); | ||||
| } | ||||
							
								
								
									
										46
									
								
								applications/lfrfid/helpers/rfid-worker.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								applications/lfrfid/helpers/rfid-worker.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,46 @@ | ||||
| #pragma once | ||||
| #include "key-info.h" | ||||
| #include "rfid-reader.h" | ||||
| #include "rfid-writer.h" | ||||
| #include "rfid-timer-emulator.h" | ||||
| #include "rfid-key.h" | ||||
| #include "state-sequencer.h" | ||||
| 
 | ||||
| class RfidWorker { | ||||
| public: | ||||
|     RfidWorker(); | ||||
|     ~RfidWorker(); | ||||
| 
 | ||||
|     void start_read(); | ||||
|     bool read(); | ||||
|     void stop_read(); | ||||
| 
 | ||||
|     enum class WriteResult : uint8_t { | ||||
|         Ok, | ||||
|         NotWritable, | ||||
|         Nothing, | ||||
|     }; | ||||
| 
 | ||||
|     void start_write(); | ||||
|     WriteResult write(); | ||||
|     void stop_write(); | ||||
| 
 | ||||
|     void start_emulate(); | ||||
|     void stop_emulate(); | ||||
| 
 | ||||
|     RfidKey key; | ||||
| 
 | ||||
| private: | ||||
|     RfidWriter writer; | ||||
|     RfidReader reader; | ||||
|     RfidTimerEmulator emulator; | ||||
| 
 | ||||
|     WriteResult write_result; | ||||
|     TickSequencer* write_sequence; | ||||
| 
 | ||||
|     void sq_write(); | ||||
|     void sq_write_start_validate(); | ||||
|     void sq_write_validate(); | ||||
|     uint8_t validate_counts; | ||||
|     void sq_write_stop_validate(); | ||||
| }; | ||||
| @ -1,6 +1,7 @@ | ||||
| #include "rfid-writer.h" | ||||
| #include <api-hal.h> | ||||
| #include "protocols/protocol-emmarin.h" | ||||
| #include "protocols/protocol-hid-h10301.h" | ||||
| 
 | ||||
| extern COMP_HandleTypeDef hcomp1; | ||||
| 
 | ||||
| @ -11,8 +12,8 @@ extern COMP_HandleTypeDef hcomp1; | ||||
| class T55xxTiming { | ||||
| public: | ||||
|     constexpr static const uint16_t wait_time = 400; | ||||
|     constexpr static const uint8_t start_gap = 15; | ||||
|     constexpr static const uint8_t write_gap = 10; | ||||
|     constexpr static const uint8_t start_gap = 30; | ||||
|     constexpr static const uint8_t write_gap = 18; | ||||
|     constexpr static const uint8_t data_0 = 24; | ||||
|     constexpr static const uint8_t data_1 = 56; | ||||
|     constexpr static const uint16_t program = 700; | ||||
| @ -34,6 +35,7 @@ RfidWriter::~RfidWriter() { | ||||
| void RfidWriter::start() { | ||||
|     api_hal_rfid_tim_read(125000, 0.5); | ||||
|     api_hal_rfid_pins_read(); | ||||
|     api_hal_rfid_tim_read_start(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::stop() { | ||||
| @ -64,8 +66,6 @@ void RfidWriter::write_byte(uint8_t value) { | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data) { | ||||
|     // wait to power card
 | ||||
|     api_hal_rfid_tim_read_start(); | ||||
|     delay_us(T55xxTiming::wait_time * 8); | ||||
| 
 | ||||
|     // start gap
 | ||||
| @ -101,18 +101,42 @@ void RfidWriter::write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_ | ||||
| 
 | ||||
|     delay_us(T55xxTiming::program * 8); | ||||
| 
 | ||||
|     api_hal_rfid_tim_read_stop(); | ||||
|     delay_us(T55xxTiming::wait_time * 8); | ||||
|     write_reset(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_reset() { | ||||
|     write_gap(T55xxTiming::start_gap); | ||||
|     write_bit(1); | ||||
|     write_bit(0); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_em(uint8_t em_data[5]) { | ||||
|     ProtocolEMMarin em_card; | ||||
|     uint64_t em_encoded_data; | ||||
|     em_card.encode(em_data, 5, reinterpret_cast<uint8_t*>(&em_encoded_data), sizeof(uint64_t)); | ||||
|     uint32_t em_config_block_data = 0b01100000000101001000000001000000; | ||||
|     const uint32_t em_config_block_data = 0b01100000000101001000000001000000; | ||||
| 
 | ||||
|     __disable_irq(); | ||||
|     write_block(0, 0, false, em_config_block_data); | ||||
|     write_block(0, 1, false, em_encoded_data); | ||||
|     write_block(0, 2, false, em_encoded_data >> 32); | ||||
|     write_reset(); | ||||
|     __enable_irq(); | ||||
| } | ||||
| 
 | ||||
| void RfidWriter::write_hid(uint8_t hid_data[3]) { | ||||
|     ProtocolHID10301 hid_card; | ||||
|     uint32_t card_data[3]; | ||||
|     hid_card.encode(hid_data, 3, reinterpret_cast<uint8_t*>(&card_data), sizeof(card_data) * 3); | ||||
| 
 | ||||
|     const uint32_t hid_config_block_data = 0b00000000000100000111000001100000; | ||||
| 
 | ||||
|     __disable_irq(); | ||||
|     write_block(0, 0, false, hid_config_block_data); | ||||
|     write_block(0, 1, false, card_data[0]); | ||||
|     write_block(0, 2, false, card_data[1]); | ||||
|     write_block(0, 3, false, card_data[2]); | ||||
|     write_reset(); | ||||
|     __enable_irq(); | ||||
| } | ||||
| @ -8,10 +8,12 @@ public: | ||||
|     void start(); | ||||
|     void stop(); | ||||
|     void write_em(uint8_t em_data[5]); | ||||
|     void write_hid(uint8_t hid_data[3]); | ||||
| 
 | ||||
| private: | ||||
|     void write_gap(uint32_t gap_time); | ||||
|     void write_bit(bool value); | ||||
|     void write_byte(uint8_t value); | ||||
|     void write_block(uint8_t page, uint8_t block, bool lock_bit, uint32_t data); | ||||
|     void write_reset(); | ||||
| }; | ||||
							
								
								
									
										50
									
								
								applications/lfrfid/helpers/state-sequencer.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								applications/lfrfid/helpers/state-sequencer.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,50 @@ | ||||
| #include "state-sequencer.h" | ||||
| #include "stdio.h" | ||||
| 
 | ||||
| TickSequencer::TickSequencer() { | ||||
| } | ||||
| 
 | ||||
| TickSequencer::~TickSequencer() { | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::tick() { | ||||
|     if(tick_count == list_it->first) { | ||||
|         tick_count = 0; | ||||
| 
 | ||||
|         list_it++; | ||||
|         if(list_it == list.end()) { | ||||
|             list_it = list.begin(); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     list_it->second(); | ||||
|     tick_count++; | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::reset() { | ||||
|     list_it = list.begin(); | ||||
|     tick_count = 0; | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::clear() { | ||||
|     list.clear(); | ||||
|     reset(); | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::do_every_tick(uint32_t tick_count, std::function<void(void)> fn) { | ||||
|     list.push_back(std::make_pair(tick_count, fn)); | ||||
|     reset(); | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::do_after_tick(uint32_t tick_count, std::function<void(void)> fn) { | ||||
|     if(tick_count > 1) { | ||||
|         list.push_back( | ||||
|             std::make_pair(tick_count - 1, std::bind(&TickSequencer::do_nothing, this))); | ||||
|     } | ||||
|     list.push_back(std::make_pair(1, fn)); | ||||
| 
 | ||||
|     reset(); | ||||
| } | ||||
| 
 | ||||
| void TickSequencer::do_nothing() { | ||||
| } | ||||
							
								
								
									
										25
									
								
								applications/lfrfid/helpers/state-sequencer.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								applications/lfrfid/helpers/state-sequencer.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,25 @@ | ||||
| #pragma once | ||||
| #include "stdint.h" | ||||
| #include <list> | ||||
| #include <functional> | ||||
| 
 | ||||
| class TickSequencer { | ||||
| public: | ||||
|     TickSequencer(); | ||||
|     ~TickSequencer(); | ||||
| 
 | ||||
|     void tick(); | ||||
|     void reset(); | ||||
|     void clear(); | ||||
| 
 | ||||
|     void do_every_tick(uint32_t tick_count, std::function<void(void)> fn); | ||||
|     void do_after_tick(uint32_t tick_count, std::function<void(void)> fn); | ||||
| 
 | ||||
| private: | ||||
|     std::list<std::pair<uint32_t, std::function<void(void)> > > list; | ||||
|     std::list<std::pair<uint32_t, std::function<void(void)> > >::iterator list_it; | ||||
| 
 | ||||
|     uint32_t tick_count; | ||||
| 
 | ||||
|     void do_nothing(); | ||||
| }; | ||||
							
								
								
									
										10
									
								
								applications/lfrfid/lfrfid-app-launcher.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								applications/lfrfid/lfrfid-app-launcher.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,10 @@ | ||||
| #include "lfrfid-app.h" | ||||
| 
 | ||||
| // app enter function
 | ||||
| extern "C" int32_t lfrfid_app(void* p) { | ||||
|     LfRfidApp* app = new LfRfidApp(); | ||||
|     app->run(); | ||||
|     delete app; | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										37
									
								
								applications/lfrfid/lfrfid-app.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								applications/lfrfid/lfrfid-app.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,37 @@ | ||||
| #include "lfrfid-app.h" | ||||
| #include "scene/lfrfid-app-scene-start.h" | ||||
| #include "scene/lfrfid-app-scene-read.h" | ||||
| #include "scene/lfrfid-app-scene-read-success.h" | ||||
| #include "scene/lfrfid-app-scene-readed-menu.h" | ||||
| #include "scene/lfrfid-app-scene-write.h" | ||||
| #include "scene/lfrfid-app-scene-write-success.h" | ||||
| #include "scene/lfrfid-app-scene-emulate.h" | ||||
| #include "scene/lfrfid-app-scene-save-name.h" | ||||
| 
 | ||||
| LfRfidApp::LfRfidApp() | ||||
|     : scene_controller{this} | ||||
|     , fs_api{"sdcard"} | ||||
|     , sd_ex_api{"sdcard-ex"} | ||||
|     , notification{"notification"} | ||||
|     , text_store(40) { | ||||
|     api_hal_power_insomnia_enter(); | ||||
| 
 | ||||
|     // we need random
 | ||||
|     srand(DWT->CYCCNT); | ||||
| } | ||||
| 
 | ||||
| LfRfidApp::~LfRfidApp() { | ||||
|     api_hal_power_insomnia_exit(); | ||||
| } | ||||
| 
 | ||||
| void LfRfidApp::run() { | ||||
|     scene_controller.add_scene(SceneType::Start, new LfRfidAppSceneStart()); | ||||
|     scene_controller.add_scene(SceneType::Read, new LfRfidAppSceneRead()); | ||||
|     scene_controller.add_scene(SceneType::ReadSuccess, new LfRfidAppSceneReadSuccess()); | ||||
|     scene_controller.add_scene(SceneType::ReadedMenu, new LfRfidAppSceneReadedMenu()); | ||||
|     scene_controller.add_scene(SceneType::Write, new LfRfidAppSceneWrite()); | ||||
|     scene_controller.add_scene(SceneType::WriteSuccess, new LfRfidAppSceneWriteSuccess()); | ||||
|     scene_controller.add_scene(SceneType::Emulate, new LfRfidAppSceneEmulate()); | ||||
|     scene_controller.add_scene(SceneType::SaveName, new LfRfidAppSceneSaveName()); | ||||
|     scene_controller.process(100); | ||||
| } | ||||
							
								
								
									
										67
									
								
								applications/lfrfid/lfrfid-app.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								applications/lfrfid/lfrfid-app.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,67 @@ | ||||
| #pragma once | ||||
| #include <furi.h> | ||||
| #include <api-hal.h> | ||||
| 
 | ||||
| #include <generic-scene.hpp> | ||||
| #include <scene-controller.hpp> | ||||
| #include <view-controller.hpp> | ||||
| #include <record-controller.hpp> | ||||
| #include <text-store.h> | ||||
| 
 | ||||
| #include <view-modules/submenu-vm.h> | ||||
| #include <view-modules/popup-vm.h> | ||||
| #include <view-modules/dialog-ex-vm.h> | ||||
| #include <view-modules/text-input-vm.h> | ||||
| #include <view-modules/byte-input-vm.h> | ||||
| #include "view/container-vm.h" | ||||
| 
 | ||||
| #include <sd-card-api.h> | ||||
| #include <filesystem-api.h> | ||||
| #include <notification/notification-messages.h> | ||||
| 
 | ||||
| #include "helpers/rfid-worker.h" | ||||
| 
 | ||||
| class LfRfidApp { | ||||
| public: | ||||
|     enum class EventType : uint8_t { | ||||
|         GENERIC_EVENT_ENUM_VALUES, | ||||
|         Next, | ||||
|         MenuSelected, | ||||
|     }; | ||||
| 
 | ||||
|     enum class SceneType : uint8_t { | ||||
|         GENERIC_SCENE_ENUM_VALUES, | ||||
|         Read, | ||||
|         ReadSuccess, | ||||
|         ReadedMenu, | ||||
|         Write, | ||||
|         WriteSuccess, | ||||
|         Emulate, | ||||
|         SaveName, | ||||
|     }; | ||||
| 
 | ||||
|     class Event { | ||||
|     public: | ||||
|         union { | ||||
|             int32_t menu_index; | ||||
|         } payload; | ||||
| 
 | ||||
|         EventType type; | ||||
|     }; | ||||
| 
 | ||||
|     SceneController<GenericScene<LfRfidApp>, LfRfidApp> scene_controller; | ||||
|     ViewController<LfRfidApp, SubmenuVM, PopupVM, DialogExVM, TextInputVM, ByteInputVM, ContainerVM> | ||||
|         view_controller; | ||||
| 
 | ||||
|     ~LfRfidApp(); | ||||
|     LfRfidApp(); | ||||
| 
 | ||||
|     RecordController<FS_Api> fs_api; | ||||
|     RecordController<SdCard_Api> sd_ex_api; | ||||
|     RecordController<NotificationApp> notification; | ||||
| 
 | ||||
|     RfidWorker worker; | ||||
| 
 | ||||
|     TextStore text_store; | ||||
|     void run(); | ||||
| }; | ||||
							
								
								
									
										36
									
								
								applications/lfrfid/scene/lfrfid-app-scene-emulate.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								applications/lfrfid/scene/lfrfid-app-scene-emulate.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,36 @@ | ||||
| #include "lfrfid-app-scene-emulate.h" | ||||
| 
 | ||||
| void LfRfidAppSceneEmulate::on_enter(LfRfidApp* app, bool need_restore) { | ||||
|     string_init(data_string); | ||||
| 
 | ||||
|     uint8_t* data = app->worker.key.get_data(); | ||||
| 
 | ||||
|     for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { | ||||
|         string_cat_printf(data_string, "%02X", data[i]); | ||||
|     } | ||||
| 
 | ||||
|     auto popup = app->view_controller.get<PopupVM>(); | ||||
| 
 | ||||
|     popup->set_header("Emulating", 90, 34, AlignCenter, AlignTop); | ||||
|     popup->set_text(string_get_cstr(data_string), 90, 48, AlignCenter, AlignTop); | ||||
|     popup->set_icon(0, 4, I_RFIDDolphinSend_98x60); | ||||
| 
 | ||||
|     app->view_controller.switch_to<PopupVM>(); | ||||
|     app->worker.start_emulate(); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidAppSceneEmulate::on_event(LfRfidApp* app, LfRfidApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfRfidApp::EventType::Tick) { | ||||
|         notification_message(app->notification, &sequence_blink_cyan_10); | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneEmulate::on_exit(LfRfidApp* app) { | ||||
|     app->view_controller.get<PopupVM>()->clean(); | ||||
|     app->worker.stop_emulate(); | ||||
|     string_clear(data_string); | ||||
| } | ||||
							
								
								
									
										12
									
								
								applications/lfrfid/scene/lfrfid-app-scene-emulate.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								applications/lfrfid/scene/lfrfid-app-scene-emulate.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| #pragma once | ||||
| #include "../lfrfid-app.h" | ||||
| 
 | ||||
| class LfRfidAppSceneEmulate : public GenericScene<LfRfidApp> { | ||||
| public: | ||||
|     void on_enter(LfRfidApp* app, bool need_restore) final; | ||||
|     bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; | ||||
|     void on_exit(LfRfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     string_t data_string; | ||||
| }; | ||||
							
								
								
									
										117
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read-success.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read-success.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,117 @@ | ||||
| #include "lfrfid-app-scene-read-success.h" | ||||
| #include "../view/elements/button-element.h" | ||||
| #include "../view/elements/icon-element.h" | ||||
| #include "../view/elements/string-element.h" | ||||
| 
 | ||||
| void LfRfidAppSceneReadSuccess::on_enter(LfRfidApp* app, bool need_restore) { | ||||
|     string_init(string[0]); | ||||
|     string_init(string[1]); | ||||
|     string_init(string[2]); | ||||
| 
 | ||||
|     auto container = app->view_controller.get<ContainerVM>(); | ||||
| 
 | ||||
|     auto button = container->add<ButtonElement>(); | ||||
|     button->set_type(ButtonElement::Type::Left, "Retry"); | ||||
|     button->set_callback(app, LfRfidAppSceneReadSuccess::back_callback); | ||||
| 
 | ||||
|     button = container->add<ButtonElement>(); | ||||
|     button->set_type(ButtonElement::Type::Right, "More"); | ||||
|     button->set_callback(app, LfRfidAppSceneReadSuccess::more_callback); | ||||
| 
 | ||||
|     auto icon = container->add<IconElement>(); | ||||
|     icon->set_icon(3, 12, I_RFIDBigChip_37x36); | ||||
| 
 | ||||
|     auto header = container->add<StringElement>(); | ||||
|     header->set_text(app->worker.key.get_type_text(), 89, 3, AlignCenter); | ||||
| 
 | ||||
|     auto line_1_text = container->add<StringElement>(); | ||||
|     auto line_2_text = container->add<StringElement>(); | ||||
|     auto line_3_text = container->add<StringElement>(); | ||||
| 
 | ||||
|     auto line_1_value = container->add<StringElement>(); | ||||
|     auto line_2_value = container->add<StringElement>(); | ||||
|     auto line_3_value = container->add<StringElement>(); | ||||
| 
 | ||||
|     uint8_t* data = app->worker.key.get_data(); | ||||
| 
 | ||||
|     switch(app->worker.key.get_type()) { | ||||
|     case LfrfidKeyType::KeyEM4100: | ||||
|         line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); | ||||
|         line_2_text->set_text("Mod:", 65, 35, AlignRight, AlignBottom, FontSecondary); | ||||
|         line_3_text->set_text("ID:", 65, 47, AlignRight, AlignBottom, FontSecondary); | ||||
| 
 | ||||
|         for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { | ||||
|             string_cat_printf(string[0], "%02X", data[i]); | ||||
|         } | ||||
| 
 | ||||
|         string_printf(string[1], "Manchester"); | ||||
|         string_printf(string[2], "%03u,%05u", data[2], (uint16_t)((data[3] << 8) | (data[4]))); | ||||
| 
 | ||||
|         line_1_value->set_text( | ||||
|             string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary); | ||||
|         line_2_value->set_text( | ||||
|             string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary); | ||||
|         line_3_value->set_text( | ||||
|             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); | ||||
|         break; | ||||
|     case LfrfidKeyType::KeyH10301: | ||||
|         line_1_text->set_text("HEX:", 65, 23, AlignRight, AlignBottom, FontSecondary); | ||||
|         line_2_text->set_text("FC:", 65, 35, AlignRight, AlignBottom, FontSecondary); | ||||
|         line_3_text->set_text("Card:", 65, 47, AlignRight, AlignBottom, FontSecondary); | ||||
| 
 | ||||
|         for(uint8_t i = 0; i < app->worker.key.get_type_data_count(); i++) { | ||||
|             string_cat_printf(string[0], "%02X", data[i]); | ||||
|         } | ||||
| 
 | ||||
|         string_printf(string[1], "%u", data[0]); | ||||
|         string_printf(string[2], "%u", (uint16_t)((data[1] << 8) | (data[2]))); | ||||
| 
 | ||||
|         line_1_value->set_text( | ||||
|             string_get_cstr(string[0]), 68, 23, AlignLeft, AlignBottom, FontSecondary); | ||||
|         line_2_value->set_text( | ||||
|             string_get_cstr(string[1]), 68, 35, AlignLeft, AlignBottom, FontSecondary); | ||||
|         line_3_value->set_text( | ||||
|             string_get_cstr(string[2]), 68, 47, AlignLeft, AlignBottom, FontSecondary); | ||||
|         break; | ||||
|     case LfrfidKeyType::KeyI40134: | ||||
|         //TODO implement when we can read Indala
 | ||||
|         break; | ||||
|     } | ||||
| 
 | ||||
|     app->view_controller.switch_to<ContainerVM>(); | ||||
| 
 | ||||
|     notification_message_block(app->notification, &sequence_set_green_255); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidAppSceneReadSuccess::on_event(LfRfidApp* app, LfRfidApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfRfidApp::EventType::Next) { | ||||
|         app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadedMenu); | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneReadSuccess::on_exit(LfRfidApp* app) { | ||||
|     notification_message_block(app->notification, &sequence_reset_green); | ||||
|     app->view_controller.get<ContainerVM>()->clean(); | ||||
|     string_clear(string[0]); | ||||
|     string_clear(string[1]); | ||||
|     string_clear(string[2]); | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneReadSuccess::back_callback(void* context) { | ||||
|     LfRfidApp* app = static_cast<LfRfidApp*>(context); | ||||
|     LfRfidApp::Event event; | ||||
|     event.type = LfRfidApp::EventType::Back; | ||||
|     app->view_controller.send_event(&event); | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneReadSuccess::more_callback(void* context) { | ||||
|     LfRfidApp* app = static_cast<LfRfidApp*>(context); | ||||
|     LfRfidApp::Event event; | ||||
|     event.type = LfRfidApp::EventType::Next; | ||||
|     app->view_controller.send_event(&event); | ||||
| } | ||||
							
								
								
									
										15
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read-success.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read-success.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| #pragma once | ||||
| #include "../lfrfid-app.h" | ||||
| 
 | ||||
| class LfRfidAppSceneReadSuccess : public GenericScene<LfRfidApp> { | ||||
| public: | ||||
|     void on_enter(LfRfidApp* app, bool need_restore) final; | ||||
|     bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; | ||||
|     void on_exit(LfRfidApp* app) final; | ||||
| 
 | ||||
| private: | ||||
|     static void back_callback(void* context); | ||||
|     static void more_callback(void* context); | ||||
| 
 | ||||
|     string_t string[3]; | ||||
| }; | ||||
							
								
								
									
										31
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,31 @@ | ||||
| #include "lfrfid-app-scene-read.h" | ||||
| 
 | ||||
| void LfRfidAppSceneRead::on_enter(LfRfidApp* app, bool need_restore) { | ||||
|     auto popup = app->view_controller.get<PopupVM>(); | ||||
| 
 | ||||
|     popup->set_header("Reading\nLF RFID", 70, 34, AlignLeft, AlignTop); | ||||
|     popup->set_icon(0, 4, I_RFIDDolphinReceive_98x60); | ||||
| 
 | ||||
|     app->view_controller.switch_to<PopupVM>(); | ||||
|     app->worker.start_read(); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidAppSceneRead::on_event(LfRfidApp* app, LfRfidApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfRfidApp::EventType::Tick) { | ||||
|         if(app->worker.read()) { | ||||
|             notification_message(app->notification, &sequence_success); | ||||
|             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::ReadSuccess); | ||||
|         } else { | ||||
|             notification_message(app->notification, &sequence_blink_red_10); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneRead::on_exit(LfRfidApp* app) { | ||||
|     app->view_controller.get<PopupVM>()->clean(); | ||||
|     app->worker.stop_read(); | ||||
| } | ||||
							
								
								
									
										9
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								applications/lfrfid/scene/lfrfid-app-scene-read.h
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,9 @@ | ||||
| #pragma once | ||||
| #include "../lfrfid-app.h" | ||||
| 
 | ||||
| class LfRfidAppSceneRead : public GenericScene<LfRfidApp> { | ||||
| public: | ||||
|     void on_enter(LfRfidApp* app, bool need_restore) final; | ||||
|     bool on_event(LfRfidApp* app, LfRfidApp::Event* event) final; | ||||
|     void on_exit(LfRfidApp* app) final; | ||||
| }; | ||||
							
								
								
									
										60
									
								
								applications/lfrfid/scene/lfrfid-app-scene-readed-menu.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								applications/lfrfid/scene/lfrfid-app-scene-readed-menu.cpp
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,60 @@ | ||||
| #include "lfrfid-app-scene-readed-menu.h" | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubmenuWrite, | ||||
|     SubmenuNameAndSave, | ||||
|     SubmenuEmulate, | ||||
| } SubmenuIndex; | ||||
| 
 | ||||
| void LfRfidAppSceneReadedMenu::on_enter(LfRfidApp* app, bool need_restore) { | ||||
|     auto submenu = app->view_controller.get<SubmenuVM>(); | ||||
| 
 | ||||
|     submenu->add_item("Write", SubmenuWrite, submenu_callback, app); | ||||
|     submenu->add_item("Name and Save", SubmenuNameAndSave, submenu_callback, app); | ||||
|     submenu->add_item("Emulate", SubmenuEmulate, submenu_callback, app); | ||||
| 
 | ||||
|     if(need_restore) { | ||||
|         submenu->set_selected_item(submenu_item_selected); | ||||
|     } | ||||
| 
 | ||||
|     app->view_controller.switch_to<SubmenuVM>(); | ||||
| } | ||||
| 
 | ||||
| bool LfRfidAppSceneReadedMenu::on_event(LfRfidApp* app, LfRfidApp::Event* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == LfRfidApp::EventType::MenuSelected) { | ||||
|         submenu_item_selected = event->payload.menu_index; | ||||
|         switch(event->payload.menu_index) { | ||||
|         case SubmenuWrite: | ||||
|             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Write); | ||||
|             break; | ||||
|         case SubmenuNameAndSave: | ||||
|             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::SaveName); | ||||
|             break; | ||||
|         case SubmenuEmulate: | ||||
|             app->scene_controller.switch_to_next_scene(LfRfidApp::SceneType::Emulate); | ||||
|             break; | ||||
|         } | ||||
|         consumed = true; | ||||
|     } else if(event->type == LfRfidApp::EventType::Back) { | ||||
|         app->scene_controller.search_and_switch_to_previous_scene({LfRfidApp::SceneType::Start}); | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|     return consumed; | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneReadedMenu::on_exit(LfRfidApp* app) { | ||||
|     app->view_controller.get<SubmenuVM>()->clean(); | ||||
| } | ||||
| 
 | ||||
| void LfRfidAppSceneReadedMenu::submenu_callback(void* context, uint32_t index) { | ||||
|     LfRfidApp* app = static_cast<LfRfidApp*>(context); | ||||
|     LfRfidApp::Event event; | ||||
| 
 | ||||
|     event.type = LfRfidApp::EventType::MenuSelected; | ||||
|     event.payload.menu_index = index; | ||||
| 
 | ||||
|     app->view_controller.send_event(&event); | ||||
| } | ||||
Some files were not shown because too many files have changed in this diff Show More
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 SG
						SG