emulation.c 7.2 KB

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