mag_scene_read.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. // Creator: Hummus@FlipperGang
  2. #include "../mag_i.h"
  3. #include "../helpers/mag_helpers.h"
  4. #include "mag_scene_read.h"
  5. #define TAG "MagSceneRead"
  6. void uart_callback(FuriHalSerialHandle* handle, FuriHalSerialRxEvent event, void* context) {
  7. Mag* mag = context;
  8. if(event == FuriHalSerialRxEventData) {
  9. uint8_t data = furi_hal_serial_async_rx(handle);
  10. furi_stream_buffer_send(mag->uart_rx_stream, &data, 1, 0);
  11. furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtRxDone);
  12. }
  13. }
  14. static int32_t uart_worker(void* context) {
  15. Mag* mag = context;
  16. mag->uart_rx_stream = furi_stream_buffer_alloc(UART_RX_BUF_SIZE, 1);
  17. mag->uart_text_box_store_strlen = 0;
  18. while(1) {
  19. uint32_t events =
  20. furi_thread_flags_wait(WORKER_ALL_RX_EVENTS, FuriFlagWaitAny, FuriWaitForever);
  21. // furi_check((events & FuriFlagError) == 0);
  22. if(events & WorkerEvtStop) break;
  23. if(events & WorkerEvtRxDone) {
  24. FURI_LOG_D(TAG, "WorkerEvtRxDone");
  25. // notification_message(mag->notifications, &sequence_success);
  26. size_t len = furi_stream_buffer_receive(
  27. mag->uart_rx_stream, mag->uart_rx_buf, UART_RX_BUF_SIZE, 200);
  28. FURI_LOG_D(TAG, "UART RX len: %d", len);
  29. if(len > 0) {
  30. // If text box store gets too big, then truncate it
  31. mag->uart_text_box_store_strlen += len;
  32. if(mag->uart_text_box_store_strlen >= UART_TERMINAL_TEXT_BOX_STORE_SIZE - 1) {
  33. furi_string_right(
  34. mag->uart_text_box_store, mag->uart_text_box_store_strlen / 2);
  35. mag->uart_text_box_store_strlen =
  36. furi_string_size(mag->uart_text_box_store) + len;
  37. }
  38. // Add '\0' to the end of the string, and then add the new data
  39. mag->uart_rx_buf[len] = '\0';
  40. furi_string_cat_printf(mag->uart_text_box_store, "%s", mag->uart_rx_buf);
  41. FURI_LOG_D(TAG, "UART RX buf: %*.s", len, mag->uart_rx_buf);
  42. FURI_LOG_D(
  43. TAG, "UART RX store: %s", furi_string_get_cstr(mag->uart_text_box_store));
  44. }
  45. FURI_LOG_D(TAG, "UARTEventRxData");
  46. view_dispatcher_send_custom_event(mag->view_dispatcher, UARTEventRxData);
  47. }
  48. }
  49. furi_stream_buffer_free(mag->uart_rx_stream);
  50. return 0;
  51. }
  52. void update_widgets(Mag* mag) {
  53. // Clear widget from all elements
  54. widget_reset(mag->widget);
  55. // Titlebar
  56. widget_add_icon_element(mag->widget, 38, -1, &I_mag_file_10px);
  57. widget_add_string_element(mag->widget, 64, 0, AlignCenter, AlignTop, FontPrimary, "READ");
  58. widget_add_icon_element(mag->widget, 81, -1, &I_mag_file_10px);
  59. // Text box
  60. widget_add_text_scroll_element(
  61. mag->widget, 0, 10, 128, 40, furi_string_get_cstr(mag->uart_text_box_store));
  62. // Buttons
  63. widget_add_button_element(mag->widget, GuiButtonTypeLeft, "Clear", mag_widget_callback, mag);
  64. widget_add_button_element(mag->widget, GuiButtonTypeRight, "Parse", mag_widget_callback, mag);
  65. }
  66. void mag_scene_read_on_enter(void* context) {
  67. Mag* mag = context;
  68. FuriString* message = furi_string_alloc();
  69. furi_string_printf(message, "Please swipe a card!\n");
  70. mag->uart_text_box_store = message;
  71. view_dispatcher_switch_to_view(mag->view_dispatcher, MagViewWidget);
  72. update_widgets(mag);
  73. // Initialize UART
  74. mag->serial_handle = furi_hal_serial_control_acquire(FuriHalSerialIdUsart);
  75. furi_check(mag->serial_handle);
  76. furi_hal_serial_init(mag->serial_handle, 9600);
  77. furi_hal_serial_async_rx_start(mag->serial_handle, uart_callback, mag, false);
  78. FURI_LOG_D(TAG, "UART initialized");
  79. mag->uart_rx_thread = furi_thread_alloc();
  80. furi_thread_set_name(mag->uart_rx_thread, "UartRx");
  81. furi_thread_set_stack_size(mag->uart_rx_thread, 1024);
  82. furi_thread_set_context(mag->uart_rx_thread, mag);
  83. furi_thread_set_callback(mag->uart_rx_thread, uart_worker);
  84. furi_thread_start(mag->uart_rx_thread);
  85. FURI_LOG_D(TAG, "UART worker started");
  86. }
  87. bool mag_scene_read_on_event(void* context, SceneManagerEvent event) {
  88. Mag* mag = context;
  89. bool consumed = false;
  90. if(event.type == SceneManagerEventTypeCustom) {
  91. FURI_LOG_D(TAG, "Custom event: %ld", event.event);
  92. switch(event.event) {
  93. case GuiButtonTypeLeft: // Clear
  94. consumed = true;
  95. // Clear text box store
  96. furi_string_reset(mag->uart_text_box_store);
  97. mag->uart_text_box_store_strlen = 0;
  98. break;
  99. case GuiButtonTypeRight: // Parse
  100. consumed = true;
  101. FURI_LOG_D(TAG, "Trying to parse");
  102. MagDevice* mag_dev = mag->mag_dev;
  103. bool res = mag_device_parse_card_string(mag_dev, mag->uart_text_box_store);
  104. furi_string_reset(mag->uart_text_box_store);
  105. if(res) {
  106. notification_message(mag->notifications, &sequence_success);
  107. furi_string_printf(
  108. mag->uart_text_box_store,
  109. "Track 1: %.*s\nTrack 2: %.*s\nTrack 3: %.*s",
  110. mag_dev->dev_data.track[0].len,
  111. furi_string_get_cstr(mag_dev->dev_data.track[0].str),
  112. mag_dev->dev_data.track[1].len,
  113. furi_string_get_cstr(mag_dev->dev_data.track[1].str),
  114. mag_dev->dev_data.track[2].len,
  115. furi_string_get_cstr(mag_dev->dev_data.track[2].str));
  116. // Switch to saved menu scene
  117. scene_manager_next_scene(mag->scene_manager, MagSceneSavedMenu);
  118. } else {
  119. furi_string_printf(mag->uart_text_box_store, "Failed to parse! Try again\n");
  120. notification_message(mag->notifications, &sequence_error);
  121. }
  122. break;
  123. }
  124. update_widgets(mag);
  125. }
  126. return consumed;
  127. }
  128. void mag_scene_read_on_exit(void* context) {
  129. Mag* mag = context;
  130. // notification_message(mag->notifications, &sequence_blink_stop);
  131. widget_reset(mag->widget);
  132. // view_dispatcher_remove_view(mag->view_dispatcher, MagViewWidget);
  133. // Stop UART worker
  134. FURI_LOG_D(TAG, "Stopping UART worker");
  135. furi_thread_flags_set(furi_thread_get_id(mag->uart_rx_thread), WorkerEvtStop);
  136. furi_thread_join(mag->uart_rx_thread);
  137. furi_thread_free(mag->uart_rx_thread);
  138. FURI_LOG_D(TAG, "UART worker stopped");
  139. furi_string_free(mag->uart_text_box_store);
  140. furi_hal_serial_deinit(mag->serial_handle);
  141. furi_hal_serial_control_release(mag->serial_handle);
  142. notification_message(mag->notifications, &sequence_blink_stop);
  143. }