[FL-1061] iButton save and load from sd card (#394)
* SD App: fix queue adresses * sd-filesystem: fix making path on file select event * ibutton: add key reading from sd card * ibutton: save ibutton key to sd card * ibutton: add deleting keys from sd card * ibutton: remove KeyStore from application * ibutton: make directory if necessary on key save Co-authored-by: DrZlo13 <who.just.the.doctor@gmail.com> Co-authored-by: あく <alleteam@gmail.com>
This commit is contained in:
parent
6375f21cf5
commit
5309bfae41
@ -177,7 +177,7 @@ const FlipperApplication FLIPPER_APPS[] = {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BUILD_IBUTTON
|
#ifdef BUILD_IBUTTON
|
||||||
{.app = app_ibutton, .name = "iButton", .stack_size = 1024, .icon = A_iButton_14},
|
{.app = app_ibutton, .name = "iButton", .stack_size = 4096, .icon = A_iButton_14},
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef BUILD_GPIO_DEMO
|
#ifdef BUILD_GPIO_DEMO
|
||||||
|
@ -96,6 +96,9 @@ static bool file_select_input_callback(InputEvent* event, void* context) {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
if(!file_select_fill_strings(file_select)) {
|
||||||
|
file_select->callback(false, file_select->context);
|
||||||
|
}
|
||||||
} else if(event->key == InputKeyDown) {
|
} else if(event->key == InputKeyDown) {
|
||||||
with_view_model(
|
with_view_model(
|
||||||
file_select->view, (FileSelectModel * model) {
|
file_select->view, (FileSelectModel * model) {
|
||||||
@ -121,6 +124,9 @@ static bool file_select_input_callback(InputEvent* event, void* context) {
|
|||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
|
if(!file_select_fill_strings(file_select)) {
|
||||||
|
file_select->callback(false, file_select->context);
|
||||||
|
}
|
||||||
} else if(event->key == InputKeyOk) {
|
} else if(event->key == InputKeyOk) {
|
||||||
if(file_select->callback != NULL) {
|
if(file_select->callback != NULL) {
|
||||||
const char* result;
|
const char* result;
|
||||||
@ -138,10 +144,6 @@ static bool file_select_input_callback(InputEvent* event, void* context) {
|
|||||||
}
|
}
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!file_select_fill_strings(file_select)) {
|
|
||||||
file_select->callback(false, file_select->context);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return consumed;
|
return consumed;
|
||||||
@ -207,6 +209,8 @@ void file_select_set_api(FileSelect* file_select, FS_Api* fs_api) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void file_select_set_callback(FileSelect* file_select, FileSelectCallback callback, void* context) {
|
void file_select_set_callback(FileSelect* file_select, FileSelectCallback callback, void* context) {
|
||||||
|
file_select->context = context;
|
||||||
|
file_select->callback = callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
void file_select_set_filter(FileSelect* file_select, const char* path, const char* extension) {
|
void file_select_set_filter(FileSelect* file_select, const char* path, const char* extension) {
|
||||||
|
@ -1,69 +0,0 @@
|
|||||||
#include "key-store.h"
|
|
||||||
#include <furi.h>
|
|
||||||
|
|
||||||
uint16_t KeyStore::get_key_count() {
|
|
||||||
return store.size();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t KeyStore::add_key() {
|
|
||||||
store.push_back(iButtonKey());
|
|
||||||
return get_key_count() - 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyStore::set_key_type(uint8_t index, iButtonKeyType type) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
key->set_type(type);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyStore::set_key_name(uint8_t index, char* name) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
char* orphan = strdup(name);
|
|
||||||
key->set_name(orphan);
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyStore::set_key_data(uint8_t index, uint8_t* data, uint8_t data_size) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
key->set_data(data, data_size);
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonKeyType KeyStore::get_key_type(uint8_t index) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
return key->get_key_type();
|
|
||||||
}
|
|
||||||
|
|
||||||
const char* KeyStore::get_key_name(uint8_t index) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
return key->get_name();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t* KeyStore::get_key_data(uint8_t index) {
|
|
||||||
iButtonKey* key = get_key(index);
|
|
||||||
return key->get_data();
|
|
||||||
}
|
|
||||||
|
|
||||||
void KeyStore::remove_key(uint8_t index) {
|
|
||||||
furi_check(index >= 0);
|
|
||||||
furi_check(index < get_key_count());
|
|
||||||
auto item = std::next(store.begin(), index);
|
|
||||||
store.erase(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyStore::KeyStore() {
|
|
||||||
store.push_back(iButtonKey(
|
|
||||||
iButtonKeyType::KeyDallas, "Dallas_1", 0x01, 0x41, 0xCE, 0x67, 0x0F, 0x00, 0x00, 0xB6));
|
|
||||||
store.push_back(iButtonKey(
|
|
||||||
iButtonKeyType::KeyDallas, "Dallas_2", 0x01, 0xFD, 0x0E, 0x84, 0x01, 0x00, 0x00, 0xDB));
|
|
||||||
store.push_back(iButtonKey(
|
|
||||||
iButtonKeyType::KeyCyfral, "Cyfral_1", 0xA6, 0xD2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00));
|
|
||||||
store.push_back(iButtonKey(
|
|
||||||
iButtonKeyType::KeyMetakom, "Metakom_1", 0xB1, 0x2E, 0x47, 0xB2, 0x00, 0x00, 0x00, 0x00));
|
|
||||||
}
|
|
||||||
|
|
||||||
KeyStore::~KeyStore() {
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonKey* KeyStore::get_key(uint8_t index) {
|
|
||||||
furi_check(index >= 0);
|
|
||||||
furi_check(index < get_key_count());
|
|
||||||
return &(*std::next(store.begin(), index));
|
|
||||||
}
|
|
@ -1,29 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include <stdint.h>
|
|
||||||
#include <list>
|
|
||||||
#include "key-info.h"
|
|
||||||
#include "../ibutton-key.h"
|
|
||||||
|
|
||||||
class KeyStore {
|
|
||||||
public:
|
|
||||||
uint16_t get_key_count();
|
|
||||||
|
|
||||||
uint8_t add_key();
|
|
||||||
|
|
||||||
void set_key_type(uint8_t index, iButtonKeyType type);
|
|
||||||
void set_key_name(uint8_t index, char* name);
|
|
||||||
void set_key_data(uint8_t index, uint8_t* data, uint8_t data_size);
|
|
||||||
|
|
||||||
iButtonKeyType get_key_type(uint8_t index);
|
|
||||||
const char* get_key_name(uint8_t index);
|
|
||||||
uint8_t* get_key_data(uint8_t index);
|
|
||||||
|
|
||||||
void remove_key(uint8_t index);
|
|
||||||
|
|
||||||
KeyStore();
|
|
||||||
~KeyStore();
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::list<iButtonKey> store;
|
|
||||||
iButtonKey* get_key(uint8_t index);
|
|
||||||
};
|
|
@ -28,12 +28,16 @@ iButtonApp::iButtonApp() {
|
|||||||
api_hal_power_insomnia_enter();
|
api_hal_power_insomnia_enter();
|
||||||
|
|
||||||
key_worker = new KeyWorker(&ibutton_gpio);
|
key_worker = new KeyWorker(&ibutton_gpio);
|
||||||
|
sd_ex_api = static_cast<SdCard_Api*>(furi_record_open("sdcard-ex"));
|
||||||
|
fs_api = static_cast<FS_Api*>(furi_record_open("sdcard"));
|
||||||
|
|
||||||
// we need random
|
// we need random
|
||||||
srand(DWT->CYCCNT);
|
srand(DWT->CYCCNT);
|
||||||
}
|
}
|
||||||
|
|
||||||
iButtonApp::~iButtonApp() {
|
iButtonApp::~iButtonApp() {
|
||||||
|
furi_record_close("sdcard-ex");
|
||||||
|
furi_record_close("sdcard");
|
||||||
api_hal_power_insomnia_exit();
|
api_hal_power_insomnia_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -107,6 +111,22 @@ iButtonKey* iButtonApp::get_key() {
|
|||||||
return &key;
|
return &key;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SdCard_Api* iButtonApp::get_sd_ex_api() {
|
||||||
|
return sd_ex_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
FS_Api* iButtonApp::get_fs_api() {
|
||||||
|
return fs_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* iButtonApp::get_file_name() {
|
||||||
|
return file_name;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t iButtonApp::get_file_name_size() {
|
||||||
|
return file_name_size;
|
||||||
|
}
|
||||||
|
|
||||||
void iButtonApp::notify_init() {
|
void iButtonApp::notify_init() {
|
||||||
// TODO open record
|
// TODO open record
|
||||||
const GpioPin* vibro_record = &vibro_gpio;
|
const GpioPin* vibro_record = &vibro_gpio;
|
||||||
@ -193,18 +213,6 @@ uint8_t iButtonApp::get_text_store_size() {
|
|||||||
return text_store_size;
|
return text_store_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
KeyStore* iButtonApp::get_key_store() {
|
|
||||||
return &store;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint8_t iButtonApp::get_stored_key_index() {
|
|
||||||
return key_index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::set_stored_key_index(uint8_t _index) {
|
|
||||||
key_index = _index;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonApp::generate_random_name(char* name, uint8_t max_name_size) {
|
void iButtonApp::generate_random_name(char* name, uint8_t max_name_size) {
|
||||||
const uint8_t prefix_size = 9;
|
const uint8_t prefix_size = 9;
|
||||||
const char* prefix[prefix_size] = {
|
const char* prefix[prefix_size] = {
|
||||||
|
@ -12,7 +12,6 @@
|
|||||||
#include "scene/ibutton-scene-readed-key-menu.h"
|
#include "scene/ibutton-scene-readed-key-menu.h"
|
||||||
#include "scene/ibutton-scene-write.h"
|
#include "scene/ibutton-scene-write.h"
|
||||||
#include "scene/ibutton-scene-write-success.h"
|
#include "scene/ibutton-scene-write-success.h"
|
||||||
#include "scene/ibutton-scene-saved.h"
|
|
||||||
#include "scene/ibutton-scene-saved-key-menu.h"
|
#include "scene/ibutton-scene-saved-key-menu.h"
|
||||||
#include "scene/ibutton-scene-delete-confirm.h"
|
#include "scene/ibutton-scene-delete-confirm.h"
|
||||||
#include "scene/ibutton-scene-delete-success.h"
|
#include "scene/ibutton-scene-delete-success.h"
|
||||||
@ -23,9 +22,11 @@
|
|||||||
#include "scene/ibutton-scene-add-type.h"
|
#include "scene/ibutton-scene-add-type.h"
|
||||||
#include "scene/ibutton-scene-add-value.h"
|
#include "scene/ibutton-scene-add-value.h"
|
||||||
|
|
||||||
#include "helpers/key-store.h"
|
|
||||||
#include "helpers/key-worker.h"
|
#include "helpers/key-worker.h"
|
||||||
|
|
||||||
|
#include <sd-card-api.h>
|
||||||
|
#include <filesystem-api.h>
|
||||||
|
|
||||||
#include "one_wire_master.h"
|
#include "one_wire_master.h"
|
||||||
#include "maxim_crc.h"
|
#include "maxim_crc.h"
|
||||||
#include "ibutton-key.h"
|
#include "ibutton-key.h"
|
||||||
@ -48,7 +49,6 @@ public:
|
|||||||
SceneWrite,
|
SceneWrite,
|
||||||
SceneWriteSuccess,
|
SceneWriteSuccess,
|
||||||
SceneEmulate,
|
SceneEmulate,
|
||||||
SceneSavedList,
|
|
||||||
SceneSavedKeyMenu,
|
SceneSavedKeyMenu,
|
||||||
SceneDeleteConfirm,
|
SceneDeleteConfirm,
|
||||||
SceneDeleteSuccess,
|
SceneDeleteSuccess,
|
||||||
@ -88,9 +88,10 @@ public:
|
|||||||
char* get_text_store();
|
char* get_text_store();
|
||||||
uint8_t get_text_store_size();
|
uint8_t get_text_store_size();
|
||||||
|
|
||||||
KeyStore* get_key_store();
|
SdCard_Api* get_sd_ex_api();
|
||||||
uint8_t get_stored_key_index();
|
FS_Api* get_fs_api();
|
||||||
void set_stored_key_index(uint8_t index);
|
char* get_file_name();
|
||||||
|
uint8_t get_file_name_size();
|
||||||
|
|
||||||
void generate_random_name(char* name, uint8_t max_name_size);
|
void generate_random_name(char* name, uint8_t max_name_size);
|
||||||
|
|
||||||
@ -109,7 +110,6 @@ private:
|
|||||||
{Scene::SceneWrite, new iButtonSceneWrite()},
|
{Scene::SceneWrite, new iButtonSceneWrite()},
|
||||||
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
|
{Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()},
|
||||||
{Scene::SceneEmulate, new iButtonSceneEmulate()},
|
{Scene::SceneEmulate, new iButtonSceneEmulate()},
|
||||||
{Scene::SceneSavedList, new iButtonSceneSavedList()},
|
|
||||||
{Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()},
|
{Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()},
|
||||||
{Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()},
|
{Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()},
|
||||||
{Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()},
|
{Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()},
|
||||||
@ -123,12 +123,14 @@ private:
|
|||||||
KeyWorker* key_worker;
|
KeyWorker* key_worker;
|
||||||
|
|
||||||
iButtonKey key;
|
iButtonKey key;
|
||||||
uint8_t key_index = 0;
|
|
||||||
|
SdCard_Api* sd_ex_api;
|
||||||
|
FS_Api* fs_api;
|
||||||
|
static const uint8_t file_name_size = 100;
|
||||||
|
char file_name[file_name_size];
|
||||||
|
|
||||||
static const uint8_t text_store_size = 128;
|
static const uint8_t text_store_size = 128;
|
||||||
char text_store[text_store_size + 1];
|
char text_store[text_store_size + 1];
|
||||||
|
|
||||||
KeyStore store;
|
|
||||||
|
|
||||||
void notify_init();
|
void notify_init();
|
||||||
};
|
};
|
@ -51,28 +51,5 @@ iButtonKeyType iButtonKey::get_key_type() {
|
|||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
iButtonKey::iButtonKey(
|
|
||||||
iButtonKeyType _type,
|
|
||||||
const char* _name,
|
|
||||||
uint8_t d0,
|
|
||||||
uint8_t d1,
|
|
||||||
uint8_t d2,
|
|
||||||
uint8_t d3,
|
|
||||||
uint8_t d4,
|
|
||||||
uint8_t d5,
|
|
||||||
uint8_t d6,
|
|
||||||
uint8_t d7) {
|
|
||||||
type = _type;
|
|
||||||
name = _name;
|
|
||||||
data[0] = d0;
|
|
||||||
data[1] = d1;
|
|
||||||
data[2] = d2;
|
|
||||||
data[3] = d3;
|
|
||||||
data[4] = d4;
|
|
||||||
data[5] = d5;
|
|
||||||
data[6] = d6;
|
|
||||||
data[7] = d7;
|
|
||||||
}
|
|
||||||
|
|
||||||
iButtonKey::iButtonKey() {
|
iButtonKey::iButtonKey() {
|
||||||
}
|
}
|
||||||
|
@ -16,19 +16,6 @@ public:
|
|||||||
void set_type(iButtonKeyType key_type);
|
void set_type(iButtonKeyType key_type);
|
||||||
iButtonKeyType get_key_type();
|
iButtonKeyType get_key_type();
|
||||||
|
|
||||||
// temporary constructor for KeyStore mockup
|
|
||||||
iButtonKey(
|
|
||||||
iButtonKeyType type,
|
|
||||||
const char* name,
|
|
||||||
uint8_t d0,
|
|
||||||
uint8_t d1,
|
|
||||||
uint8_t d2,
|
|
||||||
uint8_t d3,
|
|
||||||
uint8_t d4,
|
|
||||||
uint8_t d5,
|
|
||||||
uint8_t d6,
|
|
||||||
uint8_t d7);
|
|
||||||
|
|
||||||
iButtonKey();
|
iButtonKey();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -55,10 +55,19 @@ bool iButtonSceneDeleteConfirm::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
if(event->type == iButtonEvent::Type::EventTypeDialogResult) {
|
||||||
if(event->payload.dialog_result == DialogExResultRight) {
|
if(event->payload.dialog_result == DialogExResultRight) {
|
||||||
KeyStore* store = app->get_key_store();
|
iButtonKey* key = app->get_key();
|
||||||
store->remove_key(app->get_stored_key_index());
|
string_t key_file_name;
|
||||||
|
string_init_set_str(key_file_name, "ibutton/");
|
||||||
|
string_cat_str(key_file_name, key->get_name());
|
||||||
|
bool res =
|
||||||
|
(app->get_fs_api()->common.remove(string_get_cstr(key_file_name)) == FSE_OK);
|
||||||
|
string_clear(key_file_name);
|
||||||
|
if(res) {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess);
|
||||||
|
} else {
|
||||||
|
// TODO error file path
|
||||||
|
// app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteFail);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
app->switch_to_previous_scene();
|
app->switch_to_previous_scene();
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ bool iButtonSceneDeleteSuccess::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
if(event->type == iButtonEvent::Type::EventTypeBack) {
|
||||||
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneSavedList});
|
app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart});
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "../ibutton-event.h"
|
#include "../ibutton-event.h"
|
||||||
#include "../ibutton-key.h"
|
#include "../ibutton-key.h"
|
||||||
#include <callback-connector.h>
|
#include <callback-connector.h>
|
||||||
|
#include <filesystem-api.h>
|
||||||
|
|
||||||
void iButtonSceneSaveName::on_enter(iButtonApp* app) {
|
void iButtonSceneSaveName::on_enter(iButtonApp* app) {
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
iButtonAppViewManager* view_manager = app->get_view_manager();
|
||||||
@ -28,14 +29,23 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
bool consumed = false;
|
bool consumed = false;
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeTextEditResult) {
|
if(event->type == iButtonEvent::Type::EventTypeTextEditResult) {
|
||||||
KeyStore* store = app->get_key_store();
|
|
||||||
uint8_t key_index = store->add_key();
|
|
||||||
iButtonKey* key = app->get_key();
|
iButtonKey* key = app->get_key();
|
||||||
|
File key_file;
|
||||||
store->set_key_type(key_index, key->get_key_type());
|
string_t key_file_name;
|
||||||
store->set_key_name(key_index, app->get_text_store());
|
string_init_set_str(key_file_name, "ibutton/");
|
||||||
store->set_key_data(key_index, key->get_data(), key->get_size());
|
string_cat_str(key_file_name, app->get_text_store());
|
||||||
|
uint8_t key_data[IBUTTON_KEY_SIZE + 1];
|
||||||
|
key_data[0] = static_cast<uint8_t>(key->get_key_type());
|
||||||
|
memcpy(key_data + 1, key->get_data(), IBUTTON_KEY_SIZE);
|
||||||
|
// Create ibutton directory if necessary
|
||||||
|
app->get_fs_api()->common.mkdir("ibutton");
|
||||||
|
bool res = app->get_fs_api()->file.open(
|
||||||
|
&key_file, string_get_cstr(key_file_name), FSAM_WRITE, FSOM_CREATE_ALWAYS);
|
||||||
|
if(res) {
|
||||||
|
res = app->get_fs_api()->file.write(&key_file, key_data, IBUTTON_KEY_SIZE + 1);
|
||||||
|
res = app->get_fs_api()->file.close(&key_file);
|
||||||
|
}
|
||||||
|
string_clear(key_file_name);
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneSaveSuccess);
|
||||||
consumed = true;
|
consumed = true;
|
||||||
}
|
}
|
||||||
|
@ -1,62 +0,0 @@
|
|||||||
#include "ibutton-scene-saved.h"
|
|
||||||
#include "../ibutton-app.h"
|
|
||||||
#include "../ibutton-view-manager.h"
|
|
||||||
#include "../ibutton-event.h"
|
|
||||||
#include <callback-connector.h>
|
|
||||||
|
|
||||||
void iButtonSceneSavedList::on_enter(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view_manager = app->get_view_manager();
|
|
||||||
Submenu* submenu = view_manager->get_submenu();
|
|
||||||
auto callback = cbc::obtain_connector(this, &iButtonSceneSavedList::submenu_callback);
|
|
||||||
|
|
||||||
KeyStore* store = app->get_key_store();
|
|
||||||
|
|
||||||
if(store->get_key_count() > 0) {
|
|
||||||
for(uint8_t i = 0; i < store->get_key_count(); i++) {
|
|
||||||
submenu_add_item(submenu, store->get_key_name(i), i, callback, app);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
submenu_add_item(submenu, "Empty", 0, NULL, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
view_manager->switch_to(iButtonAppViewManager::Type::iButtonAppViewSubmenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool iButtonSceneSavedList::on_event(iButtonApp* app, iButtonEvent* event) {
|
|
||||||
bool consumed = false;
|
|
||||||
|
|
||||||
if(event->type == iButtonEvent::Type::EventTypeMenuSelected) {
|
|
||||||
uint8_t key_index = event->payload.menu_index;
|
|
||||||
|
|
||||||
// store data
|
|
||||||
iButtonKey* stored_key_data = app->get_key();
|
|
||||||
KeyStore* store = app->get_key_store();
|
|
||||||
|
|
||||||
app->set_stored_key_index(key_index);
|
|
||||||
stored_key_data->set_name(store->get_key_name(key_index));
|
|
||||||
stored_key_data->set_type(store->get_key_type(key_index));
|
|
||||||
stored_key_data->set_data(store->get_key_data(key_index), stored_key_data->get_size());
|
|
||||||
|
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSavedKeyMenu);
|
|
||||||
consumed = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return consumed;
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSavedList::on_exit(iButtonApp* app) {
|
|
||||||
iButtonAppViewManager* view = app->get_view_manager();
|
|
||||||
Submenu* submenu = view->get_submenu();
|
|
||||||
|
|
||||||
submenu_clean(submenu);
|
|
||||||
}
|
|
||||||
|
|
||||||
void iButtonSceneSavedList::submenu_callback(void* context, uint32_t index) {
|
|
||||||
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);
|
|
||||||
}
|
|
@ -1,12 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
#include "ibutton-scene-generic.h"
|
|
||||||
|
|
||||||
class iButtonSceneSavedList : public iButtonScene {
|
|
||||||
public:
|
|
||||||
void on_enter(iButtonApp* app) final;
|
|
||||||
bool on_event(iButtonApp* app, iButtonEvent* event) final;
|
|
||||||
void on_exit(iButtonApp* app) final;
|
|
||||||
|
|
||||||
private:
|
|
||||||
void submenu_callback(void* context, uint32_t index);
|
|
||||||
};
|
|
@ -3,6 +3,7 @@
|
|||||||
#include "../ibutton-view-manager.h"
|
#include "../ibutton-view-manager.h"
|
||||||
#include "../ibutton-event.h"
|
#include "../ibutton-event.h"
|
||||||
#include <callback-connector.h>
|
#include <callback-connector.h>
|
||||||
|
#include <filesystem-api.h>
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SubmenuIndexRead,
|
SubmenuIndexRead,
|
||||||
@ -30,9 +31,40 @@ bool iButtonSceneStart::on_event(iButtonApp* app, iButtonEvent* event) {
|
|||||||
case SubmenuIndexRead:
|
case SubmenuIndexRead:
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneRead);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneRead);
|
||||||
break;
|
break;
|
||||||
case SubmenuIndexSaved:
|
case SubmenuIndexSaved: {
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneSavedList);
|
bool res = app->get_sd_ex_api()->file_select(
|
||||||
break;
|
app->get_sd_ex_api()->context,
|
||||||
|
"ibutton",
|
||||||
|
"*",
|
||||||
|
app->get_file_name(),
|
||||||
|
app->get_file_name_size());
|
||||||
|
if(res) {
|
||||||
|
string_t key_str;
|
||||||
|
string_init_set_str(key_str, "ibutton/");
|
||||||
|
string_cat_str(key_str, app->get_file_name());
|
||||||
|
File key_file;
|
||||||
|
uint8_t key_data[IBUTTON_KEY_SIZE + 1] = {};
|
||||||
|
// Read data from file
|
||||||
|
// TODO handle false return
|
||||||
|
res = app->get_fs_api()->file.open(
|
||||||
|
&key_file, string_get_cstr(key_str), FSAM_READ, FSOM_OPEN_EXISTING);
|
||||||
|
res = app->get_fs_api()->file.read(&key_file, key_data, IBUTTON_KEY_SIZE + 1);
|
||||||
|
res = app->get_fs_api()->file.close(&key_file);
|
||||||
|
string_clear(key_str);
|
||||||
|
// Set key
|
||||||
|
iButtonKeyType key_type = static_cast<iButtonKeyType>(key_data[0]);
|
||||||
|
if(key_type > iButtonKeyType::KeyMetakom) {
|
||||||
|
app->switch_to_next_scene(iButtonApp::Scene::SceneStart);
|
||||||
|
}
|
||||||
|
app->get_key()->set_name(app->get_file_name());
|
||||||
|
app->get_key()->set_type(key_type);
|
||||||
|
app->get_key()->set_data(key_data + 1, IBUTTON_KEY_SIZE);
|
||||||
|
app->switch_to_next_scene(iButtonApp::Scene::SceneSavedKeyMenu);
|
||||||
|
} else {
|
||||||
|
// TODO add error scene
|
||||||
|
app->switch_to_next_scene(iButtonApp::Scene::SceneStart);
|
||||||
|
}
|
||||||
|
}; break;
|
||||||
case SubmenuIndexAdd:
|
case SubmenuIndexAdd:
|
||||||
app->switch_to_next_scene(iButtonApp::Scene::SceneAddType);
|
app->switch_to_next_scene(iButtonApp::Scene::SceneAddType);
|
||||||
break;
|
break;
|
||||||
|
@ -325,7 +325,7 @@ bool app_sd_make_path(const char* path) {
|
|||||||
|
|
||||||
if(*path) {
|
if(*path) {
|
||||||
char* file_path = strdup(path);
|
char* file_path = strdup(path);
|
||||||
|
// Make parent directories
|
||||||
for(char* p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
|
for(char* p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) {
|
||||||
*p = '\0';
|
*p = '\0';
|
||||||
SDError result = f_mkdir(file_path);
|
SDError result = f_mkdir(file_path);
|
||||||
@ -339,6 +339,14 @@ bool app_sd_make_path(const char* path) {
|
|||||||
}
|
}
|
||||||
*p = '/';
|
*p = '/';
|
||||||
}
|
}
|
||||||
|
// Make origin directory
|
||||||
|
SDError result = f_mkdir(file_path);
|
||||||
|
if(result != SD_OK) {
|
||||||
|
if(result != SD_EXIST) {
|
||||||
|
free(file_path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
free(file_path);
|
free(file_path);
|
||||||
}
|
}
|
||||||
@ -393,7 +401,7 @@ bool sd_api_file_select(
|
|||||||
SdAppFileSelectResultEvent event;
|
SdAppFileSelectResultEvent event;
|
||||||
while(1) {
|
while(1) {
|
||||||
osStatus_t event_status =
|
osStatus_t event_status =
|
||||||
osMessageQueueGet(sd_app->event_queue, &event, NULL, osWaitForever);
|
osMessageQueueGet(return_event_queue, &event, NULL, osWaitForever);
|
||||||
if(event_status == osOK) {
|
if(event_status == osOK) {
|
||||||
retval = event.result;
|
retval = event.result;
|
||||||
break;
|
break;
|
||||||
@ -697,7 +705,7 @@ int32_t sd_filesystem(void* p) {
|
|||||||
case SdAppStateFileSelect: {
|
case SdAppStateFileSelect: {
|
||||||
SdAppFileSelectResultEvent retval = {.result = true};
|
SdAppFileSelectResultEvent retval = {.result = true};
|
||||||
furi_check(
|
furi_check(
|
||||||
osMessageQueuePut(event.result_receiver, &retval, 0, osWaitForever) ==
|
osMessageQueuePut(sd_app->result_receiver, &retval, 0, osWaitForever) ==
|
||||||
osOK);
|
osOK);
|
||||||
app_reset_state(sd_app);
|
app_reset_state(sd_app);
|
||||||
}; break;
|
}; break;
|
||||||
@ -712,7 +720,7 @@ int32_t sd_filesystem(void* p) {
|
|||||||
case SdAppStateFileSelect: {
|
case SdAppStateFileSelect: {
|
||||||
SdAppFileSelectResultEvent retval = {.result = false};
|
SdAppFileSelectResultEvent retval = {.result = false};
|
||||||
furi_check(
|
furi_check(
|
||||||
osMessageQueuePut(event.result_receiver, &retval, 0, osWaitForever) ==
|
osMessageQueuePut(sd_app->result_receiver, &retval, 0, osWaitForever) ==
|
||||||
osOK);
|
osOK);
|
||||||
app_reset_state(sd_app);
|
app_reset_state(sd_app);
|
||||||
}; break;
|
}; break;
|
||||||
@ -799,8 +807,12 @@ int32_t sd_filesystem(void* p) {
|
|||||||
break;
|
break;
|
||||||
case SdAppEventTypeFileSelect:
|
case SdAppEventTypeFileSelect:
|
||||||
if(!app_sd_make_path(event.payload.file_select_data.path)) {
|
if(!app_sd_make_path(event.payload.file_select_data.path)) {
|
||||||
|
SdAppFileSelectResultEvent retval = {.result = false};
|
||||||
|
furi_check(
|
||||||
|
osMessageQueuePut(sd_app->result_receiver, &retval, 0, osWaitForever) ==
|
||||||
|
osOK);
|
||||||
|
app_reset_state(sd_app);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(try_to_alloc_view_holder(sd_app, gui)) {
|
if(try_to_alloc_view_holder(sd_app, gui)) {
|
||||||
sd_app->result_receiver = event.result_receiver;
|
sd_app->result_receiver = event.result_receiver;
|
||||||
FileSelect* file_select = alloc_and_attach_file_select(sd_app);
|
FileSelect* file_select = alloc_and_attach_file_select(sd_app);
|
||||||
@ -814,8 +826,15 @@ int32_t sd_filesystem(void* p) {
|
|||||||
event.payload.file_select_data.result,
|
event.payload.file_select_data.result,
|
||||||
event.payload.file_select_data.result_size);
|
event.payload.file_select_data.result_size);
|
||||||
if(!file_select_init(file_select)) {
|
if(!file_select_init(file_select)) {
|
||||||
}
|
SdAppFileSelectResultEvent retval = {.result = false};
|
||||||
|
furi_check(
|
||||||
|
osMessageQueuePut(
|
||||||
|
sd_app->result_receiver, &retval, 0, osWaitForever) == osOK);
|
||||||
|
app_reset_state(sd_app);
|
||||||
|
} else {
|
||||||
sd_app->sd_app_state = SdAppStateFileSelect;
|
sd_app->sd_app_state = SdAppStateFileSelect;
|
||||||
|
view_holder_start(sd_app->view_holder);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
SdAppFileSelectResultEvent retval = {.result = false};
|
SdAppFileSelectResultEvent retval = {.result = false};
|
||||||
furi_check(
|
furi_check(
|
||||||
|
Loading…
Reference in New Issue
Block a user