picopass.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  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_manager =
  80. plugin_manager_alloc(PLUGIN_APP_ID, PLUGIN_API_VERSION, firmware_api_interface);
  81. picopass->plugin_wiegand = NULL;
  82. if(plugin_manager_load_all(picopass->plugin_manager, APP_ASSETS_PATH("plugins")) !=
  83. PluginManagerErrorNone) {
  84. FURI_LOG_E(TAG, "Failed to load all libs");
  85. } else {
  86. uint32_t plugin_count = plugin_manager_get_count(picopass->plugin_manager);
  87. FURI_LOG_I(TAG, "Loaded %lu plugin(s)", plugin_count);
  88. for(uint32_t i = 0; i < plugin_count; i++) {
  89. const PluginWiegand* plugin = plugin_manager_get_ep(picopass->plugin_manager, i);
  90. FURI_LOG_I(TAG, "plugin name: %s", plugin->name);
  91. if(strcmp(plugin->name, "Plugin Wiegand") == 0) {
  92. // Have to cast to drop "const" qualifier
  93. picopass->plugin_wiegand = (PluginWiegand*)plugin;
  94. }
  95. }
  96. }
  97. picopass->nr_mac_type = ManualNRMAC;
  98. return picopass;
  99. }
  100. void picopass_free(Picopass* picopass) {
  101. furi_assert(picopass);
  102. // Picopass device
  103. picopass_device_free(picopass->dev);
  104. picopass->dev = NULL;
  105. nfc_free(picopass->nfc);
  106. // Submenu
  107. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewMenu);
  108. submenu_free(picopass->submenu);
  109. // Popup
  110. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewPopup);
  111. popup_free(picopass->popup);
  112. // Loading
  113. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoading);
  114. loading_free(picopass->loading);
  115. // TextInput
  116. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextInput);
  117. text_input_free(picopass->text_input);
  118. // ByteInput
  119. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewByteInput);
  120. byte_input_free(picopass->byte_input);
  121. // TextBox
  122. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewTextBox);
  123. text_box_free(picopass->text_box);
  124. furi_string_free(picopass->text_box_store);
  125. // Custom Widget
  126. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewWidget);
  127. widget_free(picopass->widget);
  128. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewDictAttack);
  129. dict_attack_free(picopass->dict_attack);
  130. view_dispatcher_remove_view(picopass->view_dispatcher, PicopassViewLoclass);
  131. loclass_free(picopass->loclass);
  132. // View Dispatcher
  133. view_dispatcher_free(picopass->view_dispatcher);
  134. // Scene Manager
  135. scene_manager_free(picopass->scene_manager);
  136. // GUI
  137. furi_record_close(RECORD_GUI);
  138. picopass->gui = NULL;
  139. // Notifications
  140. furi_record_close(RECORD_NOTIFICATION);
  141. picopass->notifications = NULL;
  142. plugin_manager_free(picopass->plugin_manager);
  143. free(picopass);
  144. }
  145. void picopass_text_store_set(Picopass* picopass, const char* text, ...) {
  146. va_list args;
  147. va_start(args, text);
  148. vsnprintf(picopass->text_store, sizeof(picopass->text_store), text, args);
  149. va_end(args);
  150. }
  151. void picopass_text_store_clear(Picopass* picopass) {
  152. memset(picopass->text_store, 0, sizeof(picopass->text_store));
  153. }
  154. static const NotificationSequence picopass_sequence_blink_start_cyan = {
  155. &message_blink_start_10,
  156. &message_blink_set_color_cyan,
  157. &message_do_not_reset,
  158. NULL,
  159. };
  160. static const NotificationSequence picopass_sequence_blink_start_magenta = {
  161. &message_blink_start_10,
  162. &message_blink_set_color_magenta,
  163. &message_do_not_reset,
  164. NULL,
  165. };
  166. static const NotificationSequence picopass_sequence_blink_stop = {
  167. &message_blink_stop,
  168. NULL,
  169. };
  170. void picopass_blink_start(Picopass* picopass) {
  171. notification_message(picopass->notifications, &picopass_sequence_blink_start_cyan);
  172. }
  173. void picopass_blink_emulate_start(Picopass* picopass) {
  174. notification_message(picopass->notifications, &picopass_sequence_blink_start_magenta);
  175. }
  176. void picopass_blink_stop(Picopass* picopass) {
  177. notification_message(picopass->notifications, &picopass_sequence_blink_stop);
  178. }
  179. void picopass_show_loading_popup(void* context, bool show) {
  180. Picopass* picopass = context;
  181. if(show) {
  182. // Raise timer priority so that animations can play
  183. furi_timer_set_thread_priority(FuriTimerThreadPriorityElevated);
  184. view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewLoading);
  185. } else {
  186. // Restore default timer priority
  187. furi_timer_set_thread_priority(FuriTimerThreadPriorityNormal);
  188. }
  189. }
  190. static void picopass_migrate_from_old_folder() {
  191. Storage* storage = furi_record_open(RECORD_STORAGE);
  192. storage_common_migrate(storage, "/ext/picopass", STORAGE_APP_DATA_PATH_PREFIX);
  193. furi_record_close(RECORD_STORAGE);
  194. }
  195. bool picopass_is_memset(const uint8_t* data, const uint8_t pattern, size_t size) {
  196. bool result = size > 0;
  197. while(size > 0) {
  198. result &= (*data == pattern);
  199. data++;
  200. size--;
  201. }
  202. return result;
  203. }
  204. int32_t picopass_app(void* p) {
  205. UNUSED(p);
  206. picopass_migrate_from_old_folder();
  207. Picopass* picopass = picopass_alloc();
  208. scene_manager_next_scene(picopass->scene_manager, PicopassSceneStart);
  209. view_dispatcher_run(picopass->view_dispatcher);
  210. picopass_free(picopass);
  211. return 0;
  212. }