uhf_app.c 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. #include "uhf_app_i.h"
  2. static const char* uhf_file_header = "Flipper UHF device";
  3. static const uint32_t uhf_file_version = 1;
  4. static const uint8_t bank_data_start = 20;
  5. static const uint8_t bank_data_length = 16;
  6. // empty callback
  7. void empty_rx_callback(UartIrqEvent event, uint8_t data, void* ctx) {
  8. UNUSED(event);
  9. UNUSED(data);
  10. UNUSED(ctx);
  11. }
  12. char* convertToHexString(const uint8_t* array, size_t length) {
  13. if(array == NULL || length == 0) {
  14. return NULL;
  15. }
  16. // Each byte takes 3 characters in the hex representation (2 characters + space), plus 1 for the null terminator
  17. size_t hexLength = (length * 3) + 1;
  18. char* hexArray = (char*)malloc(hexLength * sizeof(char));
  19. if(hexArray == NULL) {
  20. return NULL;
  21. }
  22. size_t index = 0;
  23. for(size_t i = 0; i < length; i++) {
  24. index += snprintf(&hexArray[index], hexLength - index, "%02x ", array[i]);
  25. }
  26. hexArray[hexLength - 1] = '\0';
  27. return hexArray;
  28. }
  29. bool uhf_save_read_data(UHFResponseData* uhf_response_data, Storage* storage, const char* filename) {
  30. if(!storage_dir_exists(storage, UHF_APPS_DATA_FOLDER)) {
  31. storage_simply_mkdir(storage, UHF_APPS_DATA_FOLDER);
  32. }
  33. if(!storage_dir_exists(storage, UHF_APPS_STORAGE_FOLDER)) {
  34. storage_simply_mkdir(storage, UHF_APPS_STORAGE_FOLDER);
  35. }
  36. FlipperFormat* file = flipper_format_file_alloc(storage);
  37. FuriString* temp_str = furi_string_alloc();
  38. // set file name
  39. furi_string_cat_printf(
  40. temp_str, "%s/%s%s", UHF_APPS_STORAGE_FOLDER, filename, UHF_FILE_EXTENSION);
  41. // open file
  42. if(!flipper_format_file_open_always(file, furi_string_get_cstr(temp_str))) return false;
  43. // write header
  44. if(!flipper_format_write_header_cstr(file, uhf_file_header, uhf_file_version)) return false;
  45. // write rfu data to file
  46. UHFData* rfu_data = uhf_response_data_get_uhf_data(uhf_response_data, 1);
  47. if(rfu_data->length) {
  48. if(!flipper_format_write_hex(
  49. file, "RFU", rfu_data->data + bank_data_start, bank_data_length))
  50. return false;
  51. } else {
  52. if(!flipper_format_write_hex(file, "RFU", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
  53. }
  54. // write epc data to file
  55. UHFData* epc_data = uhf_response_data_get_uhf_data(uhf_response_data, 2);
  56. if(epc_data->length) {
  57. if(!flipper_format_write_hex(
  58. file, "EPC", epc_data->data + bank_data_start, bank_data_length))
  59. return false;
  60. } else {
  61. if(!flipper_format_write_hex(file, "EPC", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
  62. }
  63. // write tid data to file
  64. UHFData* tid_data = uhf_response_data_get_uhf_data(uhf_response_data, 3);
  65. if(tid_data->length) {
  66. if(!flipper_format_write_hex(
  67. file, "TID", tid_data->data + bank_data_start, bank_data_length))
  68. return false;
  69. } else {
  70. if(!flipper_format_write_hex(file, "TID", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
  71. }
  72. // write user data to file
  73. UHFData* user_data = uhf_response_data_get_uhf_data(uhf_response_data, 4);
  74. if(user_data->length) {
  75. if(!flipper_format_write_hex(
  76. file, "USER", user_data->data + bank_data_start, bank_data_length))
  77. return false;
  78. } else {
  79. if(!flipper_format_write_hex(file, "USER", UHF_BANK_DOES_NOT_EXIST, 1)) return false;
  80. }
  81. furi_string_free(temp_str);
  82. flipper_format_free(file);
  83. return true;
  84. }
  85. bool uhf_custom_event_callback(void* ctx, uint32_t event) {
  86. furi_assert(ctx);
  87. UHFApp* uhf_app = ctx;
  88. return scene_manager_handle_custom_event(uhf_app->scene_manager, event);
  89. }
  90. bool uhf_back_event_callback(void* ctx) {
  91. furi_assert(ctx);
  92. UHFApp* uhf_app = ctx;
  93. return scene_manager_handle_back_event(uhf_app->scene_manager);
  94. }
  95. void uhf_tick_event_callback(void* ctx) {
  96. furi_assert(ctx);
  97. UHFApp* uhf_app = ctx;
  98. scene_manager_handle_tick_event(uhf_app->scene_manager);
  99. }
  100. UHFApp* uhf_alloc() {
  101. UHFApp* uhf_app = (UHFApp*)malloc(sizeof(UHFApp));
  102. uhf_app->worker = (UHFWorker*)uhf_worker_alloc();
  103. uhf_app->view_dispatcher = view_dispatcher_alloc();
  104. uhf_app->scene_manager = scene_manager_alloc(&uhf_scene_handlers, uhf_app);
  105. view_dispatcher_enable_queue(uhf_app->view_dispatcher);
  106. view_dispatcher_set_event_callback_context(uhf_app->view_dispatcher, uhf_app);
  107. view_dispatcher_set_custom_event_callback(uhf_app->view_dispatcher, uhf_custom_event_callback);
  108. view_dispatcher_set_navigation_event_callback(
  109. uhf_app->view_dispatcher, uhf_back_event_callback);
  110. view_dispatcher_set_tick_event_callback(
  111. uhf_app->view_dispatcher, uhf_tick_event_callback, 100);
  112. // Open GUI record
  113. uhf_app->gui = furi_record_open(RECORD_GUI);
  114. view_dispatcher_attach_to_gui(
  115. uhf_app->view_dispatcher, uhf_app->gui, ViewDispatcherTypeFullscreen);
  116. // Storage
  117. uhf_app->storage = furi_record_open(RECORD_STORAGE);
  118. // Open Notification record
  119. uhf_app->notifications = furi_record_open(RECORD_NOTIFICATION);
  120. // Submenu
  121. uhf_app->submenu = submenu_alloc();
  122. view_dispatcher_add_view(
  123. uhf_app->view_dispatcher, UHFViewMenu, submenu_get_view(uhf_app->submenu));
  124. // Popup
  125. uhf_app->popup = popup_alloc();
  126. view_dispatcher_add_view(
  127. uhf_app->view_dispatcher, UHFViewPopup, popup_get_view(uhf_app->popup));
  128. // Loading
  129. uhf_app->loading = loading_alloc();
  130. view_dispatcher_add_view(
  131. uhf_app->view_dispatcher, UHFViewLoading, loading_get_view(uhf_app->loading));
  132. // Text Input
  133. uhf_app->text_input = text_input_alloc();
  134. view_dispatcher_add_view(
  135. uhf_app->view_dispatcher, UHFViewTextInput, text_input_get_view(uhf_app->text_input));
  136. // Custom Widget
  137. uhf_app->widget = widget_alloc();
  138. view_dispatcher_add_view(
  139. uhf_app->view_dispatcher, UHFViewWidget, widget_get_view(uhf_app->widget));
  140. return uhf_app;
  141. }
  142. void uhf_free(UHFApp* uhf_app) {
  143. furi_assert(uhf_app);
  144. // Submenu
  145. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewMenu);
  146. submenu_free(uhf_app->submenu);
  147. // Popup
  148. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewPopup);
  149. popup_free(uhf_app->popup);
  150. // Loading
  151. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewLoading);
  152. loading_free(uhf_app->loading);
  153. // TextInput
  154. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewTextInput);
  155. text_input_free(uhf_app->text_input);
  156. // Custom Widget
  157. view_dispatcher_remove_view(uhf_app->view_dispatcher, UHFViewWidget);
  158. widget_free(uhf_app->widget);
  159. // Worker
  160. uhf_worker_stop(uhf_app->worker);
  161. uhf_worker_free(uhf_app->worker);
  162. // View Dispatcher
  163. view_dispatcher_free(uhf_app->view_dispatcher);
  164. // Scene Manager
  165. scene_manager_free(uhf_app->scene_manager);
  166. // GUI
  167. furi_record_close(RECORD_GUI);
  168. uhf_app->gui = NULL;
  169. // Storage
  170. furi_record_close(RECORD_STORAGE);
  171. uhf_app->storage = NULL;
  172. // Notifications
  173. furi_record_close(RECORD_NOTIFICATION);
  174. uhf_app->notifications = NULL;
  175. free(uhf_app);
  176. }
  177. static const NotificationSequence uhf_sequence_blink_start_cyan = {
  178. &message_blink_start_10,
  179. &message_blink_set_color_cyan,
  180. &message_do_not_reset,
  181. NULL,
  182. };
  183. static const NotificationSequence uhf_sequence_blink_stop = {
  184. &message_blink_stop,
  185. NULL,
  186. };
  187. void uhf_blink_start(UHFApp* uhf_app) {
  188. notification_message(uhf_app->notifications, &uhf_sequence_blink_start_cyan);
  189. }
  190. void uhf_blink_stop(UHFApp* uhf_app) {
  191. notification_message(uhf_app->notifications, &uhf_sequence_blink_stop);
  192. }
  193. void uhf_show_loading_popup(void* ctx, bool show) {
  194. UHFApp* uhf_app = ctx;
  195. TaskHandle_t timer_task = xTaskGetHandle(configTIMER_SERVICE_TASK_NAME);
  196. if(show) {
  197. // Raise timer priority so that animations can play
  198. vTaskPrioritySet(timer_task, configMAX_PRIORITIES - 1);
  199. view_dispatcher_switch_to_view(uhf_app->view_dispatcher, UHFViewLoading);
  200. } else {
  201. // Restore default timer priority
  202. vTaskPrioritySet(timer_task, configTIMER_TASK_PRIORITY);
  203. }
  204. }
  205. int32_t uhf_app_main(void* ctx) {
  206. UNUSED(ctx);
  207. UHFApp* uhf_app = uhf_alloc();
  208. // enable 5v pin
  209. furi_hal_power_enable_otg();
  210. scene_manager_next_scene(uhf_app->scene_manager, UHFSceneVerify);
  211. view_dispatcher_run(uhf_app->view_dispatcher);
  212. // disable 5v pin
  213. furi_hal_power_disable_otg();
  214. // set uart callback to none
  215. furi_hal_uart_set_irq_cb(FuriHalUartIdUSART1, empty_rx_callback, NULL);
  216. // exit app
  217. uhf_free(uhf_app);
  218. return 0;
  219. }