detect_reader.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. #include "detect_reader.h"
  2. #include <assets_icons.h>
  3. #include <gui/elements.h>
  4. #define DETECT_READER_UID_MAX_LEN (10)
  5. struct DetectReader {
  6. View* view;
  7. DetectReaderDoneCallback callback;
  8. void* context;
  9. };
  10. typedef struct {
  11. uint16_t nonces;
  12. uint16_t nonces_max;
  13. DetectReaderState state;
  14. FuriString* uid_str;
  15. } DetectReaderViewModel;
  16. static void detect_reader_draw_callback(Canvas* canvas, void* model) {
  17. DetectReaderViewModel* m = model;
  18. char text[32] = {};
  19. // Draw header and icon
  20. canvas_draw_icon(canvas, 0, 16, &I_Modern_reader_18x34);
  21. if(m->state == DetectReaderStateStart) {
  22. snprintf(text, sizeof(text), "Touch the reader");
  23. canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39);
  24. if(furi_string_size(m->uid_str)) {
  25. elements_multiline_text_aligned(
  26. canvas, 64, 64, AlignCenter, AlignBottom, furi_string_get_cstr(m->uid_str));
  27. }
  28. } else if(m->state == DetectReaderStateReaderDetected) {
  29. snprintf(text, sizeof(text), "Move the Flipper away");
  30. canvas_draw_icon(canvas, 24, 25, &I_Release_arrow_18x15);
  31. } else if(m->state == DetectReaderStateReaderLost) {
  32. snprintf(text, sizeof(text), "Touch the reader again");
  33. canvas_draw_icon(canvas, 21, 13, &I_Move_flipper_26x39);
  34. }
  35. canvas_draw_str_aligned(canvas, 64, 0, AlignCenter, AlignTop, text);
  36. // Draw collected nonces
  37. if(m->state == DetectReaderStateStart) {
  38. canvas_set_font(canvas, FontPrimary);
  39. canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Emulating...");
  40. canvas_set_font(canvas, FontSecondary);
  41. canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, "MIFARE MFkey32");
  42. } else {
  43. if(m->state == DetectReaderStateDone) {
  44. canvas_set_font(canvas, FontPrimary);
  45. canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Completed!");
  46. } else {
  47. canvas_set_font(canvas, FontPrimary);
  48. canvas_draw_str_aligned(canvas, 51, 22, AlignLeft, AlignTop, "Collecting...");
  49. }
  50. canvas_set_font(canvas, FontSecondary);
  51. snprintf(text, sizeof(text), "Nonce pairs: %d/%d", m->nonces, m->nonces_max);
  52. canvas_draw_str_aligned(canvas, 51, 35, AlignLeft, AlignTop, text);
  53. }
  54. // Draw button
  55. if(m->nonces > 0) {
  56. elements_button_center(canvas, "Done");
  57. }
  58. }
  59. static bool detect_reader_input_callback(InputEvent* event, void* context) {
  60. DetectReader* detect_reader = context;
  61. furi_assert(detect_reader->callback);
  62. bool consumed = false;
  63. uint8_t nonces = 0;
  64. with_view_model(
  65. detect_reader->view, DetectReaderViewModel * model, { nonces = model->nonces; }, false);
  66. if(event->type == InputTypeShort) {
  67. if(event->key == InputKeyOk) {
  68. if(nonces > 0) {
  69. detect_reader->callback(detect_reader->context);
  70. consumed = true;
  71. }
  72. }
  73. }
  74. return consumed;
  75. }
  76. DetectReader* detect_reader_alloc() {
  77. DetectReader* detect_reader = malloc(sizeof(DetectReader));
  78. detect_reader->view = view_alloc();
  79. view_allocate_model(detect_reader->view, ViewModelTypeLocking, sizeof(DetectReaderViewModel));
  80. view_set_draw_callback(detect_reader->view, detect_reader_draw_callback);
  81. view_set_input_callback(detect_reader->view, detect_reader_input_callback);
  82. view_set_context(detect_reader->view, detect_reader);
  83. with_view_model(
  84. detect_reader->view,
  85. DetectReaderViewModel * model,
  86. { model->uid_str = furi_string_alloc(); },
  87. false);
  88. return detect_reader;
  89. }
  90. void detect_reader_free(DetectReader* detect_reader) {
  91. furi_assert(detect_reader);
  92. with_view_model(
  93. detect_reader->view,
  94. DetectReaderViewModel * model,
  95. { furi_string_free(model->uid_str); },
  96. false);
  97. view_free(detect_reader->view);
  98. free(detect_reader);
  99. }
  100. void detect_reader_reset(DetectReader* detect_reader) {
  101. furi_assert(detect_reader);
  102. with_view_model(
  103. detect_reader->view,
  104. DetectReaderViewModel * model,
  105. {
  106. model->nonces = 0;
  107. model->nonces_max = 0;
  108. model->state = DetectReaderStateStart;
  109. furi_string_reset(model->uid_str);
  110. },
  111. false);
  112. }
  113. View* detect_reader_get_view(DetectReader* detect_reader) {
  114. furi_assert(detect_reader);
  115. return detect_reader->view;
  116. }
  117. void detect_reader_set_callback(
  118. DetectReader* detect_reader,
  119. DetectReaderDoneCallback callback,
  120. void* context) {
  121. furi_assert(detect_reader);
  122. furi_assert(callback);
  123. detect_reader->callback = callback;
  124. detect_reader->context = context;
  125. }
  126. void detect_reader_set_nonces_max(DetectReader* detect_reader, uint16_t nonces_max) {
  127. furi_assert(detect_reader);
  128. with_view_model(
  129. detect_reader->view,
  130. DetectReaderViewModel * model,
  131. { model->nonces_max = nonces_max; },
  132. false);
  133. }
  134. void detect_reader_set_nonces_collected(DetectReader* detect_reader, uint16_t nonces_collected) {
  135. furi_assert(detect_reader);
  136. with_view_model(
  137. detect_reader->view,
  138. DetectReaderViewModel * model,
  139. { model->nonces = nonces_collected; },
  140. false);
  141. }
  142. void detect_reader_set_state(DetectReader* detect_reader, DetectReaderState state) {
  143. furi_assert(detect_reader);
  144. with_view_model(
  145. detect_reader->view, DetectReaderViewModel * model, { model->state = state; }, true);
  146. }
  147. void detect_reader_set_uid(DetectReader* detect_reader, uint8_t* uid, uint8_t uid_len) {
  148. furi_assert(detect_reader);
  149. furi_assert(uid);
  150. furi_assert(uid_len < DETECT_READER_UID_MAX_LEN);
  151. with_view_model(
  152. detect_reader->view,
  153. DetectReaderViewModel * model,
  154. {
  155. furi_string_set_str(model->uid_str, "UID:");
  156. for(size_t i = 0; i < uid_len; i++) {
  157. furi_string_cat_printf(model->uid_str, " %02X", uid[i]);
  158. }
  159. },
  160. true);
  161. }