seos.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250
  1. #include "seos_i.h"
  2. #define TAG "Seos"
  3. #define SEOS_KEYS_FILENAME "keys"
  4. bool seos_load_keys(Seos* seos) {
  5. const char* file_header = "Seos keys";
  6. const uint32_t file_version = 1;
  7. bool parsed = false;
  8. FlipperFormat* file = flipper_format_file_alloc(seos->credential->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, SEOS_KEYS_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. if(!flipper_format_read_uint32(file, "SEOS_ADF_OID_LEN", (uint32_t*)&SEOS_ADF_OID_LEN, 1))
  22. break;
  23. if(!flipper_format_read_hex(file, "SEOS_ADF_OID", SEOS_ADF_OID, SEOS_ADF_OID_LEN)) break;
  24. if(!flipper_format_read_hex(file, "SEOS_ADF1_PRIV_ENC", SEOS_ADF1_PRIV_ENC, 16)) break;
  25. if(!flipper_format_read_hex(file, "SEOS_ADF1_PRIV_MAC", SEOS_ADF1_PRIV_MAC, 16)) break;
  26. if(!flipper_format_read_hex(file, "SEOS_ADF1_READ", SEOS_ADF1_READ, 16)) break;
  27. parsed = true;
  28. } while(false);
  29. if(parsed) {
  30. FURI_LOG_I(TAG, "Keys loaded");
  31. seos_log_buffer(TAG, "Keys for ADF OID loaded", SEOS_ADF_OID, SEOS_ADF_OID_LEN);
  32. } else {
  33. FURI_LOG_I(TAG, "Using default keys");
  34. }
  35. furi_string_free(path);
  36. furi_string_free(temp_str);
  37. flipper_format_free(file);
  38. return parsed;
  39. }
  40. bool seos_custom_event_callback(void* context, uint32_t event) {
  41. furi_assert(context);
  42. Seos* seos = context;
  43. return scene_manager_handle_custom_event(seos->scene_manager, event);
  44. }
  45. bool seos_back_event_callback(void* context) {
  46. furi_assert(context);
  47. Seos* seos = context;
  48. return scene_manager_handle_back_event(seos->scene_manager);
  49. }
  50. void seos_tick_event_callback(void* context) {
  51. furi_assert(context);
  52. Seos* seos = context;
  53. scene_manager_handle_tick_event(seos->scene_manager);
  54. }
  55. Seos* seos_alloc() {
  56. Seos* seos = malloc(sizeof(Seos));
  57. seos->has_external_ble = false;
  58. furi_hal_power_enable_otg();
  59. seos->view_dispatcher = view_dispatcher_alloc();
  60. seos->scene_manager = scene_manager_alloc(&seos_scene_handlers, seos);
  61. view_dispatcher_set_event_callback_context(seos->view_dispatcher, seos);
  62. view_dispatcher_set_custom_event_callback(seos->view_dispatcher, seos_custom_event_callback);
  63. view_dispatcher_set_navigation_event_callback(seos->view_dispatcher, seos_back_event_callback);
  64. view_dispatcher_set_tick_event_callback(seos->view_dispatcher, seos_tick_event_callback, 100);
  65. seos->nfc = nfc_alloc();
  66. // Nfc device
  67. seos->nfc_device = nfc_device_alloc();
  68. nfc_device_set_loading_callback(seos->nfc_device, seos_show_loading_popup, seos);
  69. // Open GUI record
  70. seos->gui = furi_record_open(RECORD_GUI);
  71. view_dispatcher_attach_to_gui(seos->view_dispatcher, seos->gui, ViewDispatcherTypeFullscreen);
  72. // Open Notification record
  73. seos->notifications = furi_record_open(RECORD_NOTIFICATION);
  74. // Submenu
  75. seos->submenu = submenu_alloc();
  76. view_dispatcher_add_view(seos->view_dispatcher, SeosViewMenu, submenu_get_view(seos->submenu));
  77. // Popup
  78. seos->popup = popup_alloc();
  79. view_dispatcher_add_view(seos->view_dispatcher, SeosViewPopup, popup_get_view(seos->popup));
  80. // Loading
  81. seos->loading = loading_alloc();
  82. view_dispatcher_add_view(
  83. seos->view_dispatcher, SeosViewLoading, loading_get_view(seos->loading));
  84. // Text Input
  85. seos->text_input = text_input_alloc();
  86. view_dispatcher_add_view(
  87. seos->view_dispatcher, SeosViewTextInput, text_input_get_view(seos->text_input));
  88. // TextBox
  89. seos->text_box = text_box_alloc();
  90. view_dispatcher_add_view(
  91. seos->view_dispatcher, SeosViewTextBox, text_box_get_view(seos->text_box));
  92. seos->text_box_store = furi_string_alloc();
  93. // Custom Widget
  94. seos->widget = widget_alloc();
  95. view_dispatcher_add_view(seos->view_dispatcher, SeosViewWidget, widget_get_view(seos->widget));
  96. seos->credential = seos_credential_alloc();
  97. seos->seos_emulator = seos_emulator_alloc(seos->credential);
  98. seos->keys_loaded = seos_load_keys(seos);
  99. return seos;
  100. }
  101. void seos_free(Seos* seos) {
  102. furi_assert(seos);
  103. furi_hal_power_disable_otg();
  104. nfc_free(seos->nfc);
  105. // Nfc device
  106. nfc_device_free(seos->nfc_device);
  107. // Submenu
  108. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewMenu);
  109. submenu_free(seos->submenu);
  110. // Popup
  111. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewPopup);
  112. popup_free(seos->popup);
  113. // Loading
  114. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewLoading);
  115. loading_free(seos->loading);
  116. // TextInput
  117. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewTextInput);
  118. text_input_free(seos->text_input);
  119. // TextBox
  120. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewTextBox);
  121. text_box_free(seos->text_box);
  122. furi_string_free(seos->text_box_store);
  123. // Custom Widget
  124. view_dispatcher_remove_view(seos->view_dispatcher, SeosViewWidget);
  125. widget_free(seos->widget);
  126. // View Dispatcher
  127. view_dispatcher_free(seos->view_dispatcher);
  128. // Scene Manager
  129. scene_manager_free(seos->scene_manager);
  130. // GUI
  131. furi_record_close(RECORD_GUI);
  132. seos->gui = NULL;
  133. // Notifications
  134. furi_record_close(RECORD_NOTIFICATION);
  135. seos->notifications = NULL;
  136. seos_credential_free(seos->credential);
  137. if(seos->seos_emulator) {
  138. seos_emulator_free(seos->seos_emulator);
  139. seos->seos_emulator = NULL;
  140. }
  141. free(seos);
  142. }
  143. void seos_text_store_set(Seos* seos, const char* text, ...) {
  144. va_list args;
  145. va_start(args, text);
  146. vsnprintf(seos->text_store, sizeof(seos->text_store), text, args);
  147. va_end(args);
  148. }
  149. void seos_text_store_clear(Seos* seos) {
  150. memset(seos->text_store, 0, sizeof(seos->text_store));
  151. }
  152. static const NotificationSequence seos_sequence_blink_start_blue = {
  153. &message_blink_start_10,
  154. &message_blink_set_color_blue,
  155. &message_do_not_reset,
  156. NULL,
  157. };
  158. static const NotificationSequence seos_sequence_blink_stop = {
  159. &message_blink_stop,
  160. NULL,
  161. };
  162. void seos_blink_start(Seos* seos) {
  163. notification_message(seos->notifications, &seos_sequence_blink_start_blue);
  164. }
  165. void seos_blink_stop(Seos* seos) {
  166. notification_message(seos->notifications, &seos_sequence_blink_stop);
  167. }
  168. void seos_show_loading_popup(void* context, bool show) {
  169. Seos* seos = context;
  170. if(show) {
  171. // Raise timer priority so that animations can play
  172. furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
  173. view_dispatcher_switch_to_view(seos->view_dispatcher, SeosViewLoading);
  174. } else {
  175. // Restore default timer priority
  176. furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
  177. }
  178. }
  179. int32_t seos_app(void* p) {
  180. UNUSED(p);
  181. Seos* seos = seos_alloc();
  182. if(seos->keys_loaded) {
  183. scene_manager_next_scene(seos->scene_manager, SeosSceneMainMenu);
  184. } else {
  185. scene_manager_next_scene(seos->scene_manager, SeosSceneZeroKeys);
  186. }
  187. view_dispatcher_run(seos->view_dispatcher);
  188. seos_free(seos);
  189. return 0;
  190. }