vb_migrate.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331
  1. // SPDX-License-Identifier: GPL-3.0-or-later
  2. //
  3. // VB Lab Migration Assistant for Flipper Zero
  4. // Copyright (C) 2022 cyanic
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License, or
  9. // (at your option) any later version.
  10. //
  11. // This program is distributed in the hope that it will be useful,
  12. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. // GNU General Public License for more details.
  15. //
  16. // You should have received a copy of the GNU General Public License
  17. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  18. #include <notification/notification_messages.h>
  19. #include "vb_migrate_i.h"
  20. #define TAG "vb_migrate"
  21. bool vb_migrate_custom_event_callback(void* context, uint32_t event) {
  22. furi_assert(context);
  23. VbMigrate* inst = context;
  24. return scene_manager_handle_custom_event(inst->scene_manager, event);
  25. }
  26. bool vb_migrate_back_event_callback(void* context) {
  27. furi_assert(context);
  28. VbMigrate* inst = context;
  29. return scene_manager_handle_back_event(inst->scene_manager);
  30. }
  31. void vb_migrate_blink_read(VbMigrate* inst) {
  32. notification_message(inst->notifications, &sequence_blink_start_cyan);
  33. }
  34. void vb_migrate_blink_emulate(VbMigrate* inst) {
  35. notification_message(inst->notifications, &sequence_blink_start_magenta);
  36. }
  37. void vb_migrate_blink_stop(VbMigrate* inst) {
  38. notification_message_block(inst->notifications, &sequence_blink_stop);
  39. }
  40. void vb_migrate_text_store_set(VbMigrate* inst, const char* text, ...) {
  41. va_list args;
  42. va_start(args, text);
  43. vsnprintf(inst->text_store, sizeof(inst->text_store), text, args);
  44. va_end(args);
  45. }
  46. void vb_migrate_text_store_clear(VbMigrate* inst) {
  47. memset(inst->text_store, 0, sizeof(inst->text_store));
  48. }
  49. bool vb_migrate_save_nfc(VbMigrate* inst, const char* dev_name, const char* file_name) {
  50. bool saved = false;
  51. FuriString* temp_str = furi_string_alloc();
  52. do {
  53. furi_string_printf(temp_str, "%s/%s", VB_MIGRATE_FOLDER, dev_name);
  54. if(!storage_simply_mkdir(inst->storage, furi_string_get_cstr(temp_str))) {
  55. dialog_message_show_storage_error(inst->dialogs, "Can not create\ndata folder");
  56. break;
  57. }
  58. furi_string_cat_printf(temp_str, "/%s", file_name);
  59. inst->nfc_dev->format = NfcDeviceSaveFormatMifareUl;
  60. saved = nfc_device_save(inst->nfc_dev, furi_string_get_cstr(temp_str));
  61. } while(false);
  62. furi_string_free(temp_str);
  63. return saved;
  64. }
  65. bool vb_migrate_load_nfc(VbMigrate* inst, const char* dev_name, const char* file_name) {
  66. bool saved = false;
  67. FuriString* temp_str =
  68. furi_string_alloc_printf("%s/%s/%s", VB_MIGRATE_FOLDER, dev_name, file_name);
  69. saved = nfc_device_load(inst->nfc_dev, furi_string_get_cstr(temp_str), true);
  70. furi_string_free(temp_str);
  71. return saved;
  72. }
  73. bool vb_migrate_delete(VbMigrate* inst, const char* dev_name, bool whole_vb) {
  74. bool deleted = false;
  75. FuriString* dir_path = furi_string_alloc_printf("%s/%s", VB_MIGRATE_FOLDER, dev_name);
  76. if(whole_vb) {
  77. deleted = storage_simply_remove_recursive(inst->storage, furi_string_get_cstr(dir_path));
  78. } else {
  79. File* dir_handle = storage_file_alloc(inst->storage);
  80. if(storage_dir_open(dir_handle, furi_string_get_cstr(dir_path))) {
  81. FileInfo file_info;
  82. char name[256];
  83. FuriString* file_path = furi_string_alloc();
  84. while(storage_dir_read(dir_handle, &file_info, name, sizeof(name))) {
  85. // Files that is .nfc, but is not template
  86. if(!(file_info.flags & FSF_DIRECTORY) && strstr(name, NFC_APP_EXTENSION) &&
  87. !strstr(name, VB_MIGRATE_TEMPLATE_NAME)) {
  88. furi_string_printf(file_path, "%s/%s", furi_string_get_cstr(dir_path), name);
  89. deleted =
  90. storage_simply_remove(inst->storage, furi_string_get_cstr(file_path));
  91. if(!deleted) break;
  92. }
  93. }
  94. furi_string_free(file_path);
  95. storage_dir_close(dir_handle);
  96. }
  97. storage_file_free(dir_handle);
  98. }
  99. furi_string_free(dir_path);
  100. return deleted;
  101. }
  102. int vb_migrate_count_captured_mons(VbMigrate* inst, const char* dev_name) {
  103. int count = 0;
  104. FuriString* dir_path = furi_string_alloc_printf("%s/%s", VB_MIGRATE_FOLDER, dev_name);
  105. File* dir_handle = storage_file_alloc(inst->storage);
  106. if(storage_dir_open(dir_handle, furi_string_get_cstr(dir_path))) {
  107. FileInfo file_info;
  108. char name[256];
  109. while(storage_dir_read(dir_handle, &file_info, name, sizeof(name))) {
  110. // Files that is .nfc, but is not template
  111. if(!(file_info.flags & FSF_DIRECTORY) && strstr(name, NFC_APP_EXTENSION) &&
  112. !strstr(name, VB_MIGRATE_TEMPLATE_NAME))
  113. ++count;
  114. }
  115. storage_dir_close(dir_handle);
  116. }
  117. storage_file_free(dir_handle);
  118. furi_string_free(dir_path);
  119. return count;
  120. }
  121. int vb_migrate_get_next_id(VbMigrate* inst, const char* dev_name, int i, bool is_load) {
  122. FuriString* dir_path = furi_string_alloc_printf("%s/%s", VB_MIGRATE_FOLDER, dev_name);
  123. FuriString* file_path = furi_string_alloc();
  124. while(true) {
  125. furi_string_printf(
  126. file_path,
  127. "%s/" VB_MIGRATE_CAPTURE_FORMAT,
  128. furi_string_get_cstr(dir_path),
  129. i,
  130. NFC_APP_EXTENSION);
  131. bool exit_cond =
  132. storage_common_stat(inst->storage, furi_string_get_cstr(file_path), NULL) ==
  133. FSE_NOT_EXIST;
  134. if(is_load) exit_cond = !exit_cond;
  135. if(exit_cond) break;
  136. ++i;
  137. }
  138. furi_string_free(file_path);
  139. furi_string_free(dir_path);
  140. return i;
  141. }
  142. void vb_migrate_show_loading_popup(VbMigrate* inst, bool show) {
  143. TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
  144. if(show) {
  145. // Raise timer priority so that animations can play
  146. vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
  147. view_dispatcher_switch_to_view(inst->view_dispatcher, VbMigrateViewLoading);
  148. } else {
  149. // Restore default timer priority
  150. vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
  151. }
  152. }
  153. VbMigrate* vb_migrate_alloc() {
  154. VbMigrate* inst = malloc(sizeof(VbMigrate));
  155. inst->view_dispatcher = view_dispatcher_alloc();
  156. inst->scene_manager = scene_manager_alloc(&vb_migrate_scene_handlers, inst);
  157. view_dispatcher_enable_queue(inst->view_dispatcher);
  158. view_dispatcher_set_event_callback_context(inst->view_dispatcher, inst);
  159. view_dispatcher_set_custom_event_callback(
  160. inst->view_dispatcher, vb_migrate_custom_event_callback);
  161. view_dispatcher_set_navigation_event_callback(
  162. inst->view_dispatcher, vb_migrate_back_event_callback);
  163. inst->clear_account_id = false;
  164. // GUI
  165. inst->gui = furi_record_open(RECORD_GUI);
  166. // Storage
  167. inst->storage = furi_record_open(RECORD_STORAGE);
  168. // Notifications service
  169. inst->notifications = furi_record_open(RECORD_NOTIFICATION);
  170. // Dialogs
  171. inst->dialogs = furi_record_open(RECORD_DIALOGS);
  172. // NFC
  173. inst->nfc_dev = nfc_device_alloc();
  174. inst->worker = nfc_worker_alloc();
  175. // Submenu
  176. inst->submenu = submenu_alloc();
  177. view_dispatcher_add_view(
  178. inst->view_dispatcher, VbMigrateViewMenu, submenu_get_view(inst->submenu));
  179. // Popup
  180. inst->popup = popup_alloc();
  181. view_dispatcher_add_view(
  182. inst->view_dispatcher, VbMigrateViewPopup, popup_get_view(inst->popup));
  183. // Widget
  184. inst->widget = widget_alloc();
  185. view_dispatcher_add_view(
  186. inst->view_dispatcher, VbMigrateViewWidget, widget_get_view(inst->widget));
  187. // File select
  188. inst->file_select = file_select_alloc();
  189. view_dispatcher_add_view(
  190. inst->view_dispatcher, VbMigrateViewFileSelect, file_select_get_view(inst->file_select));
  191. // Text input
  192. inst->text_input = text_input_alloc();
  193. view_dispatcher_add_view(
  194. inst->view_dispatcher, VbMigrateViewTextInput, text_input_get_view(inst->text_input));
  195. // Loading
  196. inst->loading = loading_alloc();
  197. view_dispatcher_add_view(
  198. inst->view_dispatcher, VbMigrateViewLoading, loading_get_view(inst->loading));
  199. // Variable item list
  200. inst->variable_list = variable_item_list_ex_alloc();
  201. view_dispatcher_add_view(
  202. inst->view_dispatcher,
  203. VbMigrateViewVariableItemList,
  204. variable_item_list_ex_get_view(inst->variable_list));
  205. // Dialog ex
  206. // inst->dialog_ex = dialog_ex_alloc();
  207. // view_dispatcher_add_view(
  208. // inst->view_dispatcher, VbMigrateViewDialogEx, dialog_ex_get_view(inst->dialog_ex));
  209. return inst;
  210. }
  211. void vb_migrate_free(VbMigrate* inst) {
  212. // Dialog ex
  213. // view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewDialogEx);
  214. // dialog_ex_free(inst->dialog_ex);
  215. // Variable item list
  216. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewVariableItemList);
  217. variable_item_list_ex_free(inst->variable_list);
  218. // Loading
  219. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewLoading);
  220. loading_free(inst->loading);
  221. // Text input
  222. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewTextInput);
  223. text_input_free(inst->text_input);
  224. // File select
  225. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewFileSelect);
  226. file_select_free(inst->file_select);
  227. // Widget
  228. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewWidget);
  229. widget_free(inst->widget);
  230. // Popup
  231. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewPopup);
  232. popup_free(inst->popup);
  233. // Submenu
  234. view_dispatcher_remove_view(inst->view_dispatcher, VbMigrateViewMenu);
  235. submenu_free(inst->submenu);
  236. // NFC
  237. nfc_worker_free(inst->worker);
  238. nfc_device_free(inst->nfc_dev);
  239. furi_record_close(RECORD_DIALOGS);
  240. furi_record_close(RECORD_NOTIFICATION);
  241. furi_record_close(RECORD_STORAGE);
  242. furi_record_close(RECORD_GUI);
  243. view_dispatcher_free(inst->view_dispatcher);
  244. scene_manager_free(inst->scene_manager);
  245. free(inst);
  246. }
  247. int32_t vb_migrate_app(void* p) {
  248. UNUSED(p);
  249. VbMigrate* inst = vb_migrate_alloc();
  250. view_dispatcher_attach_to_gui(inst->view_dispatcher, inst->gui, ViewDispatcherTypeFullscreen);
  251. if(storage_simply_mkdir(inst->storage, VB_MIGRATE_FOLDER)) {
  252. scene_manager_next_scene(inst->scene_manager, VbMigrateSceneMainMenu);
  253. view_dispatcher_run(inst->view_dispatcher);
  254. } else {
  255. dialog_message_show_storage_error(inst->dialogs, "Can not create\napp folder");
  256. }
  257. vb_migrate_free(inst);
  258. return 0;
  259. }
  260. void vb_migrate_add_bg(Widget* widget, VbMigrateBgType type) {
  261. widget_add_icon_element(widget, 0, 0, &I_Background_128x64);
  262. if(type & VbMigrateBgTypeLeftButton) {
  263. widget_add_icon_element(widget, 0, 49, &I_LeftButtonBg_54x15);
  264. }
  265. if(type & VbMigrateBgTypeRightButton) {
  266. widget_add_icon_element(widget, 74, 49, &I_RightButtonBg_54x15);
  267. }
  268. }