[FL-2514] Port iButton application to C (#1198)
* Initial C iButton app setup * Add more scenes * Add even more scenes * Add even more scenes again * More scenes... * Add key info scene * Add delete success scene * Use scene state to store internal data * Add parameter parsing * Add emulate scene * Add write scene * Add write success scene * Add Read scene * Add read success scene * Add exit confirm scene * Add retry confirm scene * Add CRC error scene * Add not key scene * Add read key menu scene * Rename some scenes * Refactor conditionals * Remove unneeded custom events * Remove the old iButton app * Correct formatting * Remove rogue comments and function prototypes * iButton: cleanup merge artifacts and fix warnings Co-authored-by: Aleksandr Kutuzov <alleteam@gmail.com>
This commit is contained in:
parent
37bd0d546a
commit
5171a6ad14
349
applications/ibutton/ibutton.c
Normal file
349
applications/ibutton/ibutton.c
Normal file
@ -0,0 +1,349 @@
|
|||||||
|
#include "ibutton.h"
|
||||||
|
#include "ibutton_i.h"
|
||||||
|
#include "ibutton/scenes/ibutton_scene.h"
|
||||||
|
|
||||||
|
#include <toolbox/path.h>
|
||||||
|
#include <flipper_format/flipper_format.h>
|
||||||
|
|
||||||
|
static const NotificationSequence* ibutton_notification_sequences[] = {
|
||||||
|
&sequence_error,
|
||||||
|
&sequence_success,
|
||||||
|
&sequence_blink_cyan_10,
|
||||||
|
&sequence_blink_magenta_10,
|
||||||
|
&sequence_blink_yellow_10,
|
||||||
|
&sequence_set_red_255,
|
||||||
|
&sequence_reset_red,
|
||||||
|
&sequence_set_green_255,
|
||||||
|
&sequence_reset_green,
|
||||||
|
};
|
||||||
|
|
||||||
|
static void ibutton_make_app_folder(iButton* ibutton) {
|
||||||
|
if(!storage_simply_mkdir(ibutton->storage, IBUTTON_APP_FOLDER)) {
|
||||||
|
dialog_message_show_storage_error(ibutton->dialogs, "Cannot create\napp folder");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool ibutton_load_key_data(iButton* ibutton, string_t key_path) {
|
||||||
|
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
|
||||||
|
bool result = false;
|
||||||
|
string_t data;
|
||||||
|
string_init(data);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break;
|
||||||
|
|
||||||
|
// header
|
||||||
|
uint32_t version;
|
||||||
|
if(!flipper_format_read_header(file, data, &version)) break;
|
||||||
|
if(string_cmp_str(data, IBUTTON_APP_FILE_TYPE) != 0) break;
|
||||||
|
if(version != 1) break;
|
||||||
|
|
||||||
|
// key type
|
||||||
|
iButtonKeyType type;
|
||||||
|
if(!flipper_format_read_string(file, "Key type", data)) break;
|
||||||
|
if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break;
|
||||||
|
|
||||||
|
// key data
|
||||||
|
uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0};
|
||||||
|
if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type)))
|
||||||
|
break;
|
||||||
|
|
||||||
|
ibutton_key_set_type(ibutton->key, type);
|
||||||
|
ibutton_key_set_data(ibutton->key, key_data, IBUTTON_KEY_DATA_SIZE);
|
||||||
|
|
||||||
|
result = true;
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
flipper_format_free(file);
|
||||||
|
string_clear(data);
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
dialog_message_show_storage_error(ibutton->dialogs, "Cannot load\nkey file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_custom_event_callback(void* context, uint32_t event) {
|
||||||
|
furi_assert(context);
|
||||||
|
iButton* ibutton = context;
|
||||||
|
return scene_manager_handle_custom_event(ibutton->scene_manager, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_back_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
iButton* ibutton = context;
|
||||||
|
return scene_manager_handle_back_event(ibutton->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_tick_event_callback(void* context) {
|
||||||
|
furi_assert(context);
|
||||||
|
iButton* ibutton = context;
|
||||||
|
scene_manager_handle_tick_event(ibutton->scene_manager);
|
||||||
|
}
|
||||||
|
|
||||||
|
iButton* ibutton_alloc() {
|
||||||
|
iButton* ibutton = malloc(sizeof(iButton));
|
||||||
|
|
||||||
|
ibutton->scene_manager = scene_manager_alloc(&ibutton_scene_handlers, ibutton);
|
||||||
|
|
||||||
|
ibutton->view_dispatcher = view_dispatcher_alloc();
|
||||||
|
view_dispatcher_enable_queue(ibutton->view_dispatcher);
|
||||||
|
view_dispatcher_set_event_callback_context(ibutton->view_dispatcher, ibutton);
|
||||||
|
view_dispatcher_set_custom_event_callback(
|
||||||
|
ibutton->view_dispatcher, ibutton_custom_event_callback);
|
||||||
|
view_dispatcher_set_navigation_event_callback(
|
||||||
|
ibutton->view_dispatcher, ibutton_back_event_callback);
|
||||||
|
view_dispatcher_set_tick_event_callback(
|
||||||
|
ibutton->view_dispatcher, ibutton_tick_event_callback, 100);
|
||||||
|
|
||||||
|
ibutton->gui = furi_record_open("gui");
|
||||||
|
view_dispatcher_attach_to_gui(
|
||||||
|
ibutton->view_dispatcher, ibutton->gui, ViewDispatcherTypeFullscreen);
|
||||||
|
|
||||||
|
ibutton->storage = furi_record_open("storage");
|
||||||
|
ibutton->dialogs = furi_record_open("dialogs");
|
||||||
|
ibutton->notifications = furi_record_open("notification");
|
||||||
|
|
||||||
|
ibutton->key = ibutton_key_alloc();
|
||||||
|
ibutton->key_worker = ibutton_worker_alloc();
|
||||||
|
ibutton_worker_start_thread(ibutton->key_worker);
|
||||||
|
|
||||||
|
ibutton->submenu = submenu_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewSubmenu, submenu_get_view(ibutton->submenu));
|
||||||
|
|
||||||
|
ibutton->byte_input = byte_input_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewByteInput, byte_input_get_view(ibutton->byte_input));
|
||||||
|
|
||||||
|
ibutton->text_input = text_input_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewTextInput, text_input_get_view(ibutton->text_input));
|
||||||
|
|
||||||
|
ibutton->popup = popup_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewPopup, popup_get_view(ibutton->popup));
|
||||||
|
|
||||||
|
ibutton->widget = widget_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewWidget, widget_get_view(ibutton->widget));
|
||||||
|
|
||||||
|
ibutton->dialog_ex = dialog_ex_alloc();
|
||||||
|
view_dispatcher_add_view(
|
||||||
|
ibutton->view_dispatcher, iButtonViewDialogEx, dialog_ex_get_view(ibutton->dialog_ex));
|
||||||
|
|
||||||
|
return ibutton;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_free(iButton* ibutton) {
|
||||||
|
furi_assert(ibutton);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewDialogEx);
|
||||||
|
dialog_ex_free(ibutton->dialog_ex);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
widget_free(ibutton->widget);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
popup_free(ibutton->popup);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewTextInput);
|
||||||
|
text_input_free(ibutton->text_input);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewByteInput);
|
||||||
|
byte_input_free(ibutton->byte_input);
|
||||||
|
|
||||||
|
view_dispatcher_remove_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
submenu_free(ibutton->submenu);
|
||||||
|
|
||||||
|
view_dispatcher_free(ibutton->view_dispatcher);
|
||||||
|
scene_manager_free(ibutton->scene_manager);
|
||||||
|
|
||||||
|
furi_record_close("storage");
|
||||||
|
ibutton->storage = NULL;
|
||||||
|
|
||||||
|
furi_record_close("notification");
|
||||||
|
ibutton->notifications = NULL;
|
||||||
|
|
||||||
|
furi_record_close("dialogs");
|
||||||
|
ibutton->dialogs = NULL;
|
||||||
|
|
||||||
|
furi_record_close("gui");
|
||||||
|
ibutton->gui = NULL;
|
||||||
|
|
||||||
|
ibutton_worker_stop_thread(ibutton->key_worker);
|
||||||
|
ibutton_worker_free(ibutton->key_worker);
|
||||||
|
ibutton_key_free(ibutton->key);
|
||||||
|
|
||||||
|
free(ibutton);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_file_select(iButton* ibutton) {
|
||||||
|
bool success = dialog_file_select_show(
|
||||||
|
ibutton->dialogs,
|
||||||
|
IBUTTON_APP_FOLDER,
|
||||||
|
IBUTTON_APP_EXTENSION,
|
||||||
|
ibutton->file_name,
|
||||||
|
IBUTTON_FILE_NAME_SIZE,
|
||||||
|
ibutton_key_get_name_p(ibutton->key));
|
||||||
|
|
||||||
|
if(success) {
|
||||||
|
string_t key_str;
|
||||||
|
string_init_printf(
|
||||||
|
key_str, "%s/%s%s", IBUTTON_APP_FOLDER, ibutton->file_name, IBUTTON_APP_EXTENSION);
|
||||||
|
success = ibutton_load_key_data(ibutton, key_str);
|
||||||
|
|
||||||
|
if(success) {
|
||||||
|
ibutton_key_set_name(ibutton->key, ibutton->file_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(key_str);
|
||||||
|
}
|
||||||
|
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_load_key(iButton* ibutton, const char* key_name) {
|
||||||
|
string_t key_path;
|
||||||
|
string_init_set_str(key_path, key_name);
|
||||||
|
|
||||||
|
const bool success = ibutton_load_key_data(ibutton, key_path);
|
||||||
|
|
||||||
|
if(success) {
|
||||||
|
path_extract_filename_no_ext(key_name, key_path);
|
||||||
|
ibutton_key_set_name(ibutton->key, string_get_cstr(key_path));
|
||||||
|
}
|
||||||
|
|
||||||
|
string_clear(key_path);
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_save_key(iButton* ibutton, const char* key_name) {
|
||||||
|
// Create ibutton directory if necessary
|
||||||
|
ibutton_make_app_folder(ibutton);
|
||||||
|
|
||||||
|
FlipperFormat* file = flipper_format_file_alloc(ibutton->storage);
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
|
||||||
|
string_t key_file_name;
|
||||||
|
bool result = false;
|
||||||
|
string_init(key_file_name);
|
||||||
|
|
||||||
|
do {
|
||||||
|
// First remove key if it was saved (we rename the key)
|
||||||
|
if(!ibutton_delete_key(ibutton)) break;
|
||||||
|
|
||||||
|
// Save the key
|
||||||
|
ibutton_key_set_name(key, key_name);
|
||||||
|
|
||||||
|
// Set full file name, for new key
|
||||||
|
string_printf(
|
||||||
|
key_file_name,
|
||||||
|
"%s/%s%s",
|
||||||
|
IBUTTON_APP_FOLDER,
|
||||||
|
ibutton_key_get_name_p(key),
|
||||||
|
IBUTTON_APP_EXTENSION);
|
||||||
|
|
||||||
|
// Open file for write
|
||||||
|
if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break;
|
||||||
|
|
||||||
|
// Write header
|
||||||
|
if(!flipper_format_write_header_cstr(file, IBUTTON_APP_FILE_TYPE, 1)) break;
|
||||||
|
|
||||||
|
// Write key type
|
||||||
|
if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom"))
|
||||||
|
break;
|
||||||
|
const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key));
|
||||||
|
if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break;
|
||||||
|
|
||||||
|
// Write data
|
||||||
|
if(!flipper_format_write_comment_cstr(
|
||||||
|
file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8"))
|
||||||
|
break;
|
||||||
|
|
||||||
|
if(!flipper_format_write_hex(
|
||||||
|
file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)))
|
||||||
|
break;
|
||||||
|
result = true;
|
||||||
|
|
||||||
|
} while(false);
|
||||||
|
|
||||||
|
flipper_format_free(file);
|
||||||
|
|
||||||
|
string_clear(key_file_name);
|
||||||
|
|
||||||
|
if(!result) {
|
||||||
|
dialog_message_show_storage_error(ibutton->dialogs, "Cannot save\nkey file");
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_delete_key(iButton* ibutton) {
|
||||||
|
string_t file_name;
|
||||||
|
bool result = false;
|
||||||
|
|
||||||
|
string_init_printf(
|
||||||
|
file_name,
|
||||||
|
"%s/%s%s",
|
||||||
|
IBUTTON_APP_FOLDER,
|
||||||
|
ibutton_key_get_name_p(ibutton->key),
|
||||||
|
IBUTTON_APP_EXTENSION);
|
||||||
|
result = storage_simply_remove(ibutton->storage, string_get_cstr(file_name));
|
||||||
|
string_clear(file_name);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_text_store_set(iButton* ibutton, const char* text, ...) {
|
||||||
|
va_list args;
|
||||||
|
va_start(args, text);
|
||||||
|
|
||||||
|
vsnprintf(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE, text, args);
|
||||||
|
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_text_store_clear(iButton* ibutton) {
|
||||||
|
memset(ibutton->text_store, 0, IBUTTON_TEXT_STORE_SIZE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_switch_to_previous_scene_one_of(
|
||||||
|
iButton* ibutton,
|
||||||
|
const uint32_t* scene_ids,
|
||||||
|
size_t scene_ids_size) {
|
||||||
|
furi_assert(scene_ids_size);
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
|
||||||
|
for(size_t i = 0; i < scene_ids_size; ++i) {
|
||||||
|
const uint32_t scene_id = scene_ids[i];
|
||||||
|
if(scene_manager_has_previous_scene(scene_manager, scene_id)) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(scene_manager, scene_id);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_notification_message(iButton* ibutton, uint32_t message) {
|
||||||
|
furi_assert(message < sizeof(ibutton_notification_sequences) / sizeof(NotificationSequence*));
|
||||||
|
notification_message(ibutton->notifications, ibutton_notification_sequences[message]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ibutton_app(void* p) {
|
||||||
|
iButton* ibutton = ibutton_alloc();
|
||||||
|
|
||||||
|
ibutton_make_app_folder(ibutton);
|
||||||
|
|
||||||
|
if(p && ibutton_load_key(ibutton, (const char*)p)) {
|
||||||
|
// TODO: Display an error if the key from p could not be loaded
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||||
|
} else {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneStart);
|
||||||
|
}
|
||||||
|
|
||||||
|
view_dispatcher_run(ibutton->view_dispatcher);
|
||||||
|
|
||||||
|
ibutton_free(ibutton);
|
||||||
|
return 0;
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
#include "ibutton_app.h"
|
|
||||||
|
|
||||||
// app enter function
|
|
||||||
extern "C" int32_t ibutton_app(void* p) {
|
|
||||||
iButtonApp* app = new iButtonApp();
|
|
||||||
app->run(p);
|
|
||||||
delete app;
|
|
||||||
|
|
||||||
return 255;
|
|
||||||
}
|
|
3
applications/ibutton/ibutton.h
Normal file
3
applications/ibutton/ibutton.h
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef struct iButton iButton;
|
@ -1,342 +0,0 @@
|
|||||||
#include "ibutton_app.h"
|
|
||||||
#include <stdarg.h>
|
|
||||||
#include <furi_hal.h>
|
|
||||||
#include <m-string.h>
|
|
||||||
#include <toolbox/path.h>
|
|
||||||
#include <flipper_format/flipper_format.h>
|
|
||||||
|
|
||||||
const char* iButtonApp::app_folder = "/any/ibutton";
|
|
||||||
const char* iButtonApp::app_extension = ".ibtn";
|
|
||||||
const char* iButtonApp::app_filetype = "Flipper iButton key";
|
|
||||||
|
|
||||||
void iButtonApp::run(void* args) {
|
|
||||||
iButtonEvent event;
|
|
||||||
bool consumed;
|
|
||||||
bool exit = false;
|
|
||||||
|
|
||||||
make_app_folder();
|
|
||||||
|
|
||||||
if(args && load_key((const char*)args)) {
|
|
||||||
current_scene = Scene::SceneEmulate;
|
|
||||||
}
|
|
||||||
|
|
||||||
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 == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
exit = switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
scenes[current_scene]->on_exit(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonApp::iButtonApp()
|
|
||||||
: notification{"notification"}
|
|
||||||
, storage{"storage"}
|
|
||||||
, dialogs{"dialogs"} {
|
|
||||||
key = ibutton_key_alloc();
|
|
||||||
key_worker = ibutton_worker_alloc();
|
|
||||||
ibutton_worker_start_thread(key_worker);
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonApp::~iButtonApp() {
|
|
||||||
for(std::map<Scene, iButtonScene*>::iterator it = scenes.begin(); it != scenes.end(); ++it) {
|
|
||||||
delete it->second;
|
|
||||||
}
|
|
||||||
scenes.clear();
|
|
||||||
|
|
||||||
ibutton_worker_stop_thread(key_worker);
|
|
||||||
ibutton_worker_free(key_worker);
|
|
||||||
ibutton_key_free(key);
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonAppViewManager* iButtonApp::get_view_manager() {
|
|
||||||
return &view;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::switch_to_next_scene(Scene next_scene) {
|
|
||||||
previous_scenes_list.push_front(current_scene);
|
|
||||||
|
|
||||||
if(next_scene != Scene::SceneExit) {
|
|
||||||
scenes[current_scene]->on_exit(this);
|
|
||||||
current_scene = next_scene;
|
|
||||||
scenes[current_scene]->on_enter(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::search_and_switch_to_previous_scene(std::initializer_list<Scene> scenes_list) {
|
|
||||||
Scene previous_scene = Scene::SceneStart;
|
|
||||||
bool scene_found = false;
|
|
||||||
|
|
||||||
while(!scene_found) {
|
|
||||||
previous_scene = get_previous_scene();
|
|
||||||
for(Scene element : scenes_list) {
|
|
||||||
if(previous_scene == element || previous_scene == Scene::SceneStart) {
|
|
||||||
scene_found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
scenes[current_scene]->on_exit(this);
|
|
||||||
current_scene = previous_scene;
|
|
||||||
scenes[current_scene]->on_enter(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonApp::switch_to_previous_scene(uint8_t count) {
|
|
||||||
Scene previous_scene = Scene::SceneStart;
|
|
||||||
|
|
||||||
for(uint8_t i = 0; i < count; i++) {
|
|
||||||
previous_scene = get_previous_scene();
|
|
||||||
if(previous_scene == Scene::SceneExit) break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(previous_scene == Scene::SceneExit) {
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
scenes[current_scene]->on_exit(this);
|
|
||||||
current_scene = previous_scene;
|
|
||||||
scenes[current_scene]->on_enter(this);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonApp::Scene iButtonApp::get_previous_scene() {
|
|
||||||
Scene scene = previous_scenes_list.front();
|
|
||||||
previous_scenes_list.pop_front();
|
|
||||||
return scene;
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonWorker* iButtonApp::get_key_worker() {
|
|
||||||
return key_worker;
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonKey* iButtonApp::get_key() {
|
|
||||||
return key;
|
|
||||||
}
|
|
||||||
|
|
||||||
char* iButtonApp::get_file_name() {
|
|
||||||
return file_name;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t iButtonApp::get_file_name_size() {
|
|
||||||
return file_name_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_read() {
|
|
||||||
notification_message(notification, &sequence_blink_cyan_10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_emulate() {
|
|
||||||
notification_message(notification, &sequence_blink_magenta_10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_yellow_blink() {
|
|
||||||
notification_message(notification, &sequence_blink_yellow_10);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_error() {
|
|
||||||
notification_message(notification, &sequence_error);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_success() {
|
|
||||||
notification_message(notification, &sequence_success);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_green_on() {
|
|
||||||
notification_message_block(notification, &sequence_set_green_255);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_green_off() {
|
|
||||||
notification_message(notification, &sequence_reset_green);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_red_on() {
|
|
||||||
notification_message_block(notification, &sequence_set_red_255);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::notify_red_off() {
|
|
||||||
notification_message(notification, &sequence_reset_red);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::set_text_store(const char* text...) {
|
|
||||||
va_list args;
|
|
||||||
va_start(args, text);
|
|
||||||
|
|
||||||
vsnprintf(text_store, text_store_size, text, args);
|
|
||||||
|
|
||||||
va_end(args);
|
|
||||||
}
|
|
||||||
|
|
||||||
char* iButtonApp::get_text_store() {
|
|
||||||
return text_store;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t iButtonApp::get_text_store_size() {
|
|
||||||
return text_store_size;
|
|
||||||
}
|
|
||||||
|
|
||||||
// file managment
|
|
||||||
bool iButtonApp::save_key(const char* key_name) {
|
|
||||||
// Create ibutton directory if necessary
|
|
||||||
make_app_folder();
|
|
||||||
|
|
||||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
|
||||||
string_t key_file_name;
|
|
||||||
bool result = false;
|
|
||||||
string_init(key_file_name);
|
|
||||||
|
|
||||||
do {
|
|
||||||
// First remove key if it was saved (we rename the key)
|
|
||||||
if(!delete_key()) break;
|
|
||||||
|
|
||||||
// Save the key
|
|
||||||
ibutton_key_set_name(key, key_name);
|
|
||||||
|
|
||||||
// Set full file name, for new key
|
|
||||||
string_printf(
|
|
||||||
key_file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension);
|
|
||||||
|
|
||||||
// Open file for write
|
|
||||||
if(!flipper_format_file_open_always(file, string_get_cstr(key_file_name))) break;
|
|
||||||
|
|
||||||
// Write header
|
|
||||||
if(!flipper_format_write_header_cstr(file, iButtonApp::app_filetype, 1)) break;
|
|
||||||
|
|
||||||
// Write key type
|
|
||||||
if(!flipper_format_write_comment_cstr(file, "Key type can be Cyfral, Dallas or Metakom"))
|
|
||||||
break;
|
|
||||||
const char* key_type = ibutton_key_get_string_by_type(ibutton_key_get_type(key));
|
|
||||||
if(!flipper_format_write_string_cstr(file, "Key type", key_type)) break;
|
|
||||||
|
|
||||||
// Write data
|
|
||||||
if(!flipper_format_write_comment_cstr(
|
|
||||||
file, "Data size for Cyfral is 2, for Metakom is 4, for Dallas is 8"))
|
|
||||||
break;
|
|
||||||
|
|
||||||
if(!flipper_format_write_hex(
|
|
||||||
file, "Data", ibutton_key_get_data_p(key), ibutton_key_get_data_size(key)))
|
|
||||||
break;
|
|
||||||
result = true;
|
|
||||||
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
flipper_format_free(file);
|
|
||||||
|
|
||||||
string_clear(key_file_name);
|
|
||||||
|
|
||||||
if(!result) {
|
|
||||||
dialog_message_show_storage_error(dialogs, "Cannot save\nkey file");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonApp::load_key_data(string_t key_path) {
|
|
||||||
FlipperFormat* file = flipper_format_file_alloc(storage);
|
|
||||||
bool result = false;
|
|
||||||
string_t data;
|
|
||||||
string_init(data);
|
|
||||||
|
|
||||||
do {
|
|
||||||
if(!flipper_format_file_open_existing(file, string_get_cstr(key_path))) break;
|
|
||||||
|
|
||||||
// header
|
|
||||||
uint32_t version;
|
|
||||||
if(!flipper_format_read_header(file, data, &version)) break;
|
|
||||||
if(string_cmp_str(data, iButtonApp::app_filetype) != 0) break;
|
|
||||||
if(version != 1) break;
|
|
||||||
|
|
||||||
// key type
|
|
||||||
iButtonKeyType type;
|
|
||||||
if(!flipper_format_read_string(file, "Key type", data)) break;
|
|
||||||
if(!ibutton_key_get_type_by_string(string_get_cstr(data), &type)) break;
|
|
||||||
|
|
||||||
// key data
|
|
||||||
uint8_t key_data[IBUTTON_KEY_DATA_SIZE] = {0};
|
|
||||||
if(!flipper_format_read_hex(file, "Data", key_data, ibutton_key_get_size_by_type(type)))
|
|
||||||
break;
|
|
||||||
|
|
||||||
ibutton_key_set_type(key, type);
|
|
||||||
ibutton_key_set_data(key, key_data, IBUTTON_KEY_DATA_SIZE);
|
|
||||||
|
|
||||||
result = true;
|
|
||||||
} while(false);
|
|
||||||
|
|
||||||
flipper_format_free(file);
|
|
||||||
string_clear(data);
|
|
||||||
|
|
||||||
if(!result) {
|
|
||||||
dialog_message_show_storage_error(dialogs, "Cannot load\nkey file");
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonApp::load_key(const char* key_name) {
|
|
||||||
bool result = false;
|
|
||||||
string_t key_path;
|
|
||||||
|
|
||||||
string_init_set_str(key_path, key_name);
|
|
||||||
|
|
||||||
result = load_key_data(key_path);
|
|
||||||
if(result) {
|
|
||||||
path_extract_filename_no_ext(key_name, key_path);
|
|
||||||
ibutton_key_set_name(key, string_get_cstr(key_path));
|
|
||||||
}
|
|
||||||
string_clear(key_path);
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonApp::load_key() {
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
// Input events and views are managed by file_select
|
|
||||||
bool res = dialog_file_select_show(
|
|
||||||
dialogs,
|
|
||||||
app_folder,
|
|
||||||
app_extension,
|
|
||||||
get_file_name(),
|
|
||||||
get_file_name_size(),
|
|
||||||
ibutton_key_get_name_p(key));
|
|
||||||
|
|
||||||
if(res) {
|
|
||||||
string_t key_str;
|
|
||||||
|
|
||||||
// Get key file path
|
|
||||||
string_init_printf(key_str, "%s/%s%s", app_folder, get_file_name(), app_extension);
|
|
||||||
|
|
||||||
result = load_key_data(key_str);
|
|
||||||
if(result) {
|
|
||||||
ibutton_key_set_name(key, get_file_name());
|
|
||||||
}
|
|
||||||
string_clear(key_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonApp::delete_key() {
|
|
||||||
string_t file_name;
|
|
||||||
bool result = false;
|
|
||||||
|
|
||||||
string_init_printf(
|
|
||||||
file_name, "%s/%s%s", app_folder, ibutton_key_get_name_p(key), app_extension);
|
|
||||||
result = storage_simply_remove(storage, string_get_cstr(file_name));
|
|
||||||
string_clear(file_name);
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::make_app_folder() {
|
|
||||||
if(!storage_simply_mkdir(storage, app_folder)) {
|
|
||||||
dialog_message_show_storage_error(dialogs, "Cannot create\napp folder");
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,144 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <map>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "ibutton_view_manager.h"
|
|
||||||
#include "scene/ibutton_scene_generic.h"
|
|
||||||
#include "scene/ibutton_scene_start.h"
|
|
||||||
#include "scene/ibutton_scene_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_retry_confirm.h"
|
|
||||||
#include "scene/ibutton_scene_exit_confirm.h"
|
|
||||||
#include "scene/ibutton_scene_read_key_menu.h"
|
|
||||||
#include "scene/ibutton_scene_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_save_name.h"
|
|
||||||
#include "scene/ibutton_scene_save_success.h"
|
|
||||||
#include "scene/ibutton_scene_info.h"
|
|
||||||
#include "scene/ibutton_scene_select_key.h"
|
|
||||||
#include "scene/ibutton_scene_add_type.h"
|
|
||||||
#include "scene/ibutton_scene_add_value.h"
|
|
||||||
#include <one_wire/ibutton/ibutton_worker.h>
|
|
||||||
#include <notification/notification_messages.h>
|
|
||||||
#include <storage/storage.h>
|
|
||||||
#include <dialogs/dialogs.h>
|
|
||||||
#include <record_controller.hpp>
|
|
||||||
|
|
||||||
class iButtonApp {
|
|
||||||
public:
|
|
||||||
void run(void* args);
|
|
||||||
|
|
||||||
iButtonApp();
|
|
||||||
~iButtonApp();
|
|
||||||
|
|
||||||
enum class Scene : uint8_t {
|
|
||||||
SceneExit,
|
|
||||||
SceneStart,
|
|
||||||
SceneRead,
|
|
||||||
SceneReadNotKeyError,
|
|
||||||
SceneReadCRCError,
|
|
||||||
SceneReadSuccess,
|
|
||||||
SceneRetryConfirm,
|
|
||||||
SceneExitConfirm,
|
|
||||||
SceneReadKeyMenu,
|
|
||||||
SceneWrite,
|
|
||||||
SceneWriteSuccess,
|
|
||||||
SceneEmulate,
|
|
||||||
SceneSavedKeyMenu,
|
|
||||||
SceneDeleteConfirm,
|
|
||||||
SceneDeleteSuccess,
|
|
||||||
SceneSaveName,
|
|
||||||
SceneSaveSuccess,
|
|
||||||
SceneInfo,
|
|
||||||
SceneSelectKey,
|
|
||||||
SceneAddType,
|
|
||||||
SceneAddValue,
|
|
||||||
};
|
|
||||||
|
|
||||||
static const char* app_folder;
|
|
||||||
static const char* app_extension;
|
|
||||||
static const char* app_filetype;
|
|
||||||
|
|
||||||
iButtonAppViewManager* 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();
|
|
||||||
|
|
||||||
const GpioPin* get_ibutton_pin();
|
|
||||||
iButtonWorker* get_key_worker();
|
|
||||||
iButtonKey* get_key();
|
|
||||||
|
|
||||||
void notify_read();
|
|
||||||
void notify_yellow_blink();
|
|
||||||
void notify_emulate();
|
|
||||||
|
|
||||||
void notify_error();
|
|
||||||
void notify_success();
|
|
||||||
void notify_green_on();
|
|
||||||
void notify_green_off();
|
|
||||||
void notify_red_on();
|
|
||||||
void notify_red_off();
|
|
||||||
|
|
||||||
void set_text_store(const char* text...);
|
|
||||||
char* get_text_store();
|
|
||||||
uint8_t get_text_store_size();
|
|
||||||
|
|
||||||
char* get_file_name();
|
|
||||||
uint8_t get_file_name_size();
|
|
||||||
|
|
||||||
bool save_key(const char* key_name);
|
|
||||||
bool load_key();
|
|
||||||
bool load_key(const char* key_name);
|
|
||||||
bool delete_key();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::list<Scene> previous_scenes_list = {Scene::SceneExit};
|
|
||||||
Scene current_scene = Scene::SceneStart;
|
|
||||||
iButtonAppViewManager view;
|
|
||||||
|
|
||||||
std::map<Scene, iButtonScene*> scenes = {
|
|
||||||
{Scene::SceneStart, new iButtonSceneStart()},
|
|
||||||
{Scene::SceneRead, new iButtonSceneRead()},
|
|
||||||
{Scene::SceneReadCRCError, new iButtonSceneReadCRCError()},
|
|
||||||
{Scene::SceneReadNotKeyError, new iButtonSceneReadNotKeyError()},
|
|
||||||
{Scene::SceneReadSuccess, new iButtonSceneReadSuccess()},
|
|
||||||
{Scene::SceneRetryConfirm, new iButtonSceneRetryConfirm()},
|
|
||||||
{Scene::SceneExitConfirm, new iButtonSceneExitConfirm()},
|
|
||||||
{Scene::SceneReadKeyMenu, new iButtonSceneReadKeyMenu()},
|
|
||||||
{Scene::SceneWrite, new iButtonSceneWrite()},
|
|
||||||
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
|
|
||||||
{Scene::SceneEmulate, new iButtonSceneEmulate()},
|
|
||||||
{Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()},
|
|
||||||
{Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()},
|
|
||||||
{Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()},
|
|
||||||
{Scene::SceneSaveName, new iButtonSceneSaveName()},
|
|
||||||
{Scene::SceneSaveSuccess, new iButtonSceneSaveSuccess()},
|
|
||||||
{Scene::SceneInfo, new iButtonSceneInfo()},
|
|
||||||
{Scene::SceneSelectKey, new iButtonSceneSelectKey()},
|
|
||||||
{Scene::SceneAddType, new iButtonSceneAddType()},
|
|
||||||
{Scene::SceneAddValue, new iButtonSceneAddValue()},
|
|
||||||
};
|
|
||||||
|
|
||||||
iButtonWorker* key_worker;
|
|
||||||
iButtonKey* key;
|
|
||||||
|
|
||||||
RecordController<NotificationApp> notification;
|
|
||||||
RecordController<Storage> storage;
|
|
||||||
RecordController<DialogsApp> dialogs;
|
|
||||||
|
|
||||||
static const uint8_t file_name_size = 100;
|
|
||||||
char file_name[file_name_size];
|
|
||||||
|
|
||||||
static const uint8_t text_store_size = 128;
|
|
||||||
char text_store[text_store_size + 1];
|
|
||||||
|
|
||||||
bool load_key_data(string_t key_path);
|
|
||||||
void make_app_folder();
|
|
||||||
};
|
|
12
applications/ibutton/ibutton_custom_event.h
Normal file
12
applications/ibutton/ibutton_custom_event.h
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
enum iButtonCustomEvent {
|
||||||
|
// Reserve first 100 events for button types and indexes, starting from 0
|
||||||
|
iButtonCustomEventReserved = 100,
|
||||||
|
|
||||||
|
iButtonCustomEventBack,
|
||||||
|
iButtonCustomEventTextEditResult,
|
||||||
|
iButtonCustomEventByteEditResult,
|
||||||
|
iButtonCustomEventWorkerEmulated,
|
||||||
|
iButtonCustomEventWorkerRead,
|
||||||
|
};
|
@ -1,36 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <gui/modules/dialog_ex.h>
|
|
||||||
#include <gui/modules/widget.h>
|
|
||||||
#include <one_wire/ibutton/ibutton_worker.h>
|
|
||||||
|
|
||||||
class iButtonApp;
|
|
||||||
|
|
||||||
class iButtonEvent {
|
|
||||||
public:
|
|
||||||
// events enum
|
|
||||||
enum class Type : uint8_t {
|
|
||||||
EventTypeTick,
|
|
||||||
EventTypeBack,
|
|
||||||
EventTypeMenuSelected,
|
|
||||||
EventTypeDialogResult,
|
|
||||||
EventTypeTextEditResult,
|
|
||||||
EventTypeByteEditResult,
|
|
||||||
EventTypeWidgetButtonResult,
|
|
||||||
EventTypeWorkerEmulated,
|
|
||||||
EventTypeWorkerRead,
|
|
||||||
EventTypeWorkerWrite,
|
|
||||||
};
|
|
||||||
|
|
||||||
// payload
|
|
||||||
union {
|
|
||||||
uint32_t dummy;
|
|
||||||
uint32_t menu_index;
|
|
||||||
DialogExResult dialog_result;
|
|
||||||
GuiButtonType widget_button_result;
|
|
||||||
iButtonWorkerWriteResult worker_write_result;
|
|
||||||
} payload;
|
|
||||||
|
|
||||||
// event type
|
|
||||||
Type type;
|
|
||||||
};
|
|
86
applications/ibutton/ibutton_i.h
Normal file
86
applications/ibutton/ibutton_i.h
Normal file
@ -0,0 +1,86 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "ibutton.h"
|
||||||
|
|
||||||
|
#include <gui/gui.h>
|
||||||
|
#include <gui/view.h>
|
||||||
|
#include <gui/view_dispatcher.h>
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
#include <notification/notification_messages.h>
|
||||||
|
|
||||||
|
#include <one_wire/ibutton/ibutton_worker.h>
|
||||||
|
#include <storage/storage.h>
|
||||||
|
#include <dialogs/dialogs.h>
|
||||||
|
|
||||||
|
#include <gui/modules/submenu.h>
|
||||||
|
#include <gui/modules/popup.h>
|
||||||
|
#include <gui/modules/dialog_ex.h>
|
||||||
|
#include <gui/modules/text_input.h>
|
||||||
|
#include <gui/modules/byte_input.h>
|
||||||
|
#include <gui/modules/widget.h>
|
||||||
|
|
||||||
|
#include "ibutton_custom_event.h"
|
||||||
|
#include "scenes/ibutton_scene.h"
|
||||||
|
|
||||||
|
#define IBUTTON_FILE_NAME_SIZE 100
|
||||||
|
#define IBUTTON_TEXT_STORE_SIZE 128
|
||||||
|
|
||||||
|
#define IBUTTON_APP_FOLDER "/any/ibutton"
|
||||||
|
#define IBUTTON_APP_EXTENSION ".ibtn"
|
||||||
|
#define IBUTTON_APP_FILE_TYPE "Flipper iButton key"
|
||||||
|
|
||||||
|
struct iButton {
|
||||||
|
SceneManager* scene_manager;
|
||||||
|
ViewDispatcher* view_dispatcher;
|
||||||
|
|
||||||
|
Gui* gui;
|
||||||
|
Storage* storage;
|
||||||
|
DialogsApp* dialogs;
|
||||||
|
NotificationApp* notifications;
|
||||||
|
|
||||||
|
iButtonWorker* key_worker;
|
||||||
|
iButtonKey* key;
|
||||||
|
|
||||||
|
char file_name[IBUTTON_FILE_NAME_SIZE];
|
||||||
|
char text_store[IBUTTON_TEXT_STORE_SIZE + 1];
|
||||||
|
|
||||||
|
Submenu* submenu;
|
||||||
|
ByteInput* byte_input;
|
||||||
|
TextInput* text_input;
|
||||||
|
Popup* popup;
|
||||||
|
Widget* widget;
|
||||||
|
DialogEx* dialog_ex;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
iButtonViewSubmenu,
|
||||||
|
iButtonViewByteInput,
|
||||||
|
iButtonViewTextInput,
|
||||||
|
iButtonViewPopup,
|
||||||
|
iButtonViewWidget,
|
||||||
|
iButtonViewDialogEx,
|
||||||
|
} iButtonView;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
iButtonNotificationMessageError,
|
||||||
|
iButtonNotificationMessageSuccess,
|
||||||
|
iButtonNotificationMessageRead,
|
||||||
|
iButtonNotificationMessageEmulate,
|
||||||
|
iButtonNotificationMessageYellowBlink,
|
||||||
|
iButtonNotificationMessageRedOn,
|
||||||
|
iButtonNotificationMessageRedOff,
|
||||||
|
iButtonNotificationMessageGreenOn,
|
||||||
|
iButtonNotificationMessageGreenOff,
|
||||||
|
} iButtonNotificationMessage;
|
||||||
|
|
||||||
|
bool ibutton_file_select(iButton* ibutton);
|
||||||
|
bool ibutton_load_key(iButton* ibutton, const char* key_name);
|
||||||
|
bool ibutton_save_key(iButton* ibutton, const char* key_name);
|
||||||
|
bool ibutton_delete_key(iButton* ibutton);
|
||||||
|
void ibutton_text_store_set(iButton* ibutton, const char* text, ...);
|
||||||
|
void ibutton_text_store_clear(iButton* ibutton);
|
||||||
|
void ibutton_switch_to_previous_scene_one_of(
|
||||||
|
iButton* ibutton,
|
||||||
|
const uint32_t* scene_ids,
|
||||||
|
size_t scene_ids_size);
|
||||||
|
void ibutton_notification_message(iButton* ibutton, uint32_t message);
|
@ -1,140 +0,0 @@
|
|||||||
#include "ibutton_view_manager.h"
|
|
||||||
#include "ibutton_event.h"
|
|
||||||
#include <callback-connector.h>
|
|
||||||
|
|
||||||
iButtonAppViewManager::iButtonAppViewManager() {
|
|
||||||
event_queue = osMessageQueueNew(10, sizeof(iButtonEvent), NULL);
|
|
||||||
|
|
||||||
view_dispatcher = view_dispatcher_alloc();
|
|
||||||
auto callback = cbc::obtain_connector(this, &iButtonAppViewManager::previous_view_callback);
|
|
||||||
|
|
||||||
dialog_ex = dialog_ex_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewDialogEx),
|
|
||||||
dialog_ex_get_view(dialog_ex));
|
|
||||||
|
|
||||||
submenu = submenu_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewSubmenu),
|
|
||||||
submenu_get_view(submenu));
|
|
||||||
|
|
||||||
text_input = text_input_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewTextInput),
|
|
||||||
text_input_get_view(text_input));
|
|
||||||
|
|
||||||
byte_input = byte_input_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewByteInput),
|
|
||||||
byte_input_get_view(byte_input));
|
|
||||||
|
|
||||||
popup = popup_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewPopup),
|
|
||||||
popup_get_view(popup));
|
|
||||||
|
|
||||||
widget = widget_alloc();
|
|
||||||
view_dispatcher_add_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewWidget),
|
|
||||||
widget_get_view(widget));
|
|
||||||
|
|
||||||
gui = static_cast<Gui*>(furi_record_open("gui"));
|
|
||||||
view_dispatcher_attach_to_gui(view_dispatcher, gui, ViewDispatcherTypeFullscreen);
|
|
||||||
|
|
||||||
//TODO think about that method, seems unsafe and over-engineered
|
|
||||||
view_set_previous_callback(dialog_ex_get_view(dialog_ex), callback);
|
|
||||||
view_set_previous_callback(submenu_get_view(submenu), callback);
|
|
||||||
view_set_previous_callback(text_input_get_view(text_input), callback);
|
|
||||||
view_set_previous_callback(byte_input_get_view(byte_input), callback);
|
|
||||||
view_set_previous_callback(popup_get_view(popup), callback);
|
|
||||||
view_set_previous_callback(widget_get_view(widget), callback);
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonAppViewManager::~iButtonAppViewManager() {
|
|
||||||
// remove views
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewDialogEx));
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewSubmenu));
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewTextInput));
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher, static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewPopup));
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher,
|
|
||||||
static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewByteInput));
|
|
||||||
view_dispatcher_remove_view(
|
|
||||||
view_dispatcher, static_cast<uint32_t>(iButtonAppViewManager::Type::iButtonAppViewWidget));
|
|
||||||
|
|
||||||
// free view modules
|
|
||||||
popup_free(popup);
|
|
||||||
text_input_free(text_input);
|
|
||||||
byte_input_free(byte_input);
|
|
||||||
submenu_free(submenu);
|
|
||||||
dialog_ex_free(dialog_ex);
|
|
||||||
widget_free(widget);
|
|
||||||
|
|
||||||
// free dispatcher
|
|
||||||
view_dispatcher_free(view_dispatcher);
|
|
||||||
|
|
||||||
// free event queue
|
|
||||||
osMessageQueueDelete(event_queue);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonAppViewManager::switch_to(Type type) {
|
|
||||||
view_dispatcher_switch_to_view(view_dispatcher, static_cast<uint32_t>(type));
|
|
||||||
}
|
|
||||||
|
|
||||||
Submenu* iButtonAppViewManager::get_submenu() {
|
|
||||||
return submenu;
|
|
||||||
}
|
|
||||||
|
|
||||||
Popup* iButtonAppViewManager::get_popup() {
|
|
||||||
return popup;
|
|
||||||
}
|
|
||||||
|
|
||||||
DialogEx* iButtonAppViewManager::get_dialog_ex() {
|
|
||||||
return dialog_ex;
|
|
||||||
}
|
|
||||||
|
|
||||||
TextInput* iButtonAppViewManager::get_text_input() {
|
|
||||||
return text_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
ByteInput* iButtonAppViewManager::get_byte_input() {
|
|
||||||
return byte_input;
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget* iButtonAppViewManager::get_widget() {
|
|
||||||
return widget;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonAppViewManager::receive_event(iButtonEvent* event) {
|
|
||||||
if(osMessageQueueGet(event_queue, event, NULL, 100) != osOK) {
|
|
||||||
event->type = iButtonEvent::Type::EventTypeTick;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonAppViewManager::send_event(iButtonEvent* event) {
|
|
||||||
osStatus_t result = osMessageQueuePut(event_queue, event, 0, 0);
|
|
||||||
furi_check(result == osOK);
|
|
||||||
}
|
|
||||||
|
|
||||||
uint32_t iButtonAppViewManager::previous_view_callback(void*) {
|
|
||||||
if(event_queue != NULL) {
|
|
||||||
iButtonEvent event;
|
|
||||||
event.type = iButtonEvent::Type::EventTypeBack;
|
|
||||||
send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
return VIEW_IGNORE;
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <furi.h>
|
|
||||||
#include <gui/view_dispatcher.h>
|
|
||||||
#include <gui/modules/dialog_ex.h>
|
|
||||||
#include <gui/modules/submenu.h>
|
|
||||||
#include <gui/modules/text_input.h>
|
|
||||||
#include <gui/modules/byte_input.h>
|
|
||||||
#include <gui/modules/popup.h>
|
|
||||||
#include <gui/modules/widget.h>
|
|
||||||
#include "ibutton_event.h"
|
|
||||||
|
|
||||||
class iButtonAppViewManager {
|
|
||||||
public:
|
|
||||||
enum class Type : uint8_t {
|
|
||||||
iButtonAppViewTextInput,
|
|
||||||
iButtonAppViewByteInput,
|
|
||||||
iButtonAppViewSubmenu,
|
|
||||||
iButtonAppViewDialogEx,
|
|
||||||
iButtonAppViewPopup,
|
|
||||||
iButtonAppViewWidget,
|
|
||||||
};
|
|
||||||
|
|
||||||
osMessageQueueId_t event_queue;
|
|
||||||
|
|
||||||
iButtonAppViewManager();
|
|
||||||
~iButtonAppViewManager();
|
|
||||||
|
|
||||||
void switch_to(Type type);
|
|
||||||
|
|
||||||
Submenu* get_submenu();
|
|
||||||
Popup* get_popup();
|
|
||||||
DialogEx* get_dialog_ex();
|
|
||||||
TextInput* get_text_input();
|
|
||||||
ByteInput* get_byte_input();
|
|
||||||
Widget* get_widget();
|
|
||||||
|
|
||||||
void receive_event(iButtonEvent* event);
|
|
||||||
void send_event(iButtonEvent* event);
|
|
||||||
|
|
||||||
private:
|
|
||||||
ViewDispatcher* view_dispatcher;
|
|
||||||
DialogEx* dialog_ex;
|
|
||||||
Submenu* submenu;
|
|
||||||
TextInput* text_input;
|
|
||||||
ByteInput* byte_input;
|
|
||||||
Popup* popup;
|
|
||||||
Widget* widget;
|
|
||||||
Gui* gui;
|
|
||||||
|
|
||||||
uint32_t previous_view_callback(void* context);
|
|
||||||
};
|
|
@ -1,66 +0,0 @@
|
|||||||
#include "ibutton_scene_add_type.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <callback-connector.h>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubmenuIndexCyfral,
|
|
||||||
SubmenuIndexDallas,
|
|
||||||
SubmenuIndexMetakom,
|
|
||||||
} SubmenuIndex;
|
|
||||||
|
|
||||||
static void submenu_callback(void* context, uint32_t index) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeMenuSelected;
|
|
||||||
event.payload.menu_index = index;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneAddType::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
|
||||||
|
|
||||||
submenu_add_item(submenu, "Cyfral", SubmenuIndexCyfral, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Dallas", SubmenuIndexDallas, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Metakom", SubmenuIndexMetakom, submenu_callback, app);
|
|
||||||
submenu_set_selected_item(submenu, submenu_item_selected);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneAddType::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
|
||||||
submenu_item_selected = event->payload.menu_index;
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
|
|
||||||
switch(event->payload.menu_index) {
|
|
||||||
case SubmenuIndexCyfral:
|
|
||||||
ibutton_key_set_type(key, iButtonKeyCyfral);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexDallas:
|
|
||||||
ibutton_key_set_type(key, iButtonKeyDS1990);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexMetakom:
|
|
||||||
ibutton_key_set_type(key, iButtonKeyMetakom);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
ibutton_key_set_name(key, "");
|
|
||||||
ibutton_key_clear_data(key);
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneAddType::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
|
||||||
Submenu* submenu = view->get_submenu();
|
|
||||||
|
|
||||||
submenu_reset(submenu);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneAddType : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t submenu_item_selected = 0;
|
|
||||||
};
|
|
@ -1,53 +0,0 @@
|
|||||||
#include "ibutton_scene_add_value.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <dolphin/dolphin.h>
|
|
||||||
|
|
||||||
static void byte_input_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeByteEditResult;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneAddValue::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
ByteInput* byte_input = view_manager->get_byte_input();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
|
|
||||||
memcpy(this->new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key));
|
|
||||||
|
|
||||||
byte_input_set_result_callback(
|
|
||||||
byte_input,
|
|
||||||
byte_input_callback,
|
|
||||||
NULL,
|
|
||||||
app,
|
|
||||||
this->new_key_data,
|
|
||||||
ibutton_key_get_data_size(key));
|
|
||||||
|
|
||||||
byte_input_set_header_text(byte_input, "Enter the key");
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewByteInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneAddValue::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeByteEditResult) {
|
|
||||||
ibutton_key_set_data(app->get_key(), this->new_key_data, IBUTTON_KEY_DATA_SIZE);
|
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonAdd);
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneAddValue::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
ByteInput* byte_input = view_manager->get_byte_input();
|
|
||||||
|
|
||||||
byte_input_set_result_callback(byte_input, NULL, NULL, NULL, NULL, 0);
|
|
||||||
byte_input_set_header_text(byte_input, {0});
|
|
||||||
}
|
|
@ -1,13 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
#include <one_wire/ibutton/ibutton_key.h>
|
|
||||||
|
|
||||||
class iButtonSceneAddValue : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint8_t new_key_data[IBUTTON_KEY_DATA_SIZE] = {};
|
|
||||||
};
|
|
@ -1,86 +0,0 @@
|
|||||||
#include "ibutton_scene_delete_confirm.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void widget_callback(GuiButtonType result, InputType type, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
if(type == InputTypeShort) {
|
|
||||||
event.type = iButtonEvent::Type::EventTypeWidgetButtonResult;
|
|
||||||
event.payload.widget_button_result = result;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneDeleteConfirm::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
|
||||||
|
|
||||||
app->set_text_store("\e#Delete %s?\e#", ibutton_key_get_name_p(key));
|
|
||||||
widget_add_text_box_element(
|
|
||||||
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, app->get_text_store(), false);
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Cancel", widget_callback, app);
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeRight, "Delete", widget_callback, app);
|
|
||||||
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
|
||||||
case iButtonKeyDS1990:
|
|
||||||
app->set_text_store(
|
|
||||||
"%02X %02X %02X %02X %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]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas");
|
|
||||||
break;
|
|
||||||
case iButtonKeyCyfral:
|
|
||||||
app->set_text_store("%02X %02X", key_data[0], key_data[1]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
|
|
||||||
break;
|
|
||||||
case iButtonKeyMetakom:
|
|
||||||
app->set_text_store(
|
|
||||||
"%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, app->get_text_store());
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneDeleteConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) {
|
|
||||||
if(event->payload.widget_button_result == GuiButtonTypeRight) {
|
|
||||||
if(app->delete_key()) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneDeleteConfirm::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
|
|
||||||
app->set_text_store("");
|
|
||||||
|
|
||||||
widget_reset(widget);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneDeleteConfirm : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,47 +0,0 @@
|
|||||||
#include "ibutton_scene_delete_success.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void popup_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
event.type = iButtonEvent::Type::EventTypeBack;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneDeleteSuccess::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Popup* popup = view_manager->get_popup();
|
|
||||||
|
|
||||||
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
|
||||||
popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
|
|
||||||
|
|
||||||
popup_set_callback(popup, popup_callback);
|
|
||||||
popup_set_context(popup, app);
|
|
||||||
popup_set_timeout(popup, 1500);
|
|
||||||
popup_enable_timeout(popup);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneDeleteSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneSelectKey});
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 0, 0, NULL);
|
|
||||||
|
|
||||||
popup_disable_timeout(popup);
|
|
||||||
popup_set_context(popup, NULL);
|
|
||||||
popup_set_callback(popup, NULL);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneDeleteSuccess : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneEmulate : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
#include "ibutton_scene_exit_confirm.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void widget_callback(GuiButtonType result, InputType type, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
if(type == InputTypeShort) {
|
|
||||||
event.type = iButtonEvent::Type::EventTypeWidgetButtonResult;
|
|
||||||
event.payload.widget_button_result = result;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneExitConfirm::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", widget_callback, app);
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", widget_callback, app);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu");
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneExitConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) {
|
|
||||||
if(event->payload.widget_button_result == GuiButtonTypeLeft) {
|
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart});
|
|
||||||
} else if(event->payload.widget_button_result == GuiButtonTypeRight) {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneExitConfirm::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
widget_reset(widget);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneExitConfirm : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,14 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "../ibutton_event.h"
|
|
||||||
|
|
||||||
class iButtonApp;
|
|
||||||
|
|
||||||
class iButtonScene {
|
|
||||||
public:
|
|
||||||
virtual void on_enter(iButtonApp* app) = 0;
|
|
||||||
virtual bool on_event(iButtonApp* app, iButtonEvent* event) = 0;
|
|
||||||
virtual void on_exit(iButtonApp* app) = 0;
|
|
||||||
virtual ~iButtonScene(){};
|
|
||||||
|
|
||||||
private:
|
|
||||||
};
|
|
@ -1,58 +0,0 @@
|
|||||||
#include "ibutton_scene_info.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
void iButtonSceneInfo::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
|
||||||
|
|
||||||
app->set_text_store("%s", ibutton_key_get_name_p(key));
|
|
||||||
widget_add_text_box_element(
|
|
||||||
widget, 0, 0, 128, 28, AlignCenter, AlignCenter, app->get_text_store(), false);
|
|
||||||
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
|
||||||
case iButtonKeyDS1990:
|
|
||||||
app->set_text_store(
|
|
||||||
"%02X %02X %02X %02X %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]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas");
|
|
||||||
break;
|
|
||||||
case iButtonKeyMetakom:
|
|
||||||
app->set_text_store(
|
|
||||||
"%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom");
|
|
||||||
break;
|
|
||||||
case iButtonKeyCyfral:
|
|
||||||
app->set_text_store("%02X %02X", key_data[0], key_data[1]);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, app->get_text_store());
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneInfo::on_event(iButtonApp*, iButtonEvent*) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneInfo::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
|
|
||||||
app->set_text_store("");
|
|
||||||
|
|
||||||
widget_reset(widget);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneInfo : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,72 +0,0 @@
|
|||||||
#include "ibutton_scene_read.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <dolphin/dolphin.h>
|
|
||||||
|
|
||||||
static void read_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event = {
|
|
||||||
.payload = {.dummy = 0},
|
|
||||||
.type = iButtonEvent::Type::EventTypeWorkerRead,
|
|
||||||
};
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneRead::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Popup* popup = view_manager->get_popup();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
iButtonWorker* worker = app->get_key_worker();
|
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
|
||||||
|
|
||||||
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);
|
|
||||||
ibutton_key_set_name(key, "");
|
|
||||||
|
|
||||||
ibutton_worker_read_set_callback(worker, read_callback, app);
|
|
||||||
ibutton_worker_read_start(worker, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneRead::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWorkerRead) {
|
|
||||||
consumed = true;
|
|
||||||
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
bool success = false;
|
|
||||||
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
|
||||||
if(!ibutton_key_dallas_crc_is_valid(key)) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadCRCError);
|
|
||||||
} else if(!ibutton_key_dallas_is_1990_key(key)) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadNotKeyError);
|
|
||||||
} else {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
success = true;
|
|
||||||
}
|
|
||||||
if(success) {
|
|
||||||
app->notify_success();
|
|
||||||
app->notify_green_on();
|
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadSuccess);
|
|
||||||
}
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeTick) {
|
|
||||||
consumed = true;
|
|
||||||
app->notify_read();
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneRead::on_exit(iButtonApp* app) {
|
|
||||||
Popup* popup = app->get_view_manager()->get_popup();
|
|
||||||
ibutton_worker_stop(app->get_key_worker());
|
|
||||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
|
||||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
|
||||||
popup_set_icon(popup, 0, 0, NULL);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneRead : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,74 +0,0 @@
|
|||||||
#include "ibutton_scene_read_crc_error.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <one_wire/maxim_crc.h>
|
|
||||||
|
|
||||||
static void dialog_ex_callback(DialogExResult result, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeDialogResult;
|
|
||||||
event.payload.dialog_result = result;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadCRCError::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(app->get_key());
|
|
||||||
|
|
||||||
app->set_text_store(
|
|
||||||
"%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X",
|
|
||||||
key_data[0],
|
|
||||||
key_data[1],
|
|
||||||
key_data[2],
|
|
||||||
key_data[3],
|
|
||||||
key_data[4],
|
|
||||||
key_data[5],
|
|
||||||
key_data[6],
|
|
||||||
key_data[7],
|
|
||||||
maxim_crc8(key_data, 7, MAXIM_CRC8_INIT));
|
|
||||||
|
|
||||||
dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter);
|
|
||||||
dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
|
||||||
dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback);
|
|
||||||
dialog_ex_set_context(dialog_ex, app);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
|
|
||||||
app->notify_error();
|
|
||||||
app->notify_red_on();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneReadCRCError::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
|
||||||
} else {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadCRCError::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
|
|
||||||
app->set_text_store("");
|
|
||||||
|
|
||||||
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
|
||||||
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
|
||||||
dialog_ex_set_result_callback(dialog_ex, NULL);
|
|
||||||
dialog_ex_set_context(dialog_ex, NULL);
|
|
||||||
|
|
||||||
app->notify_red_off();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneReadCRCError : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,65 +0,0 @@
|
|||||||
#include "ibutton_scene_read_key_menu.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubmenuIndexSave,
|
|
||||||
SubmenuIndexEmulate,
|
|
||||||
SubmenuIndexWrite,
|
|
||||||
} SubmenuIndex;
|
|
||||||
|
|
||||||
static void submenu_callback(void* context, uint32_t index) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeMenuSelected;
|
|
||||||
event.payload.menu_index = index;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadKeyMenu::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
|
||||||
|
|
||||||
submenu_add_item(submenu, "Save", SubmenuIndexSave, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app);
|
|
||||||
if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) {
|
|
||||||
submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app);
|
|
||||||
}
|
|
||||||
submenu_set_selected_item(submenu, submenu_item_selected);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneReadKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
|
||||||
submenu_item_selected = event->payload.menu_index;
|
|
||||||
switch(event->payload.menu_index) {
|
|
||||||
case SubmenuIndexWrite:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneWrite);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexEmulate:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneEmulate);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexSave:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveName);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadKeyMenu::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
|
||||||
Submenu* submenu = view->get_submenu();
|
|
||||||
|
|
||||||
submenu_reset(submenu);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneReadKeyMenu : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t submenu_item_selected = 0;
|
|
||||||
};
|
|
@ -1,74 +0,0 @@
|
|||||||
#include "ibutton_scene_read_not_key_error.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <one_wire/maxim_crc.h>
|
|
||||||
|
|
||||||
static void dialog_ex_callback(DialogExResult result, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeDialogResult;
|
|
||||||
event.payload.dialog_result = result;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadNotKeyError::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(app->get_key());
|
|
||||||
|
|
||||||
app->set_text_store(
|
|
||||||
"THIS IS NOT A KEY\n%02X %02X %02X %02X %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],
|
|
||||||
maxim_crc8(key_data, 7, MAXIM_CRC8_INIT));
|
|
||||||
|
|
||||||
dialog_ex_set_header(dialog_ex, "ERROR:", 64, 10, AlignCenter, AlignCenter);
|
|
||||||
dialog_ex_set_text(dialog_ex, app->get_text_store(), 64, 19, AlignCenter, AlignTop);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
|
||||||
dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback);
|
|
||||||
dialog_ex_set_context(dialog_ex, app);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
|
|
||||||
app->notify_error();
|
|
||||||
app->notify_red_on();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneReadNotKeyError::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
|
||||||
} else {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadNotKeyError::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
|
|
||||||
app->set_text_store("");
|
|
||||||
|
|
||||||
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
|
||||||
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
|
||||||
dialog_ex_set_result_callback(dialog_ex, NULL);
|
|
||||||
dialog_ex_set_context(dialog_ex, NULL);
|
|
||||||
|
|
||||||
app->notify_red_off();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneReadNotKeyError : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,86 +0,0 @@
|
|||||||
#include "ibutton_scene_read_success.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <dolphin/dolphin.h>
|
|
||||||
|
|
||||||
static void dialog_ex_callback(DialogExResult result, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeDialogResult;
|
|
||||||
event.payload.dialog_result = result;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadSuccess::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
|
||||||
|
|
||||||
switch(ibutton_key_get_type(key)) {
|
|
||||||
case iButtonKeyDS1990:
|
|
||||||
app->set_text_store(
|
|
||||||
"Dallas\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]);
|
|
||||||
break;
|
|
||||||
case iButtonKeyCyfral:
|
|
||||||
app->set_text_store("Cyfral\n%02X %02X", key_data[0], key_data[1]);
|
|
||||||
break;
|
|
||||||
case iButtonKeyMetakom:
|
|
||||||
app->set_text_store(
|
|
||||||
"Metakom\n%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
dialog_ex_set_text(dialog_ex, app->get_text_store(), 95, 30, AlignCenter, AlignCenter);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
|
||||||
dialog_ex_set_right_button_text(dialog_ex, "More");
|
|
||||||
dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63);
|
|
||||||
dialog_ex_set_result_callback(dialog_ex, dialog_ex_callback);
|
|
||||||
dialog_ex_set_context(dialog_ex, app);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewDialogEx);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneReadSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneReadKeyMenu);
|
|
||||||
} else {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneRetryConfirm);
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneExitConfirm);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneReadSuccess::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
DialogEx* dialog_ex = view_manager->get_dialog_ex();
|
|
||||||
|
|
||||||
app->set_text_store("");
|
|
||||||
|
|
||||||
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
|
||||||
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
|
||||||
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, 0, 0, NULL);
|
|
||||||
|
|
||||||
app->notify_green_off();
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneReadSuccess : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,51 +0,0 @@
|
|||||||
#include "ibutton_scene_retry_confirm.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void widget_callback(GuiButtonType result, InputType type, void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
if(type == InputTypeShort) {
|
|
||||||
event.type = iButtonEvent::Type::EventTypeWidgetButtonResult;
|
|
||||||
event.payload.widget_button_result = result;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneRetryConfirm::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeLeft, "Exit", widget_callback, app);
|
|
||||||
widget_add_button_element(widget, GuiButtonTypeRight, "Stay", widget_callback, app);
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
|
|
||||||
widget_add_string_element(
|
|
||||||
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewWidget);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneRetryConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWidgetButtonResult) {
|
|
||||||
if(event->payload.widget_button_result == GuiButtonTypeLeft) {
|
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneRead});
|
|
||||||
} else if(event->payload.widget_button_result == GuiButtonTypeRight) {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneRetryConfirm::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Widget* widget = view_manager->get_widget();
|
|
||||||
widget_reset(widget);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneRetryConfirm : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,70 +0,0 @@
|
|||||||
#include "ibutton_scene_save_name.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <lib/toolbox/random_name.h>
|
|
||||||
|
|
||||||
static void text_input_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeTextEditResult;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSaveName::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
TextInput* text_input = view_manager->get_text_input();
|
|
||||||
|
|
||||||
const char* key_name = ibutton_key_get_name_p(app->get_key());
|
|
||||||
bool key_name_empty = !strcmp(key_name, "");
|
|
||||||
|
|
||||||
if(key_name_empty) {
|
|
||||||
set_random_name(app->get_text_store(), app->get_text_store_size());
|
|
||||||
} else {
|
|
||||||
app->set_text_store("%s", key_name);
|
|
||||||
}
|
|
||||||
|
|
||||||
text_input_set_header_text(text_input, "Name the key");
|
|
||||||
text_input_set_result_callback(
|
|
||||||
text_input,
|
|
||||||
text_input_callback,
|
|
||||||
app,
|
|
||||||
app->get_text_store(),
|
|
||||||
IBUTTON_KEY_NAME_SIZE,
|
|
||||||
key_name_empty);
|
|
||||||
|
|
||||||
ValidatorIsFile* validator_is_file =
|
|
||||||
validator_is_file_alloc_init(app->app_folder, app->app_extension, key_name);
|
|
||||||
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewTextInput);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeTextEditResult) {
|
|
||||||
if(app->save_key(app->get_text_store())) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
|
|
||||||
} else {
|
|
||||||
app->search_and_switch_to_previous_scene(
|
|
||||||
{iButtonApp::Scene::SceneReadKeyMenu,
|
|
||||||
iButtonApp::Scene::SceneSavedKeyMenu,
|
|
||||||
iButtonApp::Scene::SceneAddType});
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSaveName::on_exit(iButtonApp* app) {
|
|
||||||
TextInput* text_input = app->get_view_manager()->get_text_input();
|
|
||||||
|
|
||||||
void* validator_context = text_input_get_validator_callback_context(text_input);
|
|
||||||
text_input_set_validator(text_input, NULL, NULL);
|
|
||||||
validator_is_file_free((ValidatorIsFile*)validator_context);
|
|
||||||
|
|
||||||
text_input_reset(text_input);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneSaveName : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
#include "ibutton_scene_save_success.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <dolphin/dolphin.h>
|
|
||||||
|
|
||||||
static void popup_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
event.type = iButtonEvent::Type::EventTypeBack;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSaveSuccess::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Popup* popup = view_manager->get_popup();
|
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
|
||||||
|
|
||||||
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
|
||||||
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
|
||||||
|
|
||||||
popup_set_callback(popup, popup_callback);
|
|
||||||
popup_set_context(popup, app);
|
|
||||||
popup_set_timeout(popup, 1500);
|
|
||||||
popup_enable_timeout(popup);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneSaveSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
app->search_and_switch_to_previous_scene(
|
|
||||||
{iButtonApp::Scene::SceneReadKeyMenu,
|
|
||||||
iButtonApp::Scene::SceneSavedKeyMenu,
|
|
||||||
iButtonApp::Scene::SceneAddType});
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 0, 0, NULL);
|
|
||||||
|
|
||||||
popup_disable_timeout(popup);
|
|
||||||
popup_set_context(popup, NULL);
|
|
||||||
popup_set_callback(popup, NULL);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneSaveSuccess : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,73 +0,0 @@
|
|||||||
#include "ibutton_scene_saved_key_menu.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <callback-connector.h>
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubmenuIndexEmulate,
|
|
||||||
SubmenuIndexWrite,
|
|
||||||
SubmenuIndexEdit,
|
|
||||||
SubmenuIndexDelete,
|
|
||||||
SubmenuIndexInfo,
|
|
||||||
} SubmenuIndex;
|
|
||||||
|
|
||||||
static void submenu_callback(void* context, uint32_t index) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeMenuSelected;
|
|
||||||
event.payload.menu_index = index;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSavedKeyMenu::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
|
||||||
|
|
||||||
submenu_add_item(submenu, "Emulate", SubmenuIndexEmulate, submenu_callback, app);
|
|
||||||
if(ibutton_key_get_type(app->get_key()) == iButtonKeyDS1990) {
|
|
||||||
submenu_add_item(submenu, "Write", SubmenuIndexWrite, submenu_callback, app);
|
|
||||||
}
|
|
||||||
submenu_add_item(submenu, "Edit", SubmenuIndexEdit, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Delete", SubmenuIndexDelete, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Info", SubmenuIndexInfo, submenu_callback, app);
|
|
||||||
submenu_set_selected_item(submenu, submenu_item_selected);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneSavedKeyMenu::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
|
||||||
submenu_item_selected = event->payload.menu_index;
|
|
||||||
switch(event->payload.menu_index) {
|
|
||||||
case SubmenuIndexWrite:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneWrite);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexEmulate:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneEmulate);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexEdit:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneAddValue);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexDelete:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteConfirm);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexInfo:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneInfo);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSavedKeyMenu::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
|
||||||
Submenu* submenu = view->get_submenu();
|
|
||||||
|
|
||||||
submenu_reset(submenu);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneSavedKeyMenu : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t submenu_item_selected = 0;
|
|
||||||
};
|
|
@ -1,18 +0,0 @@
|
|||||||
#include "ibutton_scene_select_key.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
void iButtonSceneSelectKey::on_enter(iButtonApp* app) {
|
|
||||||
// Process file_select return
|
|
||||||
if(app->load_key()) {
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSavedKeyMenu);
|
|
||||||
} else {
|
|
||||||
app->switch_to_previous_scene();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneSelectKey::on_event(iButtonApp*, iButtonEvent*) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSelectKey::on_exit(iButtonApp*) {
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneSelectKey : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
@ -1,60 +0,0 @@
|
|||||||
#include "ibutton_scene_start.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
typedef enum {
|
|
||||||
SubmenuIndexRead,
|
|
||||||
SubmenuIndexSaved,
|
|
||||||
SubmenuIndexAdd,
|
|
||||||
} SubmenuIndex;
|
|
||||||
|
|
||||||
static void submenu_callback(void* context, uint32_t index) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
|
|
||||||
event.type = iButtonEvent::Type::EventTypeMenuSelected;
|
|
||||||
event.payload.menu_index = index;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneStart::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
|
||||||
|
|
||||||
submenu_add_item(submenu, "Read", SubmenuIndexRead, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Saved", SubmenuIndexSaved, submenu_callback, app);
|
|
||||||
submenu_add_item(submenu, "Add Manually", SubmenuIndexAdd, submenu_callback, app);
|
|
||||||
submenu_set_selected_item(submenu, submenu_item_selected);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneStart::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
|
||||||
submenu_item_selected = event->payload.menu_index;
|
|
||||||
switch(event->payload.menu_index) {
|
|
||||||
case SubmenuIndexRead:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneRead);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexSaved:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSelectKey);
|
|
||||||
break;
|
|
||||||
case SubmenuIndexAdd:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneAddType);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneStart::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
|
||||||
Submenu* submenu = view->get_submenu();
|
|
||||||
|
|
||||||
submenu_reset(submenu);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneStart : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
uint32_t submenu_item_selected = 0;
|
|
||||||
};
|
|
@ -1,111 +0,0 @@
|
|||||||
#include "ibutton_scene_write.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void ibutton_worker_write_cb(void* context, iButtonWorkerWriteResult result) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
event.type = iButtonEvent::Type::EventTypeWorkerWrite;
|
|
||||||
event.payload.worker_write_result = result;
|
|
||||||
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneWrite::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Popup* popup = view_manager->get_popup();
|
|
||||||
iButtonKey* key = app->get_key();
|
|
||||||
iButtonWorker* worker = app->get_key_worker();
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
|
||||||
const char* key_name = ibutton_key_get_name_p(key);
|
|
||||||
uint8_t line_count = 2;
|
|
||||||
|
|
||||||
// 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(ibutton_key_get_type(key)) {
|
|
||||||
case iButtonKeyDS1990:
|
|
||||||
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 iButtonKeyCyfral:
|
|
||||||
app->set_text_store("writing\n%02X %02X", key_data[0], key_data[1]);
|
|
||||||
line_count = 2;
|
|
||||||
break;
|
|
||||||
case iButtonKeyMetakom:
|
|
||||||
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", 82, 18, AlignCenter, AlignBottom);
|
|
||||||
popup_set_text(popup, app->get_text_store(), 82, 22, AlignCenter, AlignTop);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
|
|
||||||
popup_set_text(popup, app->get_text_store(), 82, 28, AlignCenter, AlignTop);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup);
|
|
||||||
|
|
||||||
blink_yellow = false;
|
|
||||||
ibutton_worker_write_set_callback(worker, ibutton_worker_write_cb, app);
|
|
||||||
ibutton_worker_write_start(worker, key);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneWrite::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWorkerWrite) {
|
|
||||||
consumed = true;
|
|
||||||
|
|
||||||
switch(event->payload.worker_write_result) {
|
|
||||||
case iButtonWorkerWriteOK:
|
|
||||||
case iButtonWorkerWriteSameKey:
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneWriteSuccess);
|
|
||||||
break;
|
|
||||||
case iButtonWorkerWriteNoDetect:
|
|
||||||
blink_yellow = false;
|
|
||||||
break;
|
|
||||||
case iButtonWorkerWriteCannotWrite:
|
|
||||||
blink_yellow = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeTick) {
|
|
||||||
if(blink_yellow) {
|
|
||||||
app->notify_yellow_blink();
|
|
||||||
} else {
|
|
||||||
app->notify_emulate();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneWrite::on_exit(iButtonApp* app) {
|
|
||||||
Popup* popup = app->get_view_manager()->get_popup();
|
|
||||||
ibutton_worker_stop(app->get_key_worker());
|
|
||||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
|
||||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
|
||||||
popup_set_icon(popup, 0, 0, NULL);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneWrite : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
bool blink_yellow;
|
|
||||||
};
|
|
@ -1,52 +0,0 @@
|
|||||||
#include "ibutton_scene_write_success.h"
|
|
||||||
#include "../ibutton_app.h"
|
|
||||||
|
|
||||||
static void popup_callback(void* context) {
|
|
||||||
furi_assert(context);
|
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
|
||||||
iButtonEvent event;
|
|
||||||
event.type = iButtonEvent::Type::EventTypeBack;
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
app->notify_green_off();
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneWriteSuccess::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Popup* popup = view_manager->get_popup();
|
|
||||||
|
|
||||||
popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52);
|
|
||||||
popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom);
|
|
||||||
|
|
||||||
popup_set_callback(popup, popup_callback);
|
|
||||||
popup_set_context(popup, app);
|
|
||||||
popup_set_timeout(popup, 1500);
|
|
||||||
popup_enable_timeout(popup);
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup);
|
|
||||||
|
|
||||||
app->notify_success();
|
|
||||||
app->notify_green_on();
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneWriteSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
|
||||||
app->search_and_switch_to_previous_scene(
|
|
||||||
{iButtonApp::Scene::SceneReadKeyMenu, iButtonApp::Scene::SceneStart});
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
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, 0, 0, NULL);
|
|
||||||
|
|
||||||
popup_disable_timeout(popup);
|
|
||||||
popup_set_context(popup, NULL);
|
|
||||||
popup_set_callback(popup, NULL);
|
|
||||||
}
|
|
@ -1,9 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton_scene_generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneWriteSuccess : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
};
|
|
30
applications/ibutton/scenes/ibutton_scene.c
Normal file
30
applications/ibutton/scenes/ibutton_scene.c
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#include "ibutton_scene.h"
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_enter,
|
||||||
|
void (*const ibutton_on_enter_handlers[])(void*) = {
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_event,
|
||||||
|
bool (*const ibutton_on_event_handlers[])(void* context, SceneManagerEvent event) = {
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers array
|
||||||
|
#define ADD_SCENE(prefix, name, id) prefix##_scene_##name##_on_exit,
|
||||||
|
void (*const ibutton_on_exit_handlers[])(void* context) = {
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
};
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Initialize scene handlers configuration structure
|
||||||
|
const SceneManagerHandlers ibutton_scene_handlers = {
|
||||||
|
.on_enter_handlers = ibutton_on_enter_handlers,
|
||||||
|
.on_event_handlers = ibutton_on_event_handlers,
|
||||||
|
.on_exit_handlers = ibutton_on_exit_handlers,
|
||||||
|
.scene_num = iButtonSceneNum,
|
||||||
|
};
|
29
applications/ibutton/scenes/ibutton_scene.h
Normal file
29
applications/ibutton/scenes/ibutton_scene.h
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <gui/scene_manager.h>
|
||||||
|
|
||||||
|
// Generate scene id and total number
|
||||||
|
#define ADD_SCENE(prefix, name, id) iButtonScene##id,
|
||||||
|
typedef enum {
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
iButtonSceneNum,
|
||||||
|
} iButtonScene;
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
extern const SceneManagerHandlers ibutton_scene_handlers;
|
||||||
|
|
||||||
|
// Generate scene on_enter handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_enter(void*);
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_event handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) \
|
||||||
|
bool prefix##_scene_##name##_on_event(void* context, SceneManagerEvent event);
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
||||||
|
|
||||||
|
// Generate scene on_exit handlers declaration
|
||||||
|
#define ADD_SCENE(prefix, name, id) void prefix##_scene_##name##_on_exit(void* context);
|
||||||
|
#include "ibutton_scene_config.h"
|
||||||
|
#undef ADD_SCENE
|
58
applications/ibutton/scenes/ibutton_scene_add_type.c
Normal file
58
applications/ibutton/scenes/ibutton_scene_add_type.c
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
enum SubmenuIndex {
|
||||||
|
SubmenuIndexCyfral,
|
||||||
|
SubmenuIndexDallas,
|
||||||
|
SubmenuIndexMetakom,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ibutton_scene_add_type_submenu_callback(void* context, uint32_t index) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_add_type_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Cyfral", SubmenuIndexCyfral, ibutton_scene_add_type_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Dallas", SubmenuIndexDallas, ibutton_scene_add_type_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Metakom", SubmenuIndexMetakom, ibutton_scene_add_type_submenu_callback, ibutton);
|
||||||
|
|
||||||
|
submenu_set_selected_item(submenu, SubmenuIndexCyfral);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_add_type_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == SubmenuIndexCyfral) {
|
||||||
|
ibutton_key_set_type(key, iButtonKeyCyfral);
|
||||||
|
} else if(event.event == SubmenuIndexDallas) {
|
||||||
|
ibutton_key_set_type(key, iButtonKeyDS1990);
|
||||||
|
} else if(event.event == SubmenuIndexMetakom) {
|
||||||
|
ibutton_key_set_type(key, iButtonKeyMetakom);
|
||||||
|
} else {
|
||||||
|
furi_crash("Unknown key type");
|
||||||
|
}
|
||||||
|
|
||||||
|
ibutton_key_set_name(key, "");
|
||||||
|
ibutton_key_clear_data(key);
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_add_type_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
submenu_reset(ibutton->submenu);
|
||||||
|
}
|
57
applications/ibutton/scenes/ibutton_scene_add_value.c
Normal file
57
applications/ibutton/scenes/ibutton_scene_add_value.c
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
void ibutton_scene_add_type_byte_input_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventByteEditResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_add_value_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
uint8_t* new_key_data = malloc(IBUTTON_KEY_DATA_SIZE);
|
||||||
|
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
ibutton->scene_manager, iButtonSceneAddValue, (uint32_t)new_key_data);
|
||||||
|
memcpy(new_key_data, ibutton_key_get_data_p(key), ibutton_key_get_data_size(key));
|
||||||
|
|
||||||
|
byte_input_set_result_callback(
|
||||||
|
ibutton->byte_input,
|
||||||
|
ibutton_scene_add_type_byte_input_callback,
|
||||||
|
NULL,
|
||||||
|
ibutton,
|
||||||
|
new_key_data,
|
||||||
|
ibutton_key_get_data_size(key));
|
||||||
|
|
||||||
|
byte_input_set_header_text(ibutton->byte_input, "Enter the key");
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewByteInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_add_value_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
uint8_t* new_key_data =
|
||||||
|
(uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue);
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventByteEditResult) {
|
||||||
|
ibutton_key_set_data(ibutton->key, new_key_data, IBUTTON_KEY_DATA_SIZE);
|
||||||
|
DOLPHIN_DEED(DolphinDeedIbuttonAdd);
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_add_value_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
uint8_t* new_key_data =
|
||||||
|
(uint8_t*)scene_manager_get_scene_state(ibutton->scene_manager, iButtonSceneAddValue);
|
||||||
|
|
||||||
|
byte_input_set_result_callback(ibutton->byte_input, NULL, NULL, NULL, NULL, 0);
|
||||||
|
byte_input_set_header_text(ibutton->byte_input, NULL);
|
||||||
|
free(new_key_data);
|
||||||
|
}
|
20
applications/ibutton/scenes/ibutton_scene_config.h
Normal file
20
applications/ibutton/scenes/ibutton_scene_config.h
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
ADD_SCENE(ibutton, start, Start)
|
||||||
|
ADD_SCENE(ibutton, emulate, Emulate)
|
||||||
|
ADD_SCENE(ibutton, write, Write)
|
||||||
|
ADD_SCENE(ibutton, write_success, WriteSuccess)
|
||||||
|
ADD_SCENE(ibutton, info, Info)
|
||||||
|
ADD_SCENE(ibutton, read, Read)
|
||||||
|
ADD_SCENE(ibutton, read_key_menu, ReadKeyMenu)
|
||||||
|
ADD_SCENE(ibutton, read_success, ReadSuccess)
|
||||||
|
ADD_SCENE(ibutton, read_crc_error, ReadCRCError)
|
||||||
|
ADD_SCENE(ibutton, read_not_key_error, ReadNotKeyError)
|
||||||
|
ADD_SCENE(ibutton, select_key, SelectKey)
|
||||||
|
ADD_SCENE(ibutton, add_type, AddType)
|
||||||
|
ADD_SCENE(ibutton, add_value, AddValue)
|
||||||
|
ADD_SCENE(ibutton, saved_key_menu, SavedKeyMenu)
|
||||||
|
ADD_SCENE(ibutton, save_name, SaveName)
|
||||||
|
ADD_SCENE(ibutton, save_success, SaveSuccess)
|
||||||
|
ADD_SCENE(ibutton, delete_confirm, DeleteConfirm)
|
||||||
|
ADD_SCENE(ibutton, delete_success, DeleteSuccess)
|
||||||
|
ADD_SCENE(ibutton, retry_confirm, RetryConfirm)
|
||||||
|
ADD_SCENE(ibutton, exit_confirm, ExitConfirm)
|
91
applications/ibutton/scenes/ibutton_scene_delete_confirm.c
Normal file
91
applications/ibutton/scenes/ibutton_scene_delete_confirm.c
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_delete_confirm_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_delete_confirm_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Widget* widget = ibutton->widget;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
|
||||||
|
ibutton_text_store_set(ibutton, "\e#Delete %s?\e#", ibutton_key_get_name_p(key));
|
||||||
|
widget_add_text_box_element(
|
||||||
|
widget, 0, 0, 128, 27, AlignCenter, AlignCenter, ibutton->text_store, false);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeLeft, "Cancel", ibutton_scene_delete_confirm_widget_callback, ibutton);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget,
|
||||||
|
GuiButtonTypeRight,
|
||||||
|
"Delete",
|
||||||
|
ibutton_scene_delete_confirm_widget_callback,
|
||||||
|
ibutton);
|
||||||
|
|
||||||
|
switch(ibutton_key_get_type(key)) {
|
||||||
|
case iButtonKeyDS1990:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"%02X %02X %02X %02X %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]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Dallas");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iButtonKeyCyfral:
|
||||||
|
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iButtonKeyMetakom:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 45, AlignCenter, AlignBottom, FontSecondary, "Metakom");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 33, AlignCenter, AlignBottom, FontSecondary, ibutton->text_store);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_delete_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == GuiButtonTypeRight) {
|
||||||
|
if(ibutton_delete_key(ibutton)) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneDeleteSuccess);
|
||||||
|
}
|
||||||
|
//TODO: What if the key could not be deleted?
|
||||||
|
} else if(event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_delete_confirm_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
ibutton_text_store_clear(ibutton);
|
||||||
|
widget_reset(ibutton->widget);
|
||||||
|
}
|
48
applications/ibutton/scenes/ibutton_scene_delete_success.c
Normal file
48
applications/ibutton/scenes/ibutton_scene_delete_success.c
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_delete_success_popup_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_delete_success_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
|
popup_set_icon(popup, 0, 2, &I_DolphinMafia_115x62);
|
||||||
|
popup_set_header(popup, "Deleted", 83, 19, AlignLeft, AlignBottom);
|
||||||
|
|
||||||
|
popup_set_callback(popup, ibutton_scene_delete_success_popup_callback);
|
||||||
|
popup_set_context(popup, ibutton);
|
||||||
|
popup_set_timeout(popup, 1500);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_delete_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventBack) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
ibutton->scene_manager, iButtonSceneSelectKey);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_delete_success_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
|
||||||
|
popup_disable_timeout(popup);
|
||||||
|
popup_set_context(popup, NULL);
|
||||||
|
popup_set_callback(popup, NULL);
|
||||||
|
}
|
@ -1,37 +1,35 @@
|
|||||||
#include "ibutton_scene_emulate.h"
|
#include "../ibutton_i.h"
|
||||||
#include "../ibutton_app.h"
|
|
||||||
#include <dolphin/dolphin.h>
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
static void emulate_callback(void* context, bool emulated) {
|
static void ibutton_scene_emulate_callback(void* context, bool emulated) {
|
||||||
furi_assert(context);
|
iButton* ibutton = context;
|
||||||
if(emulated) {
|
if(emulated) {
|
||||||
iButtonApp* app = static_cast<iButtonApp*>(context);
|
view_dispatcher_send_custom_event(
|
||||||
iButtonEvent event = {
|
ibutton->view_dispatcher, iButtonCustomEventWorkerEmulated);
|
||||||
.payload = {.worker_write_result = iButtonWorkerWriteOK},
|
|
||||||
.type = iButtonEvent::Type::EventTypeWorkerEmulated,
|
|
||||||
};
|
|
||||||
app->get_view_manager()->send_event(&event);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void iButtonSceneEmulate::on_enter(iButtonApp* app) {
|
void ibutton_scene_emulate_on_enter(void* context) {
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
iButton* ibutton = context;
|
||||||
Popup* popup = view_manager->get_popup();
|
Popup* popup = ibutton->popup;
|
||||||
iButtonKey* key = app->get_key();
|
iButtonKey* key = ibutton->key;
|
||||||
|
|
||||||
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
const char* key_name = ibutton_key_get_name_p(key);
|
const char* key_name = ibutton_key_get_name_p(key);
|
||||||
|
|
||||||
uint8_t line_count = 2;
|
uint8_t line_count = 2;
|
||||||
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
DOLPHIN_DEED(DolphinDeedIbuttonEmulate);
|
||||||
|
|
||||||
// check that stored key has name
|
// check that stored key has name
|
||||||
if(strcmp(key_name, "") != 0) {
|
if(strcmp(key_name, "") != 0) {
|
||||||
app->set_text_store("emulating\n%s", key_name);
|
ibutton_text_store_set(ibutton, "emulating\n%s", key_name);
|
||||||
line_count = 2;
|
line_count = 2;
|
||||||
} else {
|
} else {
|
||||||
// if not, show key data
|
// if not, show key data
|
||||||
switch(ibutton_key_get_type(key)) {
|
switch(ibutton_key_get_type(key)) {
|
||||||
case iButtonKeyDS1990:
|
case iButtonKeyDS1990:
|
||||||
app->set_text_store(
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
"emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X",
|
"emulating\n%02X %02X %02X %02X\n%02X %02X %02X %02X",
|
||||||
key_data[0],
|
key_data[0],
|
||||||
key_data[1],
|
key_data[1],
|
||||||
@ -44,11 +42,12 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) {
|
|||||||
line_count = 3;
|
line_count = 3;
|
||||||
break;
|
break;
|
||||||
case iButtonKeyCyfral:
|
case iButtonKeyCyfral:
|
||||||
app->set_text_store("emulating\n%02X %02X", key_data[0], key_data[1]);
|
ibutton_text_store_set(ibutton, "emulating\n%02X %02X", key_data[0], key_data[1]);
|
||||||
line_count = 2;
|
line_count = 2;
|
||||||
break;
|
break;
|
||||||
case iButtonKeyMetakom:
|
case iButtonKeyMetakom:
|
||||||
app->set_text_store(
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
"emulating\n%02X %02X %02X %02X",
|
"emulating\n%02X %02X %02X %02X",
|
||||||
key_data[0],
|
key_data[0],
|
||||||
key_data[1],
|
key_data[1],
|
||||||
@ -62,40 +61,45 @@ void iButtonSceneEmulate::on_enter(iButtonApp* app) {
|
|||||||
switch(line_count) {
|
switch(line_count) {
|
||||||
case 3:
|
case 3:
|
||||||
popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom);
|
popup_set_header(popup, "iButton", 82, 18, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, app->get_text_store(), 82, 22, AlignCenter, AlignTop);
|
popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
|
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, app->get_text_store(), 82, 28, AlignCenter, AlignTop);
|
popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
|
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewPopup);
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
|
||||||
ibutton_worker_emulate_set_callback(app->get_key_worker(), emulate_callback, app);
|
ibutton_worker_emulate_set_callback(
|
||||||
ibutton_worker_emulate_start(app->get_key_worker(), key);
|
ibutton->key_worker, ibutton_scene_emulate_callback, ibutton);
|
||||||
|
ibutton_worker_emulate_start(ibutton->key_worker, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool iButtonSceneEmulate::on_event(iButtonApp* app, iButtonEvent* event) {
|
bool ibutton_scene_emulate_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeWorkerEmulated) {
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
app->notify_yellow_blink();
|
|
||||||
consumed = true;
|
consumed = true;
|
||||||
} else if(event->type == iButtonEvent::Type::EventTypeTick) {
|
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulate);
|
||||||
app->notify_emulate();
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventWorkerEmulated) {
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
void iButtonSceneEmulate::on_exit(iButtonApp* app) {
|
void ibutton_scene_emulate_on_exit(void* context) {
|
||||||
Popup* popup = app->get_view_manager()->get_popup();
|
iButton* ibutton = context;
|
||||||
ibutton_worker_stop(app->get_key_worker());
|
Popup* popup = ibutton->popup;
|
||||||
|
ibutton_worker_stop(ibutton->key_worker);
|
||||||
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
popup_set_icon(popup, 0, 0, NULL);
|
popup_set_icon(popup, 0, 0, NULL);
|
51
applications/ibutton/scenes/ibutton_scene_exit_confirm.c
Normal file
51
applications/ibutton/scenes/ibutton_scene_exit_confirm.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_exit_confirm_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_exit_confirm_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Widget* widget = ibutton->widget;
|
||||||
|
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeLeft, "Exit", ibutton_scene_exit_confirm_widget_callback, ibutton);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeRight, "Stay", ibutton_scene_exit_confirm_widget_callback, ibutton);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Exit to iButton menu");
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_exit_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
consumed = true; // Ignore Back button presses
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(scene_manager, iButtonSceneStart);
|
||||||
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_exit_confirm_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
widget_reset(ibutton->widget);
|
||||||
|
}
|
61
applications/ibutton/scenes/ibutton_scene_info.c
Normal file
61
applications/ibutton/scenes/ibutton_scene_info.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
void ibutton_scene_info_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Widget* widget = ibutton->widget;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
|
||||||
|
ibutton_text_store_set(ibutton, "%s", ibutton_key_get_name_p(key));
|
||||||
|
widget_add_text_box_element(
|
||||||
|
widget, 0, 0, 128, 28, AlignCenter, AlignCenter, ibutton->text_store, false);
|
||||||
|
|
||||||
|
switch(ibutton_key_get_type(key)) {
|
||||||
|
case iButtonKeyDS1990:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"%02X %02X %02X %02X %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]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Dallas");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iButtonKeyMetakom:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton, "%02X %02X %02X %02X", key_data[0], key_data[1], key_data[2], key_data[3]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Metakom");
|
||||||
|
break;
|
||||||
|
|
||||||
|
case iButtonKeyCyfral:
|
||||||
|
ibutton_text_store_set(ibutton, "%02X %02X", key_data[0], key_data[1]);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 51, AlignCenter, AlignBottom, FontSecondary, "Cyfral");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 35, AlignCenter, AlignBottom, FontPrimary, ibutton->text_store);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_info_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
UNUSED(context);
|
||||||
|
UNUSED(event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_info_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
ibutton_text_store_clear(ibutton);
|
||||||
|
widget_reset(ibutton->widget);
|
||||||
|
}
|
72
applications/ibutton/scenes/ibutton_scene_read.c
Normal file
72
applications/ibutton/scenes/ibutton_scene_read.c
Normal file
@ -0,0 +1,72 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
static void ibutton_scene_read_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventWorkerRead);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
iButtonWorker* worker = ibutton->key_worker;
|
||||||
|
DOLPHIN_DEED(DolphinDeedIbuttonRead);
|
||||||
|
|
||||||
|
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_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
ibutton_key_set_name(key, "");
|
||||||
|
|
||||||
|
ibutton_worker_read_set_callback(worker, ibutton_scene_read_callback, ibutton);
|
||||||
|
ibutton_worker_read_start(worker, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeTick) {
|
||||||
|
consumed = true;
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRead);
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventWorkerRead) {
|
||||||
|
bool success = false;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
|
||||||
|
if(ibutton_key_get_type(key) == iButtonKeyDS1990) {
|
||||||
|
if(!ibutton_key_dallas_crc_is_valid(key)) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadCRCError);
|
||||||
|
} else if(!ibutton_key_dallas_is_1990_key(key)) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadNotKeyError);
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
success = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(success) {
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn);
|
||||||
|
DOLPHIN_DEED(DolphinDeedIbuttonReadSuccess);
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadSuccess);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
ibutton_worker_stop(ibutton->key_worker);
|
||||||
|
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
}
|
71
applications/ibutton/scenes/ibutton_scene_read_crc_error.c
Normal file
71
applications/ibutton/scenes/ibutton_scene_read_crc_error.c
Normal file
@ -0,0 +1,71 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <one_wire/maxim_crc.h>
|
||||||
|
|
||||||
|
static void ibutton_scene_read_crc_error_dialog_ex_callback(DialogExResult result, void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_crc_error_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"%02X %02X %02X %02X %02X %02X %02X %02X\nExpected CRC: %X",
|
||||||
|
key_data[0],
|
||||||
|
key_data[1],
|
||||||
|
key_data[2],
|
||||||
|
key_data[3],
|
||||||
|
key_data[4],
|
||||||
|
key_data[5],
|
||||||
|
key_data[6],
|
||||||
|
key_data[7],
|
||||||
|
maxim_crc8(key_data, 7, MAXIM_CRC8_INIT));
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter);
|
||||||
|
dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
|
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||||
|
dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_crc_error_dialog_ex_callback);
|
||||||
|
dialog_ex_set_context(dialog_ex, ibutton);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageError);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_crc_error_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == DialogExResultRight) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu);
|
||||||
|
} else if(event.event == DialogExResultLeft) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_crc_error_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
|
||||||
|
ibutton_text_store_clear(ibutton);
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
||||||
|
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
||||||
|
dialog_ex_set_result_callback(dialog_ex, NULL);
|
||||||
|
dialog_ex_set_context(dialog_ex, NULL);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff);
|
||||||
|
}
|
61
applications/ibutton/scenes/ibutton_scene_read_key_menu.c
Normal file
61
applications/ibutton/scenes/ibutton_scene_read_key_menu.c
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
SubmenuIndexSave,
|
||||||
|
SubmenuIndexEmulate,
|
||||||
|
SubmenuIndexWrite,
|
||||||
|
} SubmenuIndex;
|
||||||
|
|
||||||
|
void ibutton_scene_read_key_menu_submenu_callback(void* context, uint32_t index) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_key_menu_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Save", SubmenuIndexSave, ibutton_scene_read_key_menu_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Emulate",
|
||||||
|
SubmenuIndexEmulate,
|
||||||
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) {
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Write",
|
||||||
|
SubmenuIndexWrite,
|
||||||
|
ibutton_scene_read_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
}
|
||||||
|
|
||||||
|
submenu_set_selected_item(submenu, SubmenuIndexSave);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == SubmenuIndexSave) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveName);
|
||||||
|
} else if(event.event == SubmenuIndexEmulate) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||||
|
} else if(event.event == SubmenuIndexWrite) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_key_menu_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
submenu_reset(ibutton->submenu);
|
||||||
|
}
|
@ -0,0 +1,72 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <one_wire/maxim_crc.h>
|
||||||
|
|
||||||
|
static void
|
||||||
|
ibutton_scene_read_not_key_error_dialog_ex_callback(DialogExResult result, void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_not_key_error_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"THIS IS NOT A KEY\n%02X %02X %02X %02X %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],
|
||||||
|
maxim_crc8(key_data, 7, MAXIM_CRC8_INIT));
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog_ex, "CRC ERROR", 64, 10, AlignCenter, AlignCenter);
|
||||||
|
dialog_ex_set_text(dialog_ex, ibutton->text_store, 64, 19, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
|
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||||
|
dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_not_key_error_dialog_ex_callback);
|
||||||
|
dialog_ex_set_context(dialog_ex, ibutton);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageError);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_not_key_error_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == DialogExResultRight) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu);
|
||||||
|
} else if(event.event == DialogExResultLeft) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_not_key_error_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
|
||||||
|
ibutton_text_store_clear(ibutton);
|
||||||
|
|
||||||
|
dialog_ex_set_header(dialog_ex, NULL, 0, 0, AlignCenter, AlignCenter);
|
||||||
|
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
||||||
|
dialog_ex_set_result_callback(dialog_ex, NULL);
|
||||||
|
dialog_ex_set_context(dialog_ex, NULL);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageRedOff);
|
||||||
|
}
|
87
applications/ibutton/scenes/ibutton_scene_read_success.c
Normal file
87
applications/ibutton/scenes/ibutton_scene_read_success.c
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
static void ibutton_scene_read_success_dialog_ex_callback(DialogExResult result, void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_success_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
|
||||||
|
switch(ibutton_key_get_type(key)) {
|
||||||
|
case iButtonKeyDS1990:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"Dallas\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]);
|
||||||
|
break;
|
||||||
|
case iButtonKeyCyfral:
|
||||||
|
ibutton_text_store_set(ibutton, "Cyfral\n%02X %02X", key_data[0], key_data[1]);
|
||||||
|
break;
|
||||||
|
case iButtonKeyMetakom:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"Metakom\n%02X %02X %02X %02X",
|
||||||
|
key_data[0],
|
||||||
|
key_data[1],
|
||||||
|
key_data[2],
|
||||||
|
key_data[3]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
dialog_ex_set_text(dialog_ex, ibutton->text_store, 95, 30, AlignCenter, AlignCenter);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, "Retry");
|
||||||
|
dialog_ex_set_right_button_text(dialog_ex, "More");
|
||||||
|
dialog_ex_set_icon(dialog_ex, 0, 1, &I_DolphinReadingSuccess_59x63);
|
||||||
|
dialog_ex_set_result_callback(dialog_ex, ibutton_scene_read_success_dialog_ex_callback);
|
||||||
|
dialog_ex_set_context(dialog_ex, ibutton);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewDialogEx);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_read_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
consumed = true;
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneExitConfirm);
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == DialogExResultRight) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneReadKeyMenu);
|
||||||
|
} else if(event.event == DialogExResultLeft) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneRetryConfirm);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_read_success_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
DialogEx* dialog_ex = ibutton->dialog_ex;
|
||||||
|
|
||||||
|
ibutton_text_store_clear(ibutton);
|
||||||
|
|
||||||
|
dialog_ex_set_text(dialog_ex, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
dialog_ex_set_left_button_text(dialog_ex, NULL);
|
||||||
|
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, 0, 0, NULL);
|
||||||
|
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff);
|
||||||
|
}
|
51
applications/ibutton/scenes/ibutton_scene_retry_confirm.c
Normal file
51
applications/ibutton/scenes/ibutton_scene_retry_confirm.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_retry_confirm_widget_callback(
|
||||||
|
GuiButtonType result,
|
||||||
|
InputType type,
|
||||||
|
void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
if(type == InputTypeShort) {
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_retry_confirm_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Widget* widget = ibutton->widget;
|
||||||
|
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeLeft, "Exit", ibutton_scene_retry_confirm_widget_callback, ibutton);
|
||||||
|
widget_add_button_element(
|
||||||
|
widget, GuiButtonTypeRight, "Stay", ibutton_scene_retry_confirm_widget_callback, ibutton);
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 19, AlignCenter, AlignBottom, FontPrimary, "Return to reading?");
|
||||||
|
widget_add_string_element(
|
||||||
|
widget, 64, 29, AlignCenter, AlignBottom, FontSecondary, "All unsaved data will be lost");
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_retry_confirm_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeBack) {
|
||||||
|
consumed = true; // Ignore Back button presses
|
||||||
|
} else if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == GuiButtonTypeLeft) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(scene_manager, iButtonSceneRead);
|
||||||
|
} else if(event.event == GuiButtonTypeRight) {
|
||||||
|
scene_manager_previous_scene(scene_manager);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_retry_confirm_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
widget_reset(ibutton->widget);
|
||||||
|
}
|
68
applications/ibutton/scenes/ibutton_scene_save_name.c
Normal file
68
applications/ibutton/scenes/ibutton_scene_save_name.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <lib/toolbox/random_name.h>
|
||||||
|
|
||||||
|
static void ibutton_scene_save_name_text_input_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventTextEditResult);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_save_name_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
TextInput* text_input = ibutton->text_input;
|
||||||
|
|
||||||
|
const char* key_name = ibutton_key_get_name_p(ibutton->key);
|
||||||
|
const bool key_name_is_empty = !strcmp(key_name, "");
|
||||||
|
|
||||||
|
if(key_name_is_empty) {
|
||||||
|
set_random_name(ibutton->text_store, IBUTTON_TEXT_STORE_SIZE);
|
||||||
|
} else {
|
||||||
|
ibutton_text_store_set(ibutton, "%s", key_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
text_input_set_header_text(text_input, "Name the key");
|
||||||
|
text_input_set_result_callback(
|
||||||
|
text_input,
|
||||||
|
ibutton_scene_save_name_text_input_callback,
|
||||||
|
ibutton,
|
||||||
|
ibutton->text_store,
|
||||||
|
IBUTTON_KEY_NAME_SIZE,
|
||||||
|
key_name_is_empty);
|
||||||
|
|
||||||
|
ValidatorIsFile* validator_is_file =
|
||||||
|
validator_is_file_alloc_init(IBUTTON_APP_FOLDER, IBUTTON_APP_EXTENSION, key_name);
|
||||||
|
text_input_set_validator(text_input, validator_is_file_callback, validator_is_file);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewTextInput);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_save_name_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventTextEditResult) {
|
||||||
|
if(ibutton_save_key(ibutton, ibutton->text_store)) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSaveSuccess);
|
||||||
|
} else {
|
||||||
|
const uint32_t possible_scenes[] = {
|
||||||
|
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||||
|
ibutton_switch_to_previous_scene_one_of(
|
||||||
|
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_save_name_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
TextInput* text_input = ibutton->text_input;
|
||||||
|
|
||||||
|
void* validator_context = text_input_get_validator_callback_context(text_input);
|
||||||
|
text_input_set_validator(text_input, NULL, NULL);
|
||||||
|
validator_is_file_free((ValidatorIsFile*)validator_context);
|
||||||
|
|
||||||
|
text_input_reset(text_input);
|
||||||
|
}
|
52
applications/ibutton/scenes/ibutton_scene_save_success.c
Normal file
52
applications/ibutton/scenes/ibutton_scene_save_success.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
#include <dolphin/dolphin.h>
|
||||||
|
|
||||||
|
static void ibutton_scene_save_success_popup_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_save_success_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
DOLPHIN_DEED(DolphinDeedIbuttonSave);
|
||||||
|
|
||||||
|
popup_set_icon(popup, 32, 5, &I_DolphinNice_96x59);
|
||||||
|
popup_set_header(popup, "Saved!", 5, 7, AlignLeft, AlignTop);
|
||||||
|
|
||||||
|
popup_set_callback(popup, ibutton_scene_save_success_popup_callback);
|
||||||
|
popup_set_context(popup, ibutton);
|
||||||
|
popup_set_timeout(popup, 1500);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_save_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventBack) {
|
||||||
|
const uint32_t possible_scenes[] = {
|
||||||
|
iButtonSceneReadKeyMenu, iButtonSceneSavedKeyMenu, iButtonSceneAddType};
|
||||||
|
ibutton_switch_to_previous_scene_one_of(
|
||||||
|
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_save_success_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
|
||||||
|
popup_disable_timeout(popup);
|
||||||
|
popup_set_context(popup, NULL);
|
||||||
|
popup_set_callback(popup, NULL);
|
||||||
|
}
|
75
applications/ibutton/scenes/ibutton_scene_saved_key_menu.c
Normal file
75
applications/ibutton/scenes/ibutton_scene_saved_key_menu.c
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
enum SubmenuIndex {
|
||||||
|
SubmenuIndexEmulate,
|
||||||
|
SubmenuIndexWrite,
|
||||||
|
SubmenuIndexEdit,
|
||||||
|
SubmenuIndexDelete,
|
||||||
|
SubmenuIndexInfo,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ibutton_scene_saved_key_menu_submenu_callback(void* context, uint32_t index) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_saved_key_menu_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Emulate",
|
||||||
|
SubmenuIndexEmulate,
|
||||||
|
ibutton_scene_saved_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
if(ibutton_key_get_type(ibutton->key) == iButtonKeyDS1990) {
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Write",
|
||||||
|
SubmenuIndexWrite,
|
||||||
|
ibutton_scene_saved_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
}
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Edit", SubmenuIndexEdit, ibutton_scene_saved_key_menu_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu,
|
||||||
|
"Delete",
|
||||||
|
SubmenuIndexDelete,
|
||||||
|
ibutton_scene_saved_key_menu_submenu_callback,
|
||||||
|
ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Info", SubmenuIndexInfo, ibutton_scene_saved_key_menu_submenu_callback, ibutton);
|
||||||
|
|
||||||
|
submenu_set_selected_item(submenu, SubmenuIndexEmulate);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_saved_key_menu_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == SubmenuIndexEmulate) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneEmulate);
|
||||||
|
} else if(event.event == SubmenuIndexWrite) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneWrite);
|
||||||
|
} else if(event.event == SubmenuIndexEdit) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddValue);
|
||||||
|
} else if(event.event == SubmenuIndexDelete) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneDeleteConfirm);
|
||||||
|
} else if(event.event == SubmenuIndexInfo) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneInfo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_saved_key_menu_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
submenu_reset(ibutton->submenu);
|
||||||
|
}
|
22
applications/ibutton/scenes/ibutton_scene_select_key.c
Normal file
22
applications/ibutton/scenes/ibutton_scene_select_key.c
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
void ibutton_scene_select_key_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
|
||||||
|
if(!ibutton_file_select(ibutton)) {
|
||||||
|
scene_manager_search_and_switch_to_previous_scene(
|
||||||
|
ibutton->scene_manager, iButtonSceneStart);
|
||||||
|
} else {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSavedKeyMenu);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_select_key_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
UNUSED(context);
|
||||||
|
UNUSED(event);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_select_key_on_exit(void* context) {
|
||||||
|
UNUSED(context);
|
||||||
|
}
|
51
applications/ibutton/scenes/ibutton_scene_start.c
Normal file
51
applications/ibutton/scenes/ibutton_scene_start.c
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
enum SubmenuIndex {
|
||||||
|
SubmenuIndexRead,
|
||||||
|
SubmenuIndexSaved,
|
||||||
|
SubmenuIndexAdd,
|
||||||
|
};
|
||||||
|
|
||||||
|
void ibutton_scene_start_submenu_callback(void* context, uint32_t index) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_start_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Submenu* submenu = ibutton->submenu;
|
||||||
|
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Read", SubmenuIndexRead, ibutton_scene_start_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Saved", SubmenuIndexSaved, ibutton_scene_start_submenu_callback, ibutton);
|
||||||
|
submenu_add_item(
|
||||||
|
submenu, "Add Manually", SubmenuIndexAdd, ibutton_scene_start_submenu_callback, ibutton);
|
||||||
|
|
||||||
|
submenu_set_selected_item(submenu, SubmenuIndexRead);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewSubmenu);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_start_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == SubmenuIndexRead) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneRead);
|
||||||
|
} else if(event.event == SubmenuIndexSaved) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneSelectKey);
|
||||||
|
} else if(event.event == SubmenuIndexAdd) {
|
||||||
|
scene_manager_next_scene(ibutton->scene_manager, iButtonSceneAddType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_start_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
submenu_reset(ibutton->submenu);
|
||||||
|
}
|
121
applications/ibutton/scenes/ibutton_scene_write.c
Normal file
121
applications/ibutton/scenes/ibutton_scene_write.c
Normal file
@ -0,0 +1,121 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
iButtonSceneWriteStateDefault,
|
||||||
|
iButtonSceneWriteStateBlinkYellow,
|
||||||
|
} iButtonSceneWriteState;
|
||||||
|
|
||||||
|
static void ibutton_scene_write_callback(void* context, iButtonWorkerWriteResult result) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_write_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
iButtonKey* key = ibutton->key;
|
||||||
|
iButtonWorker* worker = ibutton->key_worker;
|
||||||
|
|
||||||
|
const uint8_t* key_data = ibutton_key_get_data_p(key);
|
||||||
|
const char* key_name = ibutton_key_get_name_p(key);
|
||||||
|
|
||||||
|
uint8_t line_count = 2;
|
||||||
|
|
||||||
|
// check that stored key has name
|
||||||
|
if(strcmp(key_name, "") != 0) {
|
||||||
|
ibutton_text_store_set(ibutton, "writing\n%s", key_name);
|
||||||
|
line_count = 2;
|
||||||
|
} else {
|
||||||
|
// if not, show key data
|
||||||
|
switch(ibutton_key_get_type(key)) {
|
||||||
|
case iButtonKeyDS1990:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"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 iButtonKeyCyfral:
|
||||||
|
ibutton_text_store_set(ibutton, "writing\n%02X %02X", key_data[0], key_data[1]);
|
||||||
|
line_count = 2;
|
||||||
|
break;
|
||||||
|
case iButtonKeyMetakom:
|
||||||
|
ibutton_text_store_set(
|
||||||
|
ibutton,
|
||||||
|
"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", 82, 18, AlignCenter, AlignBottom);
|
||||||
|
popup_set_text(popup, ibutton->text_store, 82, 22, AlignCenter, AlignTop);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
popup_set_header(popup, "iButton", 82, 24, AlignCenter, AlignBottom);
|
||||||
|
popup_set_text(popup, ibutton->text_store, 82, 28, AlignCenter, AlignTop);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
popup_set_icon(popup, 2, 10, &I_iButtonKey_49x44);
|
||||||
|
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
ibutton->scene_manager, iButtonSceneWrite, iButtonSceneWriteStateDefault);
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
|
||||||
|
ibutton_worker_write_set_callback(worker, ibutton_scene_write_callback, ibutton);
|
||||||
|
ibutton_worker_write_start(worker, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_write_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
SceneManager* scene_manager = ibutton->scene_manager;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if((event.event == iButtonWorkerWriteOK) || (event.event == iButtonWorkerWriteSameKey)) {
|
||||||
|
scene_manager_next_scene(scene_manager, iButtonSceneWriteSuccess);
|
||||||
|
} else if(event.event == iButtonWorkerWriteNoDetect) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
scene_manager, iButtonSceneWrite, iButtonSceneWriteStateDefault);
|
||||||
|
} else if(event.event == iButtonWorkerWriteCannotWrite) {
|
||||||
|
scene_manager_set_scene_state(
|
||||||
|
scene_manager, iButtonSceneWrite, iButtonSceneWriteStateBlinkYellow);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else if(event.type == SceneManagerEventTypeTick) {
|
||||||
|
consumed = true;
|
||||||
|
if(scene_manager_get_scene_state(scene_manager, iButtonSceneWrite) ==
|
||||||
|
iButtonSceneWriteStateBlinkYellow) {
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageYellowBlink);
|
||||||
|
} else {
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageEmulate);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_write_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
ibutton_worker_stop(ibutton->key_worker);
|
||||||
|
popup_set_header(popup, NULL, 0, 0, AlignCenter, AlignBottom);
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
}
|
52
applications/ibutton/scenes/ibutton_scene_write_success.c
Normal file
52
applications/ibutton/scenes/ibutton_scene_write_success.c
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
#include "../ibutton_i.h"
|
||||||
|
|
||||||
|
static void ibutton_scene_write_success_popup_callback(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
view_dispatcher_send_custom_event(ibutton->view_dispatcher, iButtonCustomEventBack);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOff);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_write_success_on_enter(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
|
popup_set_icon(popup, 0, 12, &I_iButtonDolphinVerySuccess_108x52);
|
||||||
|
popup_set_text(popup, "Successfully written!", 40, 12, AlignLeft, AlignBottom);
|
||||||
|
|
||||||
|
popup_set_callback(popup, ibutton_scene_write_success_popup_callback);
|
||||||
|
popup_set_context(popup, ibutton);
|
||||||
|
popup_set_timeout(popup, 1500);
|
||||||
|
popup_enable_timeout(popup);
|
||||||
|
|
||||||
|
view_dispatcher_switch_to_view(ibutton->view_dispatcher, iButtonViewPopup);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageSuccess);
|
||||||
|
ibutton_notification_message(ibutton, iButtonNotificationMessageGreenOn);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ibutton_scene_write_success_on_event(void* context, SceneManagerEvent event) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
|
if(event.type == SceneManagerEventTypeCustom) {
|
||||||
|
consumed = true;
|
||||||
|
if(event.event == iButtonCustomEventBack) {
|
||||||
|
const uint32_t possible_scenes[] = {iButtonSceneReadKeyMenu, iButtonSceneStart};
|
||||||
|
ibutton_switch_to_previous_scene_one_of(
|
||||||
|
ibutton, possible_scenes, sizeof(possible_scenes) / sizeof(uint32_t));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ibutton_scene_write_success_on_exit(void* context) {
|
||||||
|
iButton* ibutton = context;
|
||||||
|
Popup* popup = ibutton->popup;
|
||||||
|
|
||||||
|
popup_set_text(popup, NULL, 0, 0, AlignCenter, AlignTop);
|
||||||
|
popup_set_icon(popup, 0, 0, NULL);
|
||||||
|
|
||||||
|
popup_disable_timeout(popup);
|
||||||
|
popup_set_context(popup, NULL);
|
||||||
|
popup_set_callback(popup, NULL);
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user