picopass.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "picopass_i.h"
  2. #define TAG "PicoPass"
  3. bool picopass_custom_event_callback(void* context, uint32_t event) {
  4. furi_assert(context);
  5. Picopass* picopass = context;
  6. return scene_manager_handle_custom_event(picopass->scene_manager, event);
  7. }
  8. bool picopass_back_event_callback(void* context) {
  9. furi_assert(context);
  10. Picopass* picopass = context;
  11. return scene_manager_handle_back_event(picopass->scene_manager);
  12. }
  13. void picopass_tick_event_callback(void* context) {
  14. furi_assert(context);
  15. Picopass* picopass = context;
  16. scene_manager_handle_tick_event(picopass->scene_manager);
  17. }
  18. Picopass* picopass_alloc() {
  19. Picopass* picopass = malloc(sizeof(Picopass));
  20. picopass->view_dispatcher = view_dispatcher_alloc();
  21. picopass->scene_manager = scene_manager_alloc(&picopass_scene_handlers, picopass);
  22. view_dispatcher_set_event_callback_context(picopass->view_dispatcher, picopass);
  23. view_dispatcher_set_custom_event_callback(
  24. picopass->view_dispatcher, picopass_custom_event_callback);
  25. view_dispatcher_set_navigation_event_callback(
  26. picopass->view_dispatcher, picopass_back_event_callback);
  27. view_dispatcher_set_tick_event_callback(
  28. picopass->view_dispatcher, picopass_tick_event_callback, 100);
  29. picopass->nfc = nfc_alloc();
  30. // Picopass device
  31. picopass->dev = picopass_device_alloc();
  32. // Open GUI record
  33. picopass->gui = furi_record_open(RECORD_GUI);
  34. view_dispatcher_attach_to_gui(
  35. picopass->view_dispatcher, picopass->gui, ViewDispatcherTypeFullscreen);
  36. // Open Notification record
  37. picopass->notifications = furi_record_open(RECORD_NOTIFICATION);
  38. // Submenu
  39. picopass->submenu = submenu_alloc();
  40. view_dispatcher_add_view(
  41. picopass->view_dispatcher, PicopassViewMenu, submenu_get_view(picopass->submenu));
  42. // Popup
  43. picopass->popup = popup_alloc();
  44. view_dispatcher_add_view(
  45. picopass->view_dispatcher, PicopassViewPopup, popup_get_view(picopass->popup));
  46. // Loading
  47. picopass->loading = loading_alloc();
  48. view_dispatcher_add_view(
  49. picopass->view_dispatcher, PicopassViewLoading, loading_get_view(picopass->loading));
  50. // Text Input
  51. picopass->text_input = text_input_alloc();
  52. view_dispatcher_add_view(
  53. picopass->view_dispatcher,
  54. PicopassViewTextInput,
  55. text_input_get_view(picopass->text_input));
  56. // Byte Input
  57. picopass->byte_input = byte_input_alloc();
  58. view_dispatcher_add_view(
  59. picopass->view_dispatcher,
  60. PicopassViewByteInput,
  61. byte_input_get_view(picopass->byte_input));
  62. // TextBox
  63. picopass->text_box = text_box_alloc();
  64. view_dispatcher_add_view(
  65. picopass->view_dispatcher, PicopassViewTextBox, text_box_get_view(picopass->text_box));
  66. picopass->text_box_store = furi_string_alloc();
  67. // Custom Widget
  68. picopass->widget = widget_alloc();
  69. view_dispatcher_add_view(
  70. picopass->view_dispatcher, PicopassViewWidget, widget_get_view(picopass->widget));
  71. picopass->dict_attack = dict_attack_alloc();
  72. view_dispatcher_add_view(
  73. picopass->view_dispatcher,
  74. PicopassViewDictAttack,
  75. dict_attack_get_view(picopass->dict_attack));
  76. picopass->loclass = loclass_alloc();
  77. view_dispatcher_add_view(
  78. picopass->view_dispatcher, PicopassViewLoclass, loclass_get_view(picopass->loclass));
  79. picopass->plugin_wiegand_manager =
  80. plugin_manager_alloc(PLUGIN_APP_ID, PLUGIN_API_VERSION, firmware_api_interface);
  81. picopass->plugin_wiegand = NULL;
  82. if(plugin_manager_load_single(picopass->plugin_wiegand_manager, APP_ASSETS_PATH("plugins/plugin_wiegand.fal")) !=
  83. PluginManagerErrorNone) {
  84. FURI_LOG_E(TAG, "Failed to load Wiegand plugin");
  85. } else if (plugin_manager_get_count(picopass->plugin_wiegand_manager)) {
  86. picopass->plugin_wiegand = (PluginWiegand*)plugin_manager_get_ep(picopass->plugin_wiegand_manager, 0);
  87. if(strcmp(picopass->plugin_wiegand->name, "Plugin Wiegand") != 0) {
  88. FURI_LOG_E(TAG, "Tried to load invalid Wiegand plugin");
  89. picopass->plugin_wiegand = NULL;
  90. } else {
  91. FURI_LOG_I(TAG, "Loaded Wiegand plugin");
  92. }
  93. }
  94. picopass->nr_mac_type = ManualNRMAC;
  95. return picopass;
  96. }
  97. void picopass_free(Picopass* picopass) {
  98. furi_assert(picopass);
  99. // Picopass device
  100. picopass_device_free(picopass->dev);
  101. picopass->dev = NULL;
  102. nfc_free(picopass->nfc);
  103. // Submenu
  104. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewMenu);
  105. submenu_free(picopass->submenu);
  106. // Popup
  107. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewPopup);
  108. popup_free(picopass->popup);
  109. // Loading
  110. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoading);
  111. loading_free(picopass->loading);
  112. // TextInput
  113. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextInput);
  114. text_input_free(picopass->text_input);
  115. // ByteInput
  116. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewByteInput);
  117. byte_input_free(picopass->byte_input);
  118. // TextBox
  119. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextBox);
  120. text_box_free(picopass->text_box);
  121. furi_string_free(picopass->text_box_store);
  122. // Custom Widget
  123. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewWidget);
  124. widget_free(picopass->widget);
  125. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewDictAttack);
  126. dict_attack_free(picopass->dict_attack);
  127. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoclass);
  128. loclass_free(picopass->loclass);
  129. // View Dispatcher
  130. view_dispatcher_free(picopass->view_dispatcher);
  131. // Scene Manager
  132. scene_manager_free(picopass->scene_manager);
  133. // GUI
  134. furi_record_close(RECORD_GUI);
  135. picopass->gui = NULL;
  136. // Notifications
  137. furi_record_close(RECORD_NOTIFICATION);
  138. picopass->notifications = NULL;
  139. plugin_manager_free(picopass->plugin_manager);
  140. free(picopass);
  141. }
  142. void picopass_text_store_set(Picopass* picopass, const char* text, ...) {
  143. va_list args;
  144. va_start(args, text);
  145. vsnprintf(picopass->text_store, sizeof(picopass->text_store), text, args);
  146. va_end(args);
  147. }
  148. void picopass_text_store_clear(Picopass* picopass) {
  149. memset(picopass->text_store, 0, sizeof(picopass->text_store));
  150. }
  151. static const NotificationSequence picopass_sequence_blink_start_cyan = {
  152. &message_blink_start_10,
  153. &message_blink_set_color_cyan,
  154. &message_do_not_reset,
  155. NULL,
  156. };
  157. static const NotificationSequence picopass_sequence_blink_start_magenta = {
  158. &message_blink_start_10,
  159. &message_blink_set_color_magenta,
  160. &message_do_not_reset,
  161. NULL,
  162. };
  163. static const NotificationSequence picopass_sequence_blink_stop = {
  164. &message_blink_stop,
  165. NULL,
  166. };
  167. void picopass_blink_start(Picopass* picopass) {
  168. notification_message(picopass->notifications, &picopass_sequence_blink_start_cyan);
  169. }
  170. void picopass_blink_emulate_start(Picopass* picopass) {
  171. notification_message(picopass->notifications, &picopass_sequence_blink_start_magenta);
  172. }
  173. void picopass_blink_stop(Picopass* picopass) {
  174. notification_message(picopass->notifications, &picopass_sequence_blink_stop);
  175. }
  176. void picopass_show_loading_popup(void* context, bool show) {
  177. Picopass* picopass = context;
  178. if(show) {
  179. // Raise timer priority so that animations can play
  180. furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
  181. view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewLoading);
  182. } else {
  183. // Restore default timer priority
  184. furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
  185. }
  186. }
  187. static void picopass_migrate_from_old_folder() {
  188. Storage* storage = furi_record_open(RECORD_STORAGE);
  189. storage_common_migrate(storage, "/ext/picopass", STORAGE_APP_DATA_PATH_PREFIX);
  190. furi_record_close(RECORD_STORAGE);
  191. }
  192. bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) {
  193. bool result = size > 0;
  194. while(size > 0) {
  195. result &= (*data == pattern);
  196. data++;
  197. size--;
  198. }
  199. return result;
  200. }
  201. int32_t picopass_app(void* p) {
  202. UNUSED(p);
  203. picopass_migrate_from_old_folder();
  204. Picopass* picopass = picopass_alloc();
  205. scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart);
  206. view_dispatcher_run(picopass->view_dispatcher);
  207. picopass_free(picopass);
  208. return 0;
  209. }