nfc.c 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. #include "nfc_i.h"
  2. #include "api-hal-nfc.h"
  3. osMessageQueueId_t message_queue = NULL;
  4. uint32_t nfc_view_stop(void* context) {
  5. furi_assert(message_queue);
  6. NfcMessage message;
  7. message.type = NfcMessageTypeStop;
  8. furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
  9. return NfcViewMenu;
  10. }
  11. uint32_t nfc_view_exit(void* context) {
  12. furi_assert(message_queue);
  13. NfcMessage message;
  14. message.type = NfcMessageTypeExit;
  15. furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
  16. return VIEW_NONE;
  17. }
  18. void nfc_menu_callback(void* context, uint32_t index) {
  19. furi_assert(message_queue);
  20. NfcMessage message;
  21. message.type = index;
  22. furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
  23. }
  24. Nfc* nfc_alloc() {
  25. Nfc* nfc = furi_alloc(sizeof(Nfc));
  26. message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL);
  27. nfc->worker = nfc_worker_alloc(message_queue);
  28. // Open GUI record
  29. nfc->gui = furi_record_open("gui");
  30. // View Dispatcher
  31. nfc->view_dispatcher = view_dispatcher_alloc();
  32. view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
  33. // Menu
  34. nfc->submenu = submenu_alloc();
  35. submenu_add_item(nfc->submenu, "Detect", NfcMessageTypeDetect, nfc_menu_callback, nfc);
  36. submenu_add_item(nfc->submenu, "Read EMV", NfcMessageTypeReadEMV, nfc_menu_callback, nfc);
  37. submenu_add_item(
  38. nfc->submenu, "Emulate EMV", NfcMessageTypeEmulateEMV, nfc_menu_callback, nfc);
  39. submenu_add_item(nfc->submenu, "Emulate", NfcMessageTypeEmulate, nfc_menu_callback, nfc);
  40. submenu_add_item(nfc->submenu, "Field", NfcMessageTypeField, nfc_menu_callback, nfc);
  41. submenu_add_item(
  42. nfc->submenu, "Read MfUltralight", NfcMessageTypeReadMfUltralight, nfc_menu_callback, nfc);
  43. View* submenu_view = submenu_get_view(nfc->submenu);
  44. view_set_previous_callback(submenu_view, nfc_view_exit);
  45. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_view);
  46. // Detect
  47. nfc->view_detect = view_alloc();
  48. view_set_context(nfc->view_detect, nfc);
  49. view_set_draw_callback(nfc->view_detect, nfc_view_read_draw);
  50. view_set_previous_callback(nfc->view_detect, nfc_view_stop);
  51. view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  52. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect);
  53. // Read EMV
  54. nfc->view_read_emv = view_alloc();
  55. view_set_context(nfc->view_read_emv, nfc);
  56. view_set_draw_callback(nfc->view_read_emv, nfc_view_read_emv_draw);
  57. view_set_previous_callback(nfc->view_read_emv, nfc_view_stop);
  58. view_allocate_model(nfc->view_read_emv, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  59. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewReadEmv, nfc->view_read_emv);
  60. // Emulate EMV
  61. nfc->view_emulate_emv = view_alloc();
  62. view_set_context(nfc->view_emulate_emv, nfc);
  63. view_set_draw_callback(nfc->view_emulate_emv, nfc_view_emulate_emv_draw);
  64. view_set_previous_callback(nfc->view_emulate_emv, nfc_view_stop);
  65. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulateEMV, nfc->view_emulate_emv);
  66. // Emulate
  67. nfc->view_emulate = view_alloc();
  68. view_set_context(nfc->view_emulate, nfc);
  69. view_set_draw_callback(nfc->view_emulate, nfc_view_emulate_draw);
  70. view_set_previous_callback(nfc->view_emulate, nfc_view_stop);
  71. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulate, nfc->view_emulate);
  72. // Field
  73. nfc->view_field = view_alloc();
  74. view_set_context(nfc->view_field, nfc);
  75. view_set_draw_callback(nfc->view_field, nfc_view_field_draw);
  76. view_set_previous_callback(nfc->view_field, nfc_view_stop);
  77. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field);
  78. // Read Mifare Ultralight
  79. nfc->view_read_mf_ultralight = view_alloc();
  80. view_set_context(nfc->view_read_mf_ultralight, nfc);
  81. view_set_draw_callback(nfc->view_read_mf_ultralight, nfc_view_read_mf_ultralight_draw);
  82. view_set_previous_callback(nfc->view_read_mf_ultralight, nfc_view_stop);
  83. view_allocate_model(
  84. nfc->view_read_mf_ultralight, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  85. view_dispatcher_add_view(
  86. nfc->view_dispatcher, NfcViewReadMfUltralight, nfc->view_read_mf_ultralight);
  87. // Error
  88. nfc->view_error = view_alloc();
  89. view_set_context(nfc->view_error, nfc);
  90. view_set_draw_callback(nfc->view_error, nfc_view_error_draw);
  91. view_set_previous_callback(nfc->view_error, nfc_view_stop);
  92. view_allocate_model(nfc->view_error, ViewModelTypeLockFree, sizeof(NfcViewErrorModel));
  93. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewError, nfc->view_error);
  94. // Switch to menu
  95. view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
  96. return nfc;
  97. }
  98. void nfc_free(Nfc* nfc) {
  99. // Free nfc worker
  100. nfc_worker_free(nfc->worker);
  101. // Free allocated queue
  102. osMessageQueueDelete(message_queue);
  103. message_queue = NULL;
  104. // Free allocated views
  105. // Menu
  106. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
  107. submenu_free(nfc->submenu);
  108. // Detect
  109. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewRead);
  110. view_free(nfc->view_detect);
  111. // Read EMV
  112. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewReadEmv);
  113. view_free(nfc->view_read_emv);
  114. // Emulate EMV
  115. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewEmulateEMV);
  116. view_free(nfc->view_emulate_emv);
  117. // Emulate
  118. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewEmulate);
  119. view_free(nfc->view_emulate);
  120. // Field
  121. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewField);
  122. view_free(nfc->view_field);
  123. // Read Mifare Ultralight
  124. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewReadMfUltralight);
  125. view_free(nfc->view_read_mf_ultralight);
  126. // Error
  127. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewError);
  128. view_free(nfc->view_error);
  129. // Free View Dispatcher
  130. view_dispatcher_free(nfc->view_dispatcher);
  131. // Close all opened records
  132. furi_record_close("gui");
  133. nfc->gui = NULL;
  134. // Free nfc object
  135. free(nfc);
  136. }
  137. void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
  138. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  139. if(state == NfcWorkerStateBroken) {
  140. with_view_model(
  141. nfc->view_error, (NfcViewErrorModel * model) {
  142. model->error = nfc_worker_get_error(nfc->worker);
  143. return true;
  144. });
  145. view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewError);
  146. } else if(state == NfcWorkerStateReady) {
  147. view_dispatcher_switch_to_view(nfc->view_dispatcher, view_id);
  148. nfc_worker_start(nfc->worker, worker_state);
  149. }
  150. }
  151. int32_t nfc_task(void* p) {
  152. Nfc* nfc = nfc_alloc();
  153. NfcMessage message;
  154. while(1) {
  155. furi_check(osMessageQueueGet(message_queue, &message, NULL, osWaitForever) == osOK);
  156. if(message.type == NfcMessageTypeDetect) {
  157. with_view_model(
  158. nfc->view_detect, (NfcViewReadModel * model) {
  159. model->found = false;
  160. return true;
  161. });
  162. nfc_start(nfc, NfcViewRead, NfcWorkerStatePoll);
  163. } else if(message.type == NfcMessageTypeReadEMV) {
  164. with_view_model(
  165. nfc->view_read_emv, (NfcViewReadModel * model) {
  166. model->found = false;
  167. return true;
  168. });
  169. nfc_start(nfc, NfcViewReadEmv, NfcWorkerStateReadEMV);
  170. } else if(message.type == NfcMessageTypeEmulateEMV) {
  171. nfc_start(nfc, NfcViewEmulateEMV, NfcWorkerStateEmulateEMV);
  172. } else if(message.type == NfcMessageTypeEmulate) {
  173. nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
  174. } else if(message.type == NfcMessageTypeField) {
  175. nfc_start(nfc, NfcViewField, NfcWorkerStateField);
  176. } else if(message.type == NfcMessageTypeReadMfUltralight) {
  177. nfc_start(nfc, NfcViewReadMfUltralight, NfcWorkerStateReadMfUltralight);
  178. } else if(message.type == NfcMessageTypeStop) {
  179. nfc_worker_stop(nfc->worker);
  180. } else if(message.type == NfcMessageTypeDeviceFound) {
  181. with_view_model(
  182. nfc->view_detect, (NfcViewReadModel * model) {
  183. model->found = true;
  184. model->device = message.device;
  185. return true;
  186. });
  187. } else if(message.type == NfcMessageTypeDeviceNotFound) {
  188. with_view_model(
  189. nfc->view_detect, (NfcViewReadModel * model) {
  190. model->found = false;
  191. return true;
  192. });
  193. } else if(message.type == NfcMessageTypeEMVFound) {
  194. with_view_model(
  195. nfc->view_read_emv, (NfcViewReadModel * model) {
  196. model->found = true;
  197. model->device = message.device;
  198. return true;
  199. });
  200. } else if(message.type == NfcMessageTypeEMVNotFound) {
  201. with_view_model(
  202. nfc->view_read_emv, (NfcViewReadModel * model) {
  203. model->found = false;
  204. return true;
  205. });
  206. } else if(message.type == NfcMessageTypeMfUlFound) {
  207. with_view_model(
  208. nfc->view_read_mf_ultralight, (NfcViewReadModel * model) {
  209. model->found = true;
  210. model->device = message.device;
  211. return true;
  212. });
  213. } else if(message.type == NfcMessageTypeMfUlNotFound) {
  214. with_view_model(
  215. nfc->view_read_mf_ultralight, (NfcViewReadModel * model) {
  216. model->found = false;
  217. return true;
  218. });
  219. } else if(message.type == NfcMessageTypeExit) {
  220. nfc_free(nfc);
  221. break;
  222. }
  223. }
  224. return 0;
  225. }