picopass.c 8.5 KB

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