passy.c 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292
  1. #include "passy_i.h"
  2. #define TAG "Passy"
  3. #define PASSY_MRZ_INFO_FILENAME "mrz_info"
  4. bool passy_load_mrz_info(Passy* passy) {
  5. const char* file_header = "MRZ Info";
  6. const uint32_t file_version = 1;
  7. bool parsed = false;
  8. FlipperFormat* file = flipper_format_file_alloc(passy->storage);
  9. FuriString* path = furi_string_alloc();
  10. FuriString* temp_str = furi_string_alloc();
  11. uint32_t version = 0;
  12. do {
  13. furi_string_printf(
  14. path, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, PASSY_MRZ_INFO_FILENAME, ".txt");
  15. // Open file
  16. if(!flipper_format_file_open_existing(file, furi_string_get_cstr(path))) break;
  17. if(!flipper_format_read_header(file, temp_str, &version)) break;
  18. if(!furi_string_equal_str(temp_str, file_header) || (version != file_version)) {
  19. break;
  20. }
  21. // passport number
  22. // dob
  23. // doe
  24. if(!flipper_format_read_string(file, "Passport Number", temp_str)) break;
  25. strncpy(
  26. passy->passport_number,
  27. furi_string_get_cstr(temp_str),
  28. PASSY_PASSPORT_NUMBER_MAX_LENGTH);
  29. if(!flipper_format_read_string(file, "Date of Birth", temp_str)) break;
  30. strncpy(passy->date_of_birth, furi_string_get_cstr(temp_str), PASSY_DOB_MAX_LENGTH);
  31. if(!flipper_format_read_string(file, "Date of Expiry", temp_str)) break;
  32. strncpy(passy->date_of_expiry, furi_string_get_cstr(temp_str), PASSY_DOE_MAX_LENGTH);
  33. parsed = true;
  34. } while(false);
  35. if(parsed) {
  36. FURI_LOG_I(TAG, "MRZ Info loaded");
  37. }
  38. furi_string_free(path);
  39. furi_string_free(temp_str);
  40. flipper_format_free(file);
  41. return parsed;
  42. }
  43. bool passy_save_mrz_info(Passy* passy) {
  44. bool saved = false;
  45. const char* file_header = "MRZ Info";
  46. const uint32_t file_version = 1;
  47. FlipperFormat* file = flipper_format_file_alloc(passy->storage);
  48. FuriString* temp_str = furi_string_alloc();
  49. do {
  50. furi_string_printf(
  51. temp_str, "%s/%s%s", STORAGE_APP_DATA_PATH_PREFIX, PASSY_MRZ_INFO_FILENAME, ".txt");
  52. // Open file
  53. if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) break;
  54. // Write header
  55. if(!flipper_format_write_header_cstr(file, file_header, file_version)) break;
  56. furi_string_set_str(temp_str, passy->passport_number);
  57. if(!flipper_format_write_string(file, "Passport Number", temp_str)) break;
  58. furi_string_set_str(temp_str, passy->date_of_birth);
  59. if(!flipper_format_write_string(file, "Date of Birth", temp_str)) break;
  60. furi_string_set_str(temp_str, passy->date_of_expiry);
  61. if(!flipper_format_write_string(file, "Date of Expiry", temp_str)) break;
  62. saved = true;
  63. } while(false);
  64. furi_string_free(temp_str);
  65. flipper_format_free(file);
  66. return saved;
  67. }
  68. bool passy_custom_event_callback(void* context, uint32_t event) {
  69. furi_assert(context);
  70. Passy* passy = context;
  71. return scene_manager_handle_custom_event(passy->scene_manager, event);
  72. }
  73. bool passy_back_event_callback(void* context) {
  74. furi_assert(context);
  75. Passy* passy = context;
  76. return scene_manager_handle_back_event(passy->scene_manager);
  77. }
  78. void passy_tick_event_callback(void* context) {
  79. furi_assert(context);
  80. Passy* passy = context;
  81. scene_manager_handle_tick_event(passy->scene_manager);
  82. }
  83. Passy* passy_alloc() {
  84. Passy* passy = malloc(sizeof(Passy));
  85. passy->view_dispatcher = view_dispatcher_alloc();
  86. passy->scene_manager = scene_manager_alloc(&passy_scene_handlers, passy);
  87. view_dispatcher_set_event_callback_context(passy->view_dispatcher, passy);
  88. view_dispatcher_set_custom_event_callback(passy->view_dispatcher, passy_custom_event_callback);
  89. view_dispatcher_set_navigation_event_callback(
  90. passy->view_dispatcher, passy_back_event_callback);
  91. view_dispatcher_set_tick_event_callback(
  92. passy->view_dispatcher, passy_tick_event_callback, 100);
  93. passy->nfc = nfc_alloc();
  94. // Nfc device
  95. passy->nfc_device = nfc_device_alloc();
  96. nfc_device_set_loading_callback(passy->nfc_device, passy_show_loading_popup, passy);
  97. // Open GUI record
  98. passy->gui = furi_record_open(RECORD_GUI);
  99. view_dispatcher_attach_to_gui(
  100. passy->view_dispatcher, passy->gui, ViewDispatcherTypeFullscreen);
  101. // Open Notification record
  102. passy->notifications = furi_record_open(RECORD_NOTIFICATION);
  103. // Submenu
  104. passy->submenu = submenu_alloc();
  105. view_dispatcher_add_view(
  106. passy->view_dispatcher, PassyViewMenu, submenu_get_view(passy->submenu));
  107. // Popup
  108. passy->popup = popup_alloc();
  109. view_dispatcher_add_view(passy->view_dispatcher, PassyViewPopup, popup_get_view(passy->popup));
  110. // Loading
  111. passy->loading = loading_alloc();
  112. view_dispatcher_add_view(
  113. passy->view_dispatcher, PassyViewLoading, loading_get_view(passy->loading));
  114. // Text Input
  115. passy->text_input = text_input_alloc();
  116. view_dispatcher_add_view(
  117. passy->view_dispatcher, PassyViewTextInput, text_input_get_view(passy->text_input));
  118. // Number Input
  119. passy->number_input = number_input_alloc();
  120. view_dispatcher_add_view(
  121. passy->view_dispatcher, PassyViewNumberInput, number_input_get_view(passy->number_input));
  122. // TextBox
  123. passy->text_box = text_box_alloc();
  124. view_dispatcher_add_view(
  125. passy->view_dispatcher, PassyViewTextBox, text_box_get_view(passy->text_box));
  126. passy->text_box_store = furi_string_alloc();
  127. // Custom Widget
  128. passy->widget = widget_alloc();
  129. view_dispatcher_add_view(
  130. passy->view_dispatcher, PassyViewWidget, widget_get_view(passy->widget));
  131. passy->storage = furi_record_open(RECORD_STORAGE);
  132. passy->dialogs = furi_record_open(RECORD_DIALOGS);
  133. passy->load_path = furi_string_alloc();
  134. passy->DG1 = bit_buffer_alloc(PASSY_DG1_MAX_LENGTH);
  135. return passy;
  136. }
  137. void passy_free(Passy* passy) {
  138. furi_assert(passy);
  139. nfc_free(passy->nfc);
  140. // Nfc device
  141. nfc_device_free(passy->nfc_device);
  142. // Submenu
  143. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewMenu);
  144. submenu_free(passy->submenu);
  145. // Popup
  146. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewPopup);
  147. popup_free(passy->popup);
  148. // Loading
  149. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewLoading);
  150. loading_free(passy->loading);
  151. // TextInput
  152. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewTextInput);
  153. text_input_free(passy->text_input);
  154. // NumberInput
  155. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewNumberInput);
  156. number_input_free(passy->number_input);
  157. // TextBox
  158. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewTextBox);
  159. text_box_free(passy->text_box);
  160. furi_string_free(passy->text_box_store);
  161. // Custom Widget
  162. view_dispatcher_remove_view(passy->view_dispatcher, PassyViewWidget);
  163. widget_free(passy->widget);
  164. // View Dispatcher
  165. view_dispatcher_free(passy->view_dispatcher);
  166. // Scene Manager
  167. scene_manager_free(passy->scene_manager);
  168. // GUI
  169. furi_record_close(RECORD_GUI);
  170. passy->gui = NULL;
  171. // Notifications
  172. furi_record_close(RECORD_NOTIFICATION);
  173. passy->notifications = NULL;
  174. furi_string_free(passy->load_path);
  175. furi_record_close(RECORD_STORAGE);
  176. furi_record_close(RECORD_DIALOGS);
  177. bit_buffer_free(passy->DG1);
  178. free(passy);
  179. }
  180. void passy_text_store_set(Passy* passy, const char* text, ...) {
  181. va_list args;
  182. va_start(args, text);
  183. vsnprintf(passy->text_store, sizeof(passy->text_store), text, args);
  184. va_end(args);
  185. }
  186. void passy_text_store_clear(Passy* passy) {
  187. memset(passy->text_store, 0, sizeof(passy->text_store));
  188. }
  189. static const NotificationSequence passy_sequence_blink_start_blue = {
  190. &message_blink_start_10,
  191. &message_blink_set_color_blue,
  192. &message_do_not_reset,
  193. NULL,
  194. };
  195. static const NotificationSequence passy_sequence_blink_stop = {
  196. &message_blink_stop,
  197. NULL,
  198. };
  199. void passy_blink_start(Passy* passy) {
  200. notification_message(passy->notifications, &passy_sequence_blink_start_blue);
  201. }
  202. void passy_blink_stop(Passy* passy) {
  203. notification_message(passy->notifications, &passy_sequence_blink_stop);
  204. }
  205. void passy_show_loading_popup(void* context, bool show) {
  206. Passy* passy = context;
  207. if(show) {
  208. // Raise timer priority so that animations can play
  209. furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
  210. view_dispatcher_switch_to_view(passy->view_dispatcher, PassyViewLoading);
  211. } else {
  212. // Restore default timer priority
  213. furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
  214. }
  215. }
  216. int32_t passy_app(void* p) {
  217. UNUSED(p);
  218. Passy* passy = passy_alloc();
  219. passy_load_mrz_info(passy);
  220. scene_manager_next_scene(passy->scene_manager, PassySceneMainMenu);
  221. view_dispatcher_run(passy->view_dispatcher);
  222. passy_free(passy);
  223. return 0;
  224. }