esubghz_chat_key_read_popup.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  1. #include "../esubghz_chat_i.h"
  2. typedef enum {
  3. KeyReadPopupState_Idle,
  4. KeyReadPopupState_Detecting,
  5. KeyReadPopupState_Reading,
  6. } KeyReadPopupState;
  7. static bool read_worker_cb(NfcWorkerEvent event, void* context)
  8. {
  9. furi_assert(context);
  10. ESubGhzChatState* state = context;
  11. view_dispatcher_send_custom_event(state->view_dispatcher, event);
  12. return true;
  13. }
  14. static bool key_read_popup_handle_key_read(ESubGhzChatState *state)
  15. {
  16. NfcDeviceData *dev_data = state->nfc_dev_data;
  17. if (dev_data->mf_ul_data.data_read < KEY_BITS / 8) {
  18. return false;
  19. }
  20. /* initiate the crypto context */
  21. bool ret = crypto_ctx_set_key(state->crypto_ctx,
  22. dev_data->mf_ul_data.data);
  23. /* cleanup */
  24. crypto_explicit_bzero(dev_data->mf_ul_data.data, KEY_BITS / 8);
  25. if (!ret) {
  26. crypto_ctx_clear(state->crypto_ctx);
  27. return false;
  28. }
  29. /* set encrypted flag and enter the chat */
  30. state->encrypted = true;
  31. enter_chat(state);
  32. return true;
  33. }
  34. static void key_read_popup_set_state(ESubGhzChatState *state, KeyReadPopupState
  35. new_state)
  36. {
  37. uint32_t cur_state = scene_manager_get_scene_state(
  38. state->scene_manager, ESubGhzChatScene_KeyReadPopup);
  39. if (cur_state == new_state) {
  40. return;
  41. }
  42. if (new_state == KeyReadPopupState_Detecting) {
  43. popup_reset(state->nfc_popup);
  44. popup_set_text(state->nfc_popup, "Apply card to\nFlipper's "
  45. "back", 97, 24, AlignCenter, AlignTop);
  46. popup_set_icon(state->nfc_popup, 0, 8, &I_NFC_manual_60x50);
  47. } else if (new_state == KeyReadPopupState_Reading) {
  48. popup_reset(state->nfc_popup);
  49. popup_set_header(state->nfc_popup, "Reading card\nDon't "
  50. "move...", 85, 24, AlignCenter, AlignTop);
  51. popup_set_icon(state->nfc_popup, 12, 23, &I_Loading_24);
  52. }
  53. scene_manager_set_scene_state(state->scene_manager,
  54. ESubGhzChatScene_KeyReadPopup, new_state);
  55. }
  56. /* Prepares the key share read scene. */
  57. void scene_on_enter_key_read_popup(void* context)
  58. {
  59. FURI_LOG_T(APPLICATION_NAME, "scene_on_enter_key_read_popup");
  60. furi_assert(context);
  61. ESubGhzChatState* state = context;
  62. key_read_popup_set_state(state, KeyReadPopupState_Detecting);
  63. state->nfc_dev_data->parsed_data = furi_string_alloc();
  64. if (state->nfc_dev_data->parsed_data == NULL) {
  65. /* can't do anything here, crash */
  66. furi_check(0);
  67. }
  68. nfc_worker_start(state->nfc_worker, NfcWorkerStateRead,
  69. state->nfc_dev_data, read_worker_cb, state);
  70. notification_message(state->notification, &sequence_blink_start_cyan);
  71. view_dispatcher_switch_to_view(state->view_dispatcher,
  72. ESubGhzChatView_NfcPopup);
  73. }
  74. /* Handles scene manager events for the key read popup scene. */
  75. bool scene_on_event_key_read_popup(void* context, SceneManagerEvent event)
  76. {
  77. FURI_LOG_T(APPLICATION_NAME, "scene_on_event_key_read_popup");
  78. furi_assert(context);
  79. ESubGhzChatState* state = context;
  80. bool consumed = false;
  81. switch(event.type) {
  82. case SceneManagerEventTypeCustom:
  83. switch(event.event) {
  84. /* card detected */
  85. case NfcWorkerEventCardDetected:
  86. key_read_popup_set_state(state,
  87. KeyReadPopupState_Reading);
  88. notification_message(state->notification,
  89. &sequence_blink_start_yellow);
  90. consumed = true;
  91. break;
  92. /* no card detected */
  93. case NfcWorkerEventNoCardDetected:
  94. key_read_popup_set_state(state,
  95. KeyReadPopupState_Detecting);
  96. notification_message(state->notification,
  97. &sequence_blink_start_cyan);
  98. consumed = true;
  99. break;
  100. /* key probably read */
  101. case NfcWorkerEventReadMfUltralight:
  102. if (key_read_popup_handle_key_read(state)) {
  103. scene_manager_next_scene(state->scene_manager,
  104. ESubGhzChatScene_ChatInput);
  105. } else {
  106. if (!scene_manager_previous_scene(
  107. state->scene_manager)) {
  108. view_dispatcher_stop(state->view_dispatcher);
  109. }
  110. }
  111. consumed = true;
  112. break;
  113. default:
  114. if (!scene_manager_previous_scene(
  115. state->scene_manager)) {
  116. view_dispatcher_stop(state->view_dispatcher);
  117. }
  118. consumed = true;
  119. break;
  120. }
  121. break;
  122. default:
  123. consumed = false;
  124. break;
  125. }
  126. return consumed;
  127. }
  128. /* Cleans up the key read popup scene. */
  129. void scene_on_exit_key_read_popup(void* context)
  130. {
  131. FURI_LOG_T(APPLICATION_NAME, "scene_on_exit_key_read_popup");
  132. furi_assert(context);
  133. ESubGhzChatState* state = context;
  134. popup_reset(state->nfc_popup);
  135. scene_manager_set_scene_state(state->scene_manager,
  136. ESubGhzChatScene_KeyReadPopup, KeyReadPopupState_Idle);
  137. notification_message(state->notification, &sequence_blink_stop);
  138. nfc_worker_stop(state->nfc_worker);
  139. crypto_explicit_bzero(state->nfc_dev_data->mf_ul_data.data, KEY_BITS / 8);
  140. if (state->nfc_dev_data->parsed_data != NULL) {
  141. furi_string_free(state->nfc_dev_data->parsed_data);
  142. }
  143. memset(state->nfc_dev_data, 0, sizeof(NfcDeviceData));
  144. }