metroflip_scene_load.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include "../metroflip_i.h"
  2. #include <dolphin/dolphin.h>
  3. #include <furi.h>
  4. #include <bit_lib.h>
  5. #include <lib/nfc/protocols/nfc_protocol.h>
  6. #include "../api/metroflip/metroflip_api.h"
  7. #include "../api/suica/suica_loading.h"
  8. #define TAG "Metroflip:Scene:Load"
  9. #include "keys.h"
  10. #include <nfc/protocols/mf_classic/mf_classic.h>
  11. void metroflip_scene_load_on_enter(void* context) {
  12. Metroflip* app = (Metroflip*)context;
  13. // We initialized this to be false every time we enter
  14. app->data_loaded = false;
  15. bool has_card_type = false;
  16. // The same string we will use to direct parse scene which plugin to call
  17. // Extracted from the file
  18. FuriString* card_type_str = furi_string_alloc();
  19. FuriString* device_type = furi_string_alloc();
  20. // All the app_data browser stuff. Don't worry about this
  21. DialogsFileBrowserOptions browser_options;
  22. Storage* storage = furi_record_open(RECORD_STORAGE);
  23. storage_simply_mkdir(storage, STORAGE_APP_DATA_PATH_PREFIX);
  24. dialog_file_browser_set_basic_options(&browser_options, METROFLIP_FILE_EXTENSION, &I_icon);
  25. browser_options.base_path = STORAGE_APP_DATA_PATH_PREFIX;
  26. FuriString* file_path = furi_string_alloc_set(browser_options.base_path);
  27. if(dialog_file_browser_show(app->dialogs, file_path, file_path, &browser_options)) {
  28. FlipperFormat* format = flipper_format_file_alloc(storage);
  29. do {
  30. if(!flipper_format_file_open_existing(format, furi_string_get_cstr(file_path))) break;
  31. if(!flipper_format_read_string(format, "Device type", device_type)) break;
  32. const char* protocol_name = furi_string_get_cstr(device_type);
  33. if(!flipper_format_read_string(format, "Card Type", card_type_str)) {
  34. flipper_format_file_close(format);
  35. flipper_format_file_open_existing(format, furi_string_get_cstr(file_path));
  36. if(strcmp(protocol_name, "Mifare Classic") == 0) {
  37. MfClassicData* mfc_data = mf_classic_alloc();
  38. if(!mf_classic_load(mfc_data, format, 2)) break;
  39. app->data_loaded = true;
  40. CardType card_type = determine_card_type(app->nfc, mfc_data, app->data_loaded);
  41. app->mfc_card_type = card_type;
  42. has_card_type = true;
  43. switch(card_type) {
  44. case CARD_TYPE_METROMONEY:
  45. app->card_type = "metromoney";
  46. FURI_LOG_I(TAG, "Detected: Metromoney\n");
  47. break;
  48. case CARD_TYPE_CHARLIECARD:
  49. app->card_type = "charliecard";
  50. FURI_LOG_I(TAG, "Detected: CharlieCard\n");
  51. break;
  52. case CARD_TYPE_SMARTRIDER:
  53. app->card_type = "smartrider";
  54. FURI_LOG_I(TAG, "Detected: SmartRider\n");
  55. break;
  56. case CARD_TYPE_TROIKA:
  57. app->card_type = "troika";
  58. FURI_LOG_I(TAG, "Detected: Troika\n");
  59. break;
  60. case CARD_TYPE_GOCARD:
  61. app->card_type = "gocard";
  62. FURI_LOG_I(TAG, "Detected: go card\n");
  63. break;
  64. case CARD_TYPE_UNKNOWN:
  65. app->card_type = "unknown";
  66. //popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  67. break;
  68. default:
  69. app->card_type = "unknown";
  70. FURI_LOG_I(TAG, "Detected: Unknown card type\n");
  71. //popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  72. break;
  73. }
  74. mf_classic_free(mfc_data);
  75. } else if(strcmp(protocol_name, "Mifare DESFire") == 0) {
  76. MfDesfireData* data = mf_desfire_alloc();
  77. if(!mf_desfire_load(data, format, 2)) break;
  78. app->data_loaded = true;
  79. if(clipper_verify(data)) {
  80. app->card_type = "clipper";
  81. FURI_LOG_I(TAG, "Detected: Clipper");
  82. } else if(itso_verify(data)) {
  83. app->card_type = "itso";
  84. FURI_LOG_I(TAG, "Detected: ITSO");
  85. } else if(myki_verify(data)) {
  86. app->card_type = "myki";
  87. FURI_LOG_I(TAG, "Detected: Myki");
  88. } else if(opal_verify(data)) {
  89. app->card_type = "opal";
  90. FURI_LOG_I(TAG, "Detected: Opal");
  91. } else {
  92. app->card_type = "unknown";
  93. FURI_LOG_I(TAG, "Detected: none");
  94. }
  95. mf_desfire_free(data);
  96. has_card_type = true;
  97. } else {
  98. has_card_type = true;
  99. }
  100. flipper_format_file_close(format);
  101. } else {
  102. has_card_type = false;
  103. if(furi_string_equal_str(card_type_str, "suica")) {
  104. FURI_LOG_I(TAG, "Detected: Suica");
  105. app->data_loaded = true;
  106. app->card_type = "suica";
  107. load_suica_data(app, format);
  108. }
  109. }
  110. app->file_path = furi_string_get_cstr(file_path);
  111. strncpy(
  112. app->delete_file_path,
  113. furi_string_get_cstr(file_path),
  114. sizeof(app->delete_file_path) - 1);
  115. app->delete_file_path[sizeof(app->delete_file_path) - 1] = '\0';
  116. app->data_loaded = true;
  117. } while(0);
  118. flipper_format_free(format);
  119. }
  120. if(app->data_loaded) {
  121. // Direct to the parsing screen just like the auto scene does
  122. if(!has_card_type) {
  123. app->card_type = furi_string_get_cstr(card_type_str);
  124. has_card_type = false;
  125. }
  126. scene_manager_search_and_switch_to_previous_scene(app->scene_manager, MetroflipSceneStart);
  127. scene_manager_next_scene(app->scene_manager, MetroflipSceneParse);
  128. } else {
  129. scene_manager_search_and_switch_to_previous_scene(app->scene_manager, MetroflipSceneStart);
  130. }
  131. furi_string_free(file_path);
  132. furi_string_free(card_type_str);
  133. furi_record_close(RECORD_STORAGE);
  134. }
  135. bool metroflip_scene_load_on_event(void* context, SceneManagerEvent event) {
  136. Metroflip* app = context;
  137. UNUSED(event);
  138. bool consumed = false;
  139. // If they don't select any file in the brwoser and press back button,
  140. // the data is not loaded
  141. if(!app->data_loaded) {
  142. scene_manager_search_and_switch_to_previous_scene(app->scene_manager, MetroflipSceneStart);
  143. }
  144. consumed = true;
  145. return consumed;
  146. }
  147. void metroflip_scene_load_on_exit(void* context) {
  148. Metroflip* app = context;
  149. UNUSED(app);
  150. }