emulation.c 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. #include "nfc_playlist.h"
  2. #include "scences/emulation.h"
  3. bool hiding_error = false;
  4. NfcPlaylistEmulationState EmulationState = NfcPlaylistEmulationState_Stopped;
  5. void nfc_playlist_emulation_scene_on_enter(void* context) {
  6. NfcPlaylist* nfc_playlist = context;
  7. nfc_playlist_emulation_setup(nfc_playlist);
  8. nfc_playlist_emulation_start(nfc_playlist);
  9. }
  10. bool nfc_playlist_emulation_scene_on_event(void* context, SceneManagerEvent event) {
  11. UNUSED(context);
  12. if (event.event == 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
  13. EmulationState = NfcPlaylistEmulationState_Canceled;
  14. return true;
  15. }
  16. return false;
  17. }
  18. void nfc_playlist_emulation_scene_on_exit(void* context) {
  19. NfcPlaylist* nfc_playlist = context;
  20. EmulationState = NfcPlaylistEmulationState_Stopped;
  21. nfc_playlist_emulation_stop(nfc_playlist);
  22. nfc_playlist_emulation_free(nfc_playlist);
  23. popup_reset(nfc_playlist->popup);
  24. }
  25. void nfc_playlist_emulation_setup(void* context) {
  26. NfcPlaylist* nfc_playlist = context;
  27. nfc_playlist->thread = furi_thread_alloc_ex("NfcPlaylistEmulationWorker", 8192, nfc_playlist_emulation_task, nfc_playlist);
  28. nfc_playlist->nfc_playlist_worker = nfc_playlist_worker_alloc();
  29. }
  30. void nfc_playlist_emulation_free(NfcPlaylist* nfc_playlist) {
  31. furi_assert(nfc_playlist);
  32. furi_thread_free(nfc_playlist->thread);
  33. nfc_playlist_worker_free(nfc_playlist->nfc_playlist_worker);
  34. nfc_playlist->thread = NULL;
  35. nfc_playlist->nfc_playlist_worker = NULL;
  36. }
  37. void nfc_playlist_emulation_start(NfcPlaylist* nfc_playlist) {
  38. furi_assert(nfc_playlist);
  39. furi_thread_start(nfc_playlist->thread);
  40. }
  41. void nfc_playlist_emulation_stop(NfcPlaylist* nfc_playlist) {
  42. furi_assert(nfc_playlist);
  43. furi_thread_join(nfc_playlist->thread);
  44. }
  45. int32_t nfc_playlist_emulation_task(void* context) {
  46. NfcPlaylist* nfc_playlist = context;
  47. Storage* storage = furi_record_open(RECORD_STORAGE);
  48. Stream* stream = file_stream_alloc(storage);
  49. FuriString* line = furi_string_alloc();
  50. popup_reset(nfc_playlist->popup);
  51. popup_set_context(nfc_playlist->popup, nfc_playlist);
  52. view_dispatcher_switch_to_view(nfc_playlist->view_dispatcher, NfcPlaylistView_Popup);
  53. if (file_stream_open(stream, furi_string_get_cstr(nfc_playlist->settings.file_path), FSAM_READ, FSOM_OPEN_EXISTING) && nfc_playlist->settings.file_selected_check) {
  54. EmulationState = NfcPlaylistEmulationState_Emulating;
  55. int file_position = 0;
  56. while(stream_read_line(stream, line) && EmulationState == NfcPlaylistEmulationState_Emulating) {
  57. char* file_path = (char*)furi_string_get_cstr(line);
  58. if (strlen(file_path) <= 1) {continue;}
  59. if (nfc_playlist->settings.emulate_delay > 0 && file_position > 0 && !hiding_error) {
  60. popup_set_header(nfc_playlist->popup, "Delaying", 64, 10, AlignCenter, AlignTop);
  61. start_blink(nfc_playlist, NfcPlaylistLedState_Error);
  62. int time_counter_delay_ms = (options_emulate_delay[nfc_playlist->settings.emulate_delay]*1000);
  63. do {
  64. char display_text[10];
  65. snprintf(display_text, 10, "%ds", (time_counter_delay_ms/1000));
  66. popup_set_text(nfc_playlist->popup, display_text, 64, 50, AlignCenter, AlignTop);
  67. furi_delay_ms(50);
  68. time_counter_delay_ms -= 50;
  69. } while(time_counter_delay_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating);
  70. } else if (nfc_playlist->settings.emulate_delay > 0) {
  71. file_position++;
  72. }
  73. if (hiding_error) {hiding_error = false;}
  74. if (EmulationState != NfcPlaylistEmulationState_Emulating) {break;}
  75. char const* full_file_name = strchr(file_path, '/') != NULL ? &strrchr(file_path, '/')[1] : file_path;
  76. char file_name[sizeof(full_file_name)];
  77. strcpy(file_name, full_file_name);
  78. strtok(file_name, ".");
  79. char const* file_ext = &strrchr(file_path, '.')[1];
  80. int time_counter_ms = (options_emulate_timeout[nfc_playlist->settings.emulate_timeout]*1000);
  81. if (storage_file_exists(storage, file_path) == false) {
  82. if (nfc_playlist->settings.hide_error) {
  83. hiding_error = true;
  84. continue;
  85. }
  86. int popup_header_text_size = strlen(file_name) + 18;
  87. char popup_header_text[popup_header_text_size];
  88. snprintf(popup_header_text, popup_header_text_size, "%s\n%s", "ERROR not found:", file_name);
  89. popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
  90. start_blink(nfc_playlist, NfcPlaylistLedState_Error);
  91. while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
  92. char popup_text[9];
  93. snprintf(popup_text, 9, "%ds", (time_counter_ms/1000));
  94. popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
  95. furi_delay_ms(50);
  96. time_counter_ms -= 50;
  97. }
  98. } else if (strcasestr(file_ext, "nfc") == NULL) {
  99. if (nfc_playlist->settings.hide_error) {
  100. hiding_error = true;
  101. continue;
  102. }
  103. int popup_header_text_size = strlen(file_name) + 21;
  104. char popup_header_text[popup_header_text_size];
  105. snprintf(popup_header_text, popup_header_text_size, "%s\n%s", "ERROR invalid file:", file_name);
  106. popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
  107. start_blink(nfc_playlist, NfcPlaylistLedState_Error);
  108. while(time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
  109. char popup_text[9];
  110. snprintf(popup_text, 9, "%ds", (time_counter_ms/1000));
  111. popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
  112. furi_delay_ms(50);
  113. time_counter_ms -= 50;
  114. }
  115. } else {
  116. int popup_header_text_size = strlen(file_name) + 12;
  117. char popup_header_text[popup_header_text_size];
  118. snprintf(popup_header_text, popup_header_text_size, "%s\n%s", "Emulating:", file_name);
  119. popup_set_header(nfc_playlist->popup, popup_header_text, 64, 10, AlignCenter, AlignTop);
  120. nfc_playlist_worker_set_nfc_data(nfc_playlist->nfc_playlist_worker, file_path);
  121. nfc_playlist_worker_start(nfc_playlist->nfc_playlist_worker);
  122. start_blink(nfc_playlist, NfcPlaylistLedState_Normal);
  123. while(nfc_playlist_worker_is_emulating(nfc_playlist->nfc_playlist_worker) && time_counter_ms > 0 && EmulationState == NfcPlaylistEmulationState_Emulating) {
  124. char popup_text[9];
  125. snprintf(popup_text, 9, "%ds", (time_counter_ms/1000));
  126. popup_set_text(nfc_playlist->popup, popup_text, 64, 50, AlignCenter, AlignTop);
  127. furi_delay_ms(50);
  128. time_counter_ms -= 50;
  129. }
  130. nfc_playlist_worker_stop(nfc_playlist->nfc_playlist_worker);
  131. }
  132. }
  133. popup_reset(nfc_playlist->popup);
  134. popup_set_header(nfc_playlist->popup, EmulationState == NfcPlaylistEmulationState_Canceled ? "Emulation stopped" : "Emulation finished", 64, 10, AlignCenter, AlignTop);
  135. popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop);
  136. stop_blink(nfc_playlist);
  137. EmulationState = NfcPlaylistEmulationState_Stopped;
  138. } else {
  139. popup_set_header(nfc_playlist->popup, "Failed to open playlist", 64, 10, AlignCenter, AlignTop);
  140. popup_set_text(nfc_playlist->popup, "Press back", 64, 50, AlignCenter, AlignTop);
  141. }
  142. furi_string_free(line);
  143. file_stream_close(stream);
  144. furi_record_close(RECORD_STORAGE);
  145. stream_free(stream);
  146. return 0;
  147. }