From cfcdff8346bc1e6d3a8d472e85f6d9689125048f Mon Sep 17 00:00:00 2001 From: gornekich <44112859+gornekich@users.noreply.github.com> Date: Wed, 14 Apr 2021 17:24:33 +0300 Subject: [PATCH] [FL-1064] iButton CLI commands (#407) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * ibutton: add cli commands * ibutton/scene: add cli event send * ibutton: make separate scenes for cli commands * ibutton/scene: add timeout to cli scenes * ibutton: fix reading key data from cli * cli: add cli_delete_command to API * ibutton: delete cli command after app exit * cli: free allocated string Co-authored-by: あく --- applications/cli/cli.c | 17 ++ applications/cli/cli.h | 6 + applications/ibutton/ibutton-app.cpp | 159 ++++++++++++++++++ applications/ibutton/ibutton-app.h | 27 +++ .../scene/ibutton-scene-cli-emulate.cpp | 102 +++++++++++ .../ibutton/scene/ibutton-scene-cli-emulate.h | 13 ++ .../ibutton/scene/ibutton-scene-cli-read.cpp | 65 +++++++ .../ibutton/scene/ibutton-scene-cli-read.h | 12 ++ .../ibutton/scene/ibutton-scene-cli-write.cpp | 109 ++++++++++++ .../ibutton/scene/ibutton-scene-cli-write.h | 12 ++ 10 files changed, 522 insertions(+) create mode 100644 applications/ibutton/scene/ibutton-scene-cli-emulate.cpp create mode 100644 applications/ibutton/scene/ibutton-scene-cli-emulate.h create mode 100644 applications/ibutton/scene/ibutton-scene-cli-read.cpp create mode 100644 applications/ibutton/scene/ibutton-scene-cli-read.h create mode 100644 applications/ibutton/scene/ibutton-scene-cli-write.cpp create mode 100644 applications/ibutton/scene/ibutton-scene-cli-write.h diff --git a/applications/cli/cli.c b/applications/cli/cli.c index 77163b77..63ec6503 100644 --- a/applications/cli/cli.c +++ b/applications/cli/cli.c @@ -176,6 +176,23 @@ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* con string_clear(name_str); } +void cli_delete_command(Cli* cli, const char* name) { + string_t name_str; + string_init_set_str(name_str, name); + string_strim(name_str); + + size_t name_replace; + do { + name_replace = string_replace_str(name_str, " ", "_"); + } while(name_replace != STRING_FAILURE); + + furi_check(osMutexAcquire(cli->mutex, osWaitForever) == osOK); + CliCommandDict_erase(cli->commands, name_str); + furi_check(osMutexRelease(cli->mutex) == osOK); + + string_clear(name_str); +} + int32_t cli_task(void* p) { Cli* cli = cli_alloc(); diff --git a/applications/cli/cli.h b/applications/cli/cli.h index 514cc288..e717f43c 100644 --- a/applications/cli/cli.h +++ b/applications/cli/cli.h @@ -27,6 +27,12 @@ typedef void (*CliCallback)(string_t args, void* context); */ void cli_add_command(Cli* cli, const char* name, CliCallback callback, void* context); +/* Delete cli command + * @param cli - pointer to cli instance + * @param name - command name + */ +void cli_delete_command(Cli* cli, const char* name); + /* Read from terminal * Do it only from inside of cli call. * @param cli - Cli instance diff --git a/applications/ibutton/ibutton-app.cpp b/applications/ibutton/ibutton-app.cpp index fef1942f..5f1d8456 100644 --- a/applications/ibutton/ibutton-app.cpp +++ b/applications/ibutton/ibutton-app.cpp @@ -1,5 +1,7 @@ #include "ibutton-app.h" #include +#include +#include void iButtonApp::run(void) { iButtonEvent event; @@ -23,13 +25,167 @@ void iButtonApp::run(void) { scenes[current_scene]->on_exit(this); } +void iButtonApp::print_key_data(void) { + uint8_t* key_data = key.get_data(); + switch(key.get_key_type()) { + case iButtonKeyType::KeyDallas: + printf( + "Dallas %02X %02X %02X %02X %02X %02X %02X %02X\r\n", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + break; + case iButtonKeyType::KeyCyfral: + printf("Cyfral %02X %02X\r\n", key_data[0], key_data[1]); + break; + case iButtonKeyType::KeyMetakom: + printf( + "Metakom %02X %02X %02X %02X\r\n", key_data[0], key_data[1], key_data[2], key_data[3]); + break; + } +} + +bool iButtonApp::read_hex_byte(string_t args, uint8_t* byte) { + char* endptr; + *byte = strtoul(string_get_cstr(args), &endptr, 16); + if(*endptr == '\0') { + return false; + } + size_t ws = string_search_char(args, ' '); + if(ws != 2) { + return false; + } + string_right(args, ws); + string_strim(args); + return true; +} + +void iButtonApp::cli_cmd_callback(string_t args, void* context) { + iButtonApp::Scene scene; + string_t cmd; + string_init(cmd); + if(!string_cmp_str(args, "read")) { + scene = iButtonApp::Scene::SceneCliRead; + printf("Reading key ...\r\n"); + } else { + // Parse write / emulate commands + size_t ws = string_search_char(args, ' '); + if(ws == STRING_FAILURE) { + printf("Incorrect input. Try tm [key_type] [key_data]\r\n"); + string_clear(cmd); + return; + } else { + string_set_n(cmd, args, 0, ws); + string_right(args, ws); + string_strim(args); + } + if(!string_cmp_str(cmd, "write")) { + scene = iButtonApp::Scene::SceneCliWrite; + } else if(!string_cmp_str(cmd, "emulate")) { + scene = iButtonApp::Scene::SceneCliEmulate; + } else { + printf("Incorrect input. Try tm \r\n"); + string_clear(cmd); + return; + } + string_clear(cmd); + // Parse key type + string_t key_type; + string_init(key_type); + ws = string_search_char(args, ' '); + string_set_n(key_type, args, 0, ws); + uint8_t bytes_to_read = 0; + if(!string_cmp_str(key_type, "0")) { + key.set_type(iButtonKeyType::KeyDallas); + bytes_to_read = 8; + } else if(!string_cmp_str(key_type, "1")) { + key.set_type(iButtonKeyType::KeyCyfral); + bytes_to_read = 2; + } else if(!string_cmp_str(key_type, "2")) { + key.set_type(iButtonKeyType::KeyMetakom); + bytes_to_read = 4; + } else { + printf("Incorrect key type. Try 0 - KeyDallas, 1 - KeyCyfral, 2 - KeyMetakom"); + string_clear(key_type); + return; + } + string_clear(key_type); + // Read key data + string_right(args, 1); + string_strim(args); + uint8_t key_data[8] = {}; + uint8_t i = 0; + bool ret = true; + while((i < bytes_to_read) && ret) { + ret = read_hex_byte(args, &key_data[i++]); + } + if(i != bytes_to_read) { + printf("Incorrect key data\r\n"); + return; + } + key.set_data(key_data, bytes_to_read); + if(scene == iButtonApp::Scene::SceneCliWrite) { + printf("Writing key "); + } else { + printf("Emulating key "); + } + print_key_data(); + } + switch_to_next_scene(scene); + // Wait return event + iButtonApp::CliEvent result; + if(osMessageQueueGet(cli_event_result, &result, NULL, osWaitForever) != osOK) { + printf("Command execution error\r\n"); + return; + } + // Process return event + switch(result) { + case iButtonApp::CliEvent::CliReadSuccess: + print_key_data(); + case iButtonApp::CliEvent::CliReadCRCError: + printf("Read error: invalid CRC\r\n"); + break; + case iButtonApp::CliEvent::CliReadNotKeyError: + printf("Read error: not a key\r\n"); + break; + case iButtonApp::CliEvent::CliTimeout: + printf("Timeout error\r\n"); + break; + case iButtonApp::CliEvent::CliInterrupt: + printf("Command interrupted\r\n"); + break; + case iButtonApp::CliEvent::CliWriteSuccess: + printf("Write success\r\n"); + break; + case iButtonApp::CliEvent::CliWriteFail: + printf("Write fail\r\n"); + break; + default: + break; + } + return; +} + +void iButtonApp::cli_send_event(iButtonApp::CliEvent scene) { + osMessageQueuePut(cli_event_result, &scene, 0, osWaitForever); +} + iButtonApp::iButtonApp() { notify_init(); api_hal_power_insomnia_enter(); + cli_event_result = osMessageQueueNew(1, sizeof(iButtonApp::Scene), NULL); key_worker = new KeyWorker(&ibutton_gpio); sd_ex_api = static_cast(furi_record_open("sdcard-ex")); fs_api = static_cast(furi_record_open("sdcard")); + cli = static_cast(furi_record_open("cli")); + auto callback = cbc::obtain_connector(this, &iButtonApp::cli_cmd_callback); + cli_add_command(cli, "tm", callback, cli); // we need random srand(DWT->CYCCNT); @@ -38,6 +194,9 @@ iButtonApp::iButtonApp() { iButtonApp::~iButtonApp() { furi_record_close("sdcard-ex"); furi_record_close("sdcard"); + cli_delete_command(cli, "tm"); + furi_record_close("cli"); + osMessageQueueDelete(cli_event_result); api_hal_power_insomnia_exit(); } diff --git a/applications/ibutton/ibutton-app.h b/applications/ibutton/ibutton-app.h index 142473b9..837204c6 100644 --- a/applications/ibutton/ibutton-app.h +++ b/applications/ibutton/ibutton-app.h @@ -6,16 +6,19 @@ #include "scene/ibutton-scene-generic.h" #include "scene/ibutton-scene-start.h" #include "scene/ibutton-scene-read.h" +#include "scene/ibutton-scene-cli-read.h" #include "scene/ibutton-scene-read-crc-error.h" #include "scene/ibutton-scene-read-not-key-error.h" #include "scene/ibutton-scene-read-success.h" #include "scene/ibutton-scene-readed-key-menu.h" #include "scene/ibutton-scene-write.h" +#include "scene/ibutton-scene-cli-write.h" #include "scene/ibutton-scene-write-success.h" #include "scene/ibutton-scene-saved-key-menu.h" #include "scene/ibutton-scene-delete-confirm.h" #include "scene/ibutton-scene-delete-success.h" #include "scene/ibutton-scene-emulate.h" +#include "scene/ibutton-scene-cli-emulate.h" #include "scene/ibutton-scene-save-name.h" #include "scene/ibutton-scene-save-success.h" #include "scene/ibutton-scene-info.h" @@ -26,6 +29,7 @@ #include #include +#include "../cli/cli.h" #include "one_wire_master.h" #include "maxim_crc.h" @@ -42,13 +46,16 @@ public: SceneExit, SceneStart, SceneRead, + SceneCliRead, SceneReadNotKeyError, SceneReadCRCError, SceneReadSuccess, SceneReadedKeyMenu, SceneWrite, + SceneCliWrite, SceneWriteSuccess, SceneEmulate, + SceneCliEmulate, SceneSavedKeyMenu, SceneDeleteConfirm, SceneDeleteSuccess, @@ -59,6 +66,16 @@ public: SceneAddValue, }; + enum class CliEvent : uint8_t { + CliReadSuccess, + CliReadCRCError, + CliReadNotKeyError, + CliWriteSuccess, + CliWriteFail, + CliTimeout, + CliInterrupt, + }; + iButtonAppViewManager* get_view_manager(); void switch_to_next_scene(Scene index); void search_and_switch_to_previous_scene(std::initializer_list scenes_list); @@ -93,23 +110,30 @@ public: char* get_file_name(); uint8_t get_file_name_size(); + void cli_cmd_callback(string_t args, void* context); + void cli_send_event(CliEvent scene); + void generate_random_name(char* name, uint8_t max_name_size); private: std::list previous_scenes_list = {Scene::SceneExit}; Scene current_scene = Scene::SceneStart; iButtonAppViewManager view; + osMessageQueueId_t cli_event_result; std::map scenes = { {Scene::SceneStart, new iButtonSceneStart()}, {Scene::SceneRead, new iButtonSceneRead()}, + {Scene::SceneCliRead, new iButtonSceneCliRead()}, {Scene::SceneReadCRCError, new iButtonSceneReadCRCError()}, {Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()}, {Scene::SceneReadSuccess, new iButtonSceneReadSuccess()}, {Scene::SceneReadedKeyMenu, new iButtonSceneReadedKeyMenu()}, {Scene::SceneWrite, new iButtonSceneWrite()}, + {Scene::SceneCliWrite, new iButtonSceneCliWrite()}, {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, {Scene::SceneEmulate, new iButtonSceneEmulate()}, + {Scene::SceneCliEmulate, new iButtonSceneCliEmulate()}, {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, @@ -126,6 +150,7 @@ private: SdCard_Api* sd_ex_api; FS_Api* fs_api; + Cli* cli; static const uint8_t file_name_size = 100; char file_name[file_name_size]; @@ -133,4 +158,6 @@ private: char text_store[text_store_size + 1]; void notify_init(); + bool read_hex_byte(string_t arg, uint8_t* byte); + void print_key_data(void); }; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-emulate.cpp b/applications/ibutton/scene/ibutton-scene-cli-emulate.cpp new file mode 100644 index 00000000..43e010ec --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-emulate.cpp @@ -0,0 +1,102 @@ +#include "ibutton-scene-cli-emulate.h" +#include "../ibutton-app.h" +#include "../ibutton-view-manager.h" +#include "../ibutton-event.h" +#include "../ibutton-key.h" +#include + +void iButtonSceneCliEmulate::on_enter(iButtonApp* app) { + iButtonAppViewManager* view_manager = app->get_view_manager(); + Popup* popup = view_manager->get_popup(); + iButtonKey* key = app->get_key(); + uint8_t* key_data = key->get_data(); + const char* key_name = key->get_name(); + uint8_t line_count = 2; + timeout = 50; // 5s timeout + + // check that stored key has name + if(strcmp(key_name, "") != 0) { + app->set_text_store("emulating\n%s", key_name); + line_count = 2; + } else { + // if not, show key data + switch(key->get_key_type()) { + case iButtonKeyType::KeyDallas: + app->set_text_store( + "emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + line_count = 3; + break; + case iButtonKeyType::KeyCyfral: + app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]); + line_count = 2; + break; + case iButtonKeyType::KeyMetakom: + app->set_text_store( + "emulating\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3]); + line_count = 2; + break; + } + } + + switch(line_count) { + case 3: + popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); + popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); + break; + + default: + popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); + popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); + break; + } + + popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); + + view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); + app->get_key_worker()->start_emulate(app->get_key()); +} + +bool iButtonSceneCliEmulate::on_event(iButtonApp* app, iButtonEvent* event) { + bool consumed = false; + + if(event->type == iButtonEvent::Type::EventTypeTick) { + consumed = true; + if(!timeout--) { + app->cli_send_event(iButtonApp::CliEvent::CliTimeout); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + } else { + if(app->get_key_worker()->emulated()) { + app->notify_yellow_blink(); + } else { + app->notify_red_blink(); + } + } + } else if(event->type == iButtonEvent::Type::EventTypeBack) { + consumed = false; + app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); + } + + return consumed; +} + +void iButtonSceneCliEmulate::on_exit(iButtonApp* app) { + app->get_key_worker()->stop_emulate(); + + Popup* popup = app->get_view_manager()->get_popup(); + + 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); +} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-emulate.h b/applications/ibutton/scene/ibutton-scene-cli-emulate.h new file mode 100644 index 00000000..c6d45149 --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-emulate.h @@ -0,0 +1,13 @@ +#pragma once +#include "ibutton-scene-generic.h" +#include "../helpers/key-emulator.h" + +class iButtonSceneCliEmulate : public iButtonScene { +public: + void on_enter(iButtonApp* app) final; + bool on_event(iButtonApp* app, iButtonEvent* event) final; + void on_exit(iButtonApp* app) final; + +private: + uint16_t timeout; +}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-read.cpp b/applications/ibutton/scene/ibutton-scene-cli-read.cpp new file mode 100644 index 00000000..ac4a4432 --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-read.cpp @@ -0,0 +1,65 @@ +#include "ibutton-scene-cli-read.h" +#include "../ibutton-app.h" +#include "../ibutton-view-manager.h" +#include "../ibutton-event.h" + +void iButtonSceneCliRead::on_enter(iButtonApp* app) { + iButtonAppViewManager* view_manager = app->get_view_manager(); + Popup* popup = view_manager->get_popup(); + timeout = 50; // 5s timeout + + popup_set_header(popup, "iButton", 95, 26, AlignCenter, AlignBottom); + popup_set_text(popup, "waiting\nfor key ...", 95, 30, AlignCenter, AlignTop); + popup_set_icon(popup, 0, 5, I_DolphinWait_61x59); + + view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); + app->get_key()->set_name(""); + + app->get_key_worker()->start_read(); +} + +bool iButtonSceneCliRead::on_event(iButtonApp* app, iButtonEvent* event) { + bool consumed = false; + + if(event->type == iButtonEvent::Type::EventTypeTick) { + consumed = true; + app->notify_red_blink(); + if(!timeout--) { + app->cli_send_event(iButtonApp::CliEvent::CliTimeout); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + return consumed; + } else { + switch(app->get_key_worker()->read(app->get_key())) { + case KeyReader::Error::EMPTY: + break; + case KeyReader::Error::OK: + app->cli_send_event(iButtonApp::CliEvent::CliReadSuccess); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + break; + case KeyReader::Error::CRC_ERROR: + app->cli_send_event(iButtonApp::CliEvent::CliReadCRCError); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + break; + case KeyReader::Error::NOT_ARE_KEY: + app->cli_send_event(iButtonApp::CliEvent::CliReadNotKeyError); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + break; + } + } + } else if(event->type == iButtonEvent::Type::EventTypeBack) { + consumed = false; + app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); + } + + return consumed; +} + +void iButtonSceneCliRead::on_exit(iButtonApp* app) { + app->get_key_worker()->stop_read(); + + Popup* popup = app->get_view_manager()->get_popup(); + + 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); +} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-read.h b/applications/ibutton/scene/ibutton-scene-cli-read.h new file mode 100644 index 00000000..7590068e --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-read.h @@ -0,0 +1,12 @@ +#pragma once +#include "ibutton-scene-generic.h" + +class iButtonSceneCliRead : public iButtonScene { +public: + void on_enter(iButtonApp* app) final; + bool on_event(iButtonApp* app, iButtonEvent* event) final; + void on_exit(iButtonApp* app) final; + +private: + uint16_t timeout; +}; \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-write.cpp b/applications/ibutton/scene/ibutton-scene-cli-write.cpp new file mode 100644 index 00000000..fed3b38f --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-write.cpp @@ -0,0 +1,109 @@ +#include "ibutton-scene-cli-write.h" +#include "../ibutton-app.h" +#include "../ibutton-view-manager.h" +#include "../ibutton-event.h" +#include "../ibutton-key.h" + +void iButtonSceneCliWrite::on_enter(iButtonApp* app) { + iButtonAppViewManager* view_manager = app->get_view_manager(); + Popup* popup = view_manager->get_popup(); + iButtonKey* key = app->get_key(); + uint8_t* key_data = key->get_data(); + const char* key_name = key->get_name(); + uint8_t line_count = 2; + timeout = 50; // 5s timeout + + // check that stored key has name + if(strcmp(key_name, "") != 0) { + app->set_text_store("writing\n%s", key_name); + line_count = 2; + } else { + // if not, show key data + switch(key->get_key_type()) { + case iButtonKeyType::KeyDallas: + app->set_text_store( + "writing\n%02X %02X %02X %02X\n%02X %02X %02X %02X", + key_data[0], + key_data[1], + key_data[2], + key_data[3], + key_data[4], + key_data[5], + key_data[6], + key_data[7]); + line_count = 3; + break; + case iButtonKeyType::KeyCyfral: + app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]); + line_count = 2; + break; + case iButtonKeyType::KeyMetakom: + app->set_text_store( + "writing\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]); + line_count = 2; + break; + } + } + + switch(line_count) { + case 3: + popup_set_header(popup, "iButton", 92, 18, AlignCenter, AlignBottom); + popup_set_text(popup, app->get_text_store(), 92, 22, AlignCenter, AlignTop); + break; + + default: + popup_set_header(popup, "iButton", 92, 24, AlignCenter, AlignBottom); + popup_set_text(popup, app->get_text_store(), 92, 28, AlignCenter, AlignTop); + break; + } + + popup_set_icon(popup, 10, 10, I_iButtonKey_49x44); + + view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup); + + app->get_key_worker()->start_write(); +} + +bool iButtonSceneCliWrite::on_event(iButtonApp* app, iButtonEvent* event) { + bool consumed = false; + + if(event->type == iButtonEvent::Type::EventTypeTick) { + consumed = true; + if(!timeout--) { + app->cli_send_event(iButtonApp::CliEvent::CliTimeout); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + } else { + KeyWriter::Error result = app->get_key_worker()->write(app->get_key()); + + switch(result) { + case KeyWriter::Error::SAME_KEY: + case KeyWriter::Error::OK: + app->cli_send_event(iButtonApp::CliEvent::CliWriteSuccess); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + break; + case KeyWriter::Error::NO_DETECT: + app->notify_red_blink(); + break; + case KeyWriter::Error::CANNOT_WRITE: + app->cli_send_event(iButtonApp::CliEvent::CliWriteFail); + app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); + break; + } + } + } else if(event->type == iButtonEvent::Type::EventTypeBack) { + consumed = false; + app->cli_send_event(iButtonApp::CliEvent::CliInterrupt); + } + + return consumed; +} + +void iButtonSceneCliWrite::on_exit(iButtonApp* app) { + Popup* popup = app->get_view_manager()->get_popup(); + + 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); + + app->get_key_worker()->stop_write(); +} \ No newline at end of file diff --git a/applications/ibutton/scene/ibutton-scene-cli-write.h b/applications/ibutton/scene/ibutton-scene-cli-write.h new file mode 100644 index 00000000..6d37b7a1 --- /dev/null +++ b/applications/ibutton/scene/ibutton-scene-cli-write.h @@ -0,0 +1,12 @@ +#pragma once +#include "ibutton-scene-generic.h" + +class iButtonSceneCliWrite : public iButtonScene { +public: + void on_enter(iButtonApp* app) final; + bool on_event(iButtonApp* app, iButtonEvent* event) final; + void on_exit(iButtonApp* app) final; + +private: + uint16_t timeout; +}; \ No newline at end of file