picopass.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272
  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_enable_queue(picopass->view_dispatcher);
  23. view_dispatcher_set_event_callback_context(picopass->view_dispatcher, picopass);
  24. view_dispatcher_set_custom_event_callback(
  25. picopass->view_dispatcher, picopass_custom_event_callback);
  26. view_dispatcher_set_navigation_event_callback(
  27. picopass->view_dispatcher, picopass_back_event_callback);
  28. view_dispatcher_set_tick_event_callback(
  29. picopass->view_dispatcher, picopass_tick_event_callback, 100);
  30. picopass->nfc = nfc_alloc();
  31. // Picopass device
  32. picopass->dev = picopass_device_alloc();
  33. // Open GUI record
  34. picopass->gui = furi_record_open(RECORD_GUI);
  35. view_dispatcher_attach_to_gui(
  36. picopass->view_dispatcher, picopass->gui, ViewDispatcherTypeFullscreen);
  37. // Open Notification record
  38. picopass->notifications = furi_record_open(RECORD_NOTIFICATION);
  39. // Submenu
  40. picopass->submenu = submenu_alloc();
  41. view_dispatcher_add_view(
  42. picopass->view_dispatcher, PicopassViewMenu, submenu_get_view(picopass->submenu));
  43. // Popup
  44. picopass->popup = popup_alloc();
  45. view_dispatcher_add_view(
  46. picopass->view_dispatcher, PicopassViewPopup, popup_get_view(picopass->popup));
  47. // Loading
  48. picopass->loading = loading_alloc();
  49. view_dispatcher_add_view(
  50. picopass->view_dispatcher, PicopassViewLoading, loading_get_view(picopass->loading));
  51. // Text Input
  52. picopass->text_input = text_input_alloc();
  53. view_dispatcher_add_view(
  54. picopass->view_dispatcher,
  55. PicopassViewTextInput,
  56. text_input_get_view(picopass->text_input));
  57. // Byte Input
  58. picopass->byte_input = byte_input_alloc();
  59. view_dispatcher_add_view(
  60. picopass->view_dispatcher,
  61. PicopassViewByteInput,
  62. byte_input_get_view(picopass->byte_input));
  63. // TextBox
  64. picopass->text_box = text_box_alloc();
  65. view_dispatcher_add_view(
  66. picopass->view_dispatcher, PicopassViewTextBox, text_box_get_view(picopass->text_box));
  67. picopass->text_box_store = furi_string_alloc();
  68. // Custom Widget
  69. picopass->widget = widget_alloc();
  70. view_dispatcher_add_view(
  71. picopass->view_dispatcher, PicopassViewWidget, widget_get_view(picopass->widget));
  72. picopass->dict_attack = dict_attack_alloc();
  73. view_dispatcher_add_view(
  74. picopass->view_dispatcher,
  75. PicopassViewDictAttack,
  76. dict_attack_get_view(picopass->dict_attack));
  77. picopass->loclass = loclass_alloc();
  78. view_dispatcher_add_view(
  79. picopass->view_dispatcher, PicopassViewLoclass, loclass_get_view(picopass->loclass));
  80. picopass->plugin_manager =
  81. plugin_manager_alloc(PLUGIN_APP_ID, PLUGIN_API_VERSION, firmware_api_interface);
  82. picopass->plugin_wiegand = NULL;
  83. if(plugin_manager_load_all(picopass->plugin_manager, APP_ASSETS_PATH("plugins")) !=
  84. PluginManagerErrorNone) {
  85. FURI_LOG_E(TAG, "Failed to load all libs");
  86. } else {
  87. uint32_t plugin_count = plugin_manager_get_count(picopass->plugin_manager);
  88. FURI_LOG_I(TAG, "Loaded %lu plugin(s)", plugin_count);
  89. for(uint32_t i = 0; i < plugin_count; i++) {
  90. const PluginWiegand* plugin = plugin_manager_get_ep(picopass->plugin_manager, i);
  91. FURI_LOG_I(TAG, "plugin name: %s", plugin->name);
  92. if(strcmp(plugin->name, "Plugin Wiegand") == 0) {
  93. // Have to cast to drop "const" qualifier
  94. picopass->plugin_wiegand = (PluginWiegand*)plugin;
  95. }
  96. }
  97. }
  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. }