[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 | ||||
| 
 | ||||
| #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 | ||||
| 
 | ||||
| #ifdef BUILD_GPIO_DEMO | ||||
|  | ||||
| @ -96,6 +96,9 @@ static bool file_select_input_callback(InputEvent* event, void* context) { | ||||
|                     return true; | ||||
|                 }); | ||||
|             consumed = true; | ||||
|             if(!file_select_fill_strings(file_select)) { | ||||
|                 file_select->callback(false, file_select->context); | ||||
|             } | ||||
|         } else if(event->key == InputKeyDown) { | ||||
|             with_view_model( | ||||
|                 file_select->view, (FileSelectModel * model) { | ||||
| @ -121,6 +124,9 @@ static bool file_select_input_callback(InputEvent* event, void* context) { | ||||
|                     return true; | ||||
|                 }); | ||||
|             consumed = true; | ||||
|             if(!file_select_fill_strings(file_select)) { | ||||
|                 file_select->callback(false, file_select->context); | ||||
|             } | ||||
|         } else if(event->key == InputKeyOk) { | ||||
|             if(file_select->callback != NULL) { | ||||
|                 const char* result; | ||||
| @ -138,10 +144,6 @@ static bool file_select_input_callback(InputEvent* event, void* context) { | ||||
|             } | ||||
|             consumed = true; | ||||
|         } | ||||
| 
 | ||||
|         if(!file_select_fill_strings(file_select)) { | ||||
|             file_select->callback(false, file_select->context); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     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) { | ||||
|     file_select->context = context; | ||||
|     file_select->callback = callback; | ||||
| } | ||||
| 
 | ||||
| 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(); | ||||
| 
 | ||||
|     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
 | ||||
|     srand(DWT->CYCCNT); | ||||
| } | ||||
| 
 | ||||
| iButtonApp::~iButtonApp() { | ||||
|     furi_record_close("sdcard-ex"); | ||||
|     furi_record_close("sdcard"); | ||||
|     api_hal_power_insomnia_exit(); | ||||
| } | ||||
| 
 | ||||
| @ -107,6 +111,22 @@ iButtonKey* iButtonApp::get_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() { | ||||
|     // TODO open record
 | ||||
|     const GpioPin* vibro_record = &vibro_gpio; | ||||
| @ -193,18 +213,6 @@ uint8_t iButtonApp::get_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) { | ||||
|     const uint8_t prefix_size = 9; | ||||
|     const char* prefix[prefix_size] = { | ||||
|  | ||||
| @ -12,7 +12,6 @@ | ||||
| #include "scene/ibutton-scene-readed-key-menu.h" | ||||
| #include "scene/ibutton-scene-write.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-delete-confirm.h" | ||||
| #include "scene/ibutton-scene-delete-success.h" | ||||
| @ -23,9 +22,11 @@ | ||||
| #include "scene/ibutton-scene-add-type.h" | ||||
| #include "scene/ibutton-scene-add-value.h" | ||||
| 
 | ||||
| #include "helpers/key-store.h" | ||||
| #include "helpers/key-worker.h" | ||||
| 
 | ||||
| #include <sd-card-api.h> | ||||
| #include <filesystem-api.h> | ||||
| 
 | ||||
| #include "one_wire_master.h" | ||||
| #include "maxim_crc.h" | ||||
| #include "ibutton-key.h" | ||||
| @ -48,7 +49,6 @@ public: | ||||
|         SceneWrite, | ||||
|         SceneWriteSuccess, | ||||
|         SceneEmulate, | ||||
|         SceneSavedList, | ||||
|         SceneSavedKeyMenu, | ||||
|         SceneDeleteConfirm, | ||||
|         SceneDeleteSuccess, | ||||
| @ -88,9 +88,10 @@ public: | ||||
|     char* get_text_store(); | ||||
|     uint8_t get_text_store_size(); | ||||
| 
 | ||||
|     KeyStore* get_key_store(); | ||||
|     uint8_t get_stored_key_index(); | ||||
|     void set_stored_key_index(uint8_t index); | ||||
|     SdCard_Api* get_sd_ex_api(); | ||||
|     FS_Api* get_fs_api(); | ||||
|     char* get_file_name(); | ||||
|     uint8_t get_file_name_size(); | ||||
| 
 | ||||
|     void generate_random_name(char* name, uint8_t max_name_size); | ||||
| 
 | ||||
| @ -109,7 +110,6 @@ private: | ||||
|         {Scene::SceneWrite, new iButtonSceneWrite()}, | ||||
|         {Scene::SceneWriteSuccess, new iButtonSceneWriteSuccess()}, | ||||
|         {Scene::SceneEmulate, new iButtonSceneEmulate()}, | ||||
|         {Scene::SceneSavedList, new iButtonSceneSavedList()}, | ||||
|         {Scene::SceneSavedKeyMenu, new iButtonSceneSavedKeyMenu()}, | ||||
|         {Scene::SceneDeleteConfirm, new iButtonSceneDeleteConfirm()}, | ||||
|         {Scene::SceneDeleteSuccess, new iButtonSceneDeleteSuccess()}, | ||||
| @ -123,12 +123,14 @@ private: | ||||
|     KeyWorker* key_worker; | ||||
| 
 | ||||
|     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; | ||||
|     char text_store[text_store_size + 1]; | ||||
| 
 | ||||
|     KeyStore store; | ||||
| 
 | ||||
|     void notify_init(); | ||||
| }; | ||||
| @ -51,28 +51,5 @@ iButtonKeyType iButtonKey::get_key_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() { | ||||
| } | ||||
|  | ||||
| @ -16,19 +16,6 @@ public: | ||||
|     void set_type(iButtonKeyType 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(); | ||||
| 
 | ||||
| private: | ||||
|  | ||||
| @ -55,10 +55,19 @@ bool iButtonSceneDeleteConfirm::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeDialogResult) { | ||||
|         if(event->payload.dialog_result == DialogExResultRight) { | ||||
|             KeyStore* store = app->get_key_store(); | ||||
|             store->remove_key(app->get_stored_key_index()); | ||||
| 
 | ||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteSuccess); | ||||
|             iButtonKey* key = app->get_key(); | ||||
|             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); | ||||
|             } else { | ||||
|                 // TODO error file path
 | ||||
|                 // app->switch_to_next_scene(iButtonApp::Scene::SceneDeleteFail);
 | ||||
|             } | ||||
|         } else { | ||||
|             app->switch_to_previous_scene(); | ||||
|         } | ||||
|  | ||||
| @ -25,7 +25,7 @@ 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::SceneSavedList}); | ||||
|         app->search_and_switch_to_previous_scene({iButtonApp::Scene::SceneStart}); | ||||
|         consumed = true; | ||||
|     } | ||||
| 
 | ||||
|  | ||||
| @ -4,6 +4,7 @@ | ||||
| #include "../ibutton-event.h" | ||||
| #include "../ibutton-key.h" | ||||
| #include <callback-connector.h> | ||||
| #include <filesystem-api.h> | ||||
| 
 | ||||
| void iButtonSceneSaveName::on_enter(iButtonApp* app) { | ||||
|     iButtonAppViewManager* view_manager = app->get_view_manager(); | ||||
| @ -28,14 +29,23 @@ bool iButtonSceneSaveName::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|     bool consumed = false; | ||||
| 
 | ||||
|     if(event->type == iButtonEvent::Type::EventTypeTextEditResult) { | ||||
|         KeyStore* store = app->get_key_store(); | ||||
|         uint8_t key_index = store->add_key(); | ||||
|         iButtonKey* key = app->get_key(); | ||||
| 
 | ||||
|         store->set_key_type(key_index, key->get_key_type()); | ||||
|         store->set_key_name(key_index, app->get_text_store()); | ||||
|         store->set_key_data(key_index, key->get_data(), key->get_size()); | ||||
| 
 | ||||
|         File key_file; | ||||
|         string_t key_file_name; | ||||
|         string_init_set_str(key_file_name, "ibutton/"); | ||||
|         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); | ||||
|         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-event.h" | ||||
| #include <callback-connector.h> | ||||
| #include <filesystem-api.h> | ||||
| 
 | ||||
| typedef enum { | ||||
|     SubmenuIndexRead, | ||||
| @ -30,9 +31,40 @@ bool iButtonSceneStart::on_event(iButtonApp* app, iButtonEvent* event) { | ||||
|         case SubmenuIndexRead: | ||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneRead); | ||||
|             break; | ||||
|         case SubmenuIndexSaved: | ||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneSavedList); | ||||
|             break; | ||||
|         case SubmenuIndexSaved: { | ||||
|             bool res = app->get_sd_ex_api()->file_select( | ||||
|                 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: | ||||
|             app->switch_to_next_scene(iButtonApp::Scene::SceneAddType); | ||||
|             break; | ||||
|  | ||||
| @ -325,7 +325,7 @@ bool app_sd_make_path(const char* path) { | ||||
| 
 | ||||
|     if(*path) { | ||||
|         char* file_path = strdup(path); | ||||
| 
 | ||||
|         // Make parent directories
 | ||||
|         for(char* p = strchr(file_path + 1, '/'); p; p = strchr(p + 1, '/')) { | ||||
|             *p = '\0'; | ||||
|             SDError result = f_mkdir(file_path); | ||||
| @ -339,6 +339,14 @@ bool app_sd_make_path(const char* path) { | ||||
|             } | ||||
|             *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); | ||||
|     } | ||||
| @ -393,7 +401,7 @@ bool sd_api_file_select( | ||||
|     SdAppFileSelectResultEvent event; | ||||
|     while(1) { | ||||
|         osStatus_t event_status = | ||||
|             osMessageQueueGet(sd_app->event_queue, &event, NULL, osWaitForever); | ||||
|             osMessageQueueGet(return_event_queue, &event, NULL, osWaitForever); | ||||
|         if(event_status == osOK) { | ||||
|             retval = event.result; | ||||
|             break; | ||||
| @ -697,7 +705,7 @@ int32_t sd_filesystem(void* p) { | ||||
|                 case SdAppStateFileSelect: { | ||||
|                     SdAppFileSelectResultEvent retval = {.result = true}; | ||||
|                     furi_check( | ||||
|                         osMessageQueuePut(event.result_receiver, &retval, 0, osWaitForever) == | ||||
|                         osMessageQueuePut(sd_app->result_receiver, &retval, 0, osWaitForever) == | ||||
|                         osOK); | ||||
|                     app_reset_state(sd_app); | ||||
|                 }; break; | ||||
| @ -712,7 +720,7 @@ int32_t sd_filesystem(void* p) { | ||||
|                 case SdAppStateFileSelect: { | ||||
|                     SdAppFileSelectResultEvent retval = {.result = false}; | ||||
|                     furi_check( | ||||
|                         osMessageQueuePut(event.result_receiver, &retval, 0, osWaitForever) == | ||||
|                         osMessageQueuePut(sd_app->result_receiver, &retval, 0, osWaitForever) == | ||||
|                         osOK); | ||||
|                     app_reset_state(sd_app); | ||||
|                 }; break; | ||||
| @ -799,8 +807,12 @@ int32_t sd_filesystem(void* p) { | ||||
|                 break; | ||||
|             case SdAppEventTypeFileSelect: | ||||
|                 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)) { | ||||
|                     sd_app->result_receiver = event.result_receiver; | ||||
|                     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_size); | ||||
|                     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; | ||||
|                         view_holder_start(sd_app->view_holder); | ||||
|                     } | ||||
|                     sd_app->sd_app_state = SdAppStateFileSelect; | ||||
|                 } else { | ||||
|                     SdAppFileSelectResultEvent retval = {.result = false}; | ||||
|                     furi_check( | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 gornekich
						gornekich