nfc.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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. if(index == 0) {
  22. message.type = NfcMessageTypeDetect;
  23. } else if(index == 1) {
  24. message.type = NfcMessageTypeReadEMV;
  25. } else if(index == 2) {
  26. message.type = NfcMessageTypeEmulate;
  27. } else if(index == 3) {
  28. message.type = NfcMessageTypeField;
  29. }
  30. furi_check(osMessageQueuePut(message_queue, &message, 0, osWaitForever) == osOK);
  31. }
  32. Nfc* nfc_alloc() {
  33. Nfc* nfc = furi_alloc(sizeof(Nfc));
  34. message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL);
  35. nfc->worker = nfc_worker_alloc(message_queue);
  36. // Open GUI record
  37. nfc->gui = furi_record_open("gui");
  38. // View Dispatcher
  39. nfc->view_dispatcher = view_dispatcher_alloc();
  40. view_dispatcher_attach_to_gui(nfc->view_dispatcher, nfc->gui, ViewDispatcherTypeFullscreen);
  41. // Menu
  42. nfc->submenu = submenu_alloc();
  43. submenu_add_item(nfc->submenu, "Detect", 0, nfc_menu_callback, nfc);
  44. submenu_add_item(nfc->submenu, "Read EMV", 1, nfc_menu_callback, nfc);
  45. submenu_add_item(nfc->submenu, "Emulate", 2, nfc_menu_callback, nfc);
  46. submenu_add_item(nfc->submenu, "Field", 3, nfc_menu_callback, nfc);
  47. View* submenu_view = submenu_get_view(nfc->submenu);
  48. view_set_previous_callback(submenu_view, nfc_view_exit);
  49. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewMenu, submenu_view);
  50. // Detect
  51. nfc->view_detect = view_alloc();
  52. view_set_context(nfc->view_detect, nfc);
  53. view_set_draw_callback(nfc->view_detect, nfc_view_read_draw);
  54. view_set_previous_callback(nfc->view_detect, nfc_view_stop);
  55. view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  56. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect);
  57. // Read EMV
  58. nfc->view_read_emv = view_alloc();
  59. view_set_context(nfc->view_read_emv, nfc);
  60. view_set_draw_callback(nfc->view_read_emv, nfc_view_read_emv_draw);
  61. view_set_previous_callback(nfc->view_read_emv, nfc_view_stop);
  62. view_allocate_model(nfc->view_read_emv, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  63. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewReadEmv, nfc->view_read_emv);
  64. // Emulate
  65. nfc->view_emulate = view_alloc();
  66. view_set_context(nfc->view_emulate, nfc);
  67. view_set_draw_callback(nfc->view_emulate, nfc_view_emulate_draw);
  68. view_set_previous_callback(nfc->view_emulate, nfc_view_stop);
  69. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulate, nfc->view_emulate);
  70. // Field
  71. nfc->view_field = view_alloc();
  72. view_set_context(nfc->view_field, nfc);
  73. view_set_draw_callback(nfc->view_field, nfc_view_field_draw);
  74. view_set_previous_callback(nfc->view_field, nfc_view_stop);
  75. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field);
  76. // Error
  77. nfc->view_error = view_alloc();
  78. view_set_context(nfc->view_error, nfc);
  79. view_set_draw_callback(nfc->view_error, nfc_view_error_draw);
  80. view_set_previous_callback(nfc->view_error, nfc_view_stop);
  81. view_allocate_model(nfc->view_error, ViewModelTypeLockFree, sizeof(NfcViewErrorModel));
  82. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewError, nfc->view_error);
  83. // Switch to menu
  84. view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewMenu);
  85. return nfc;
  86. }
  87. void nfc_free(Nfc* nfc) {
  88. // Free nfc worker
  89. nfc_worker_free(nfc->worker);
  90. // Free allocated queue
  91. osMessageQueueDelete(message_queue);
  92. message_queue = NULL;
  93. // Free allocated views
  94. // Menu
  95. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewMenu);
  96. submenu_free(nfc->submenu);
  97. // Detect
  98. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewRead);
  99. view_free(nfc->view_detect);
  100. // Emulate
  101. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewEmulate);
  102. view_free(nfc->view_emulate);
  103. // Field
  104. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewField);
  105. view_free(nfc->view_field);
  106. // Error
  107. view_dispatcher_remove_view(nfc->view_dispatcher, NfcViewError);
  108. view_free(nfc->view_error);
  109. // Free View Dispatcher
  110. view_dispatcher_free(nfc->view_dispatcher);
  111. // Close all opened records
  112. furi_record_close("gui");
  113. nfc->gui = NULL;
  114. // Free nfc object
  115. free(nfc);
  116. }
  117. void nfc_cli_detect(Cli* cli, string_t args, void* context) {
  118. // Check if nfc worker is not busy
  119. if(api_hal_nfc_is_busy()) {
  120. printf("Nfc is busy");
  121. return;
  122. }
  123. rfalNfcDevice* dev_list;
  124. uint8_t dev_cnt = 0;
  125. bool cmd_exit = false;
  126. api_hal_nfc_init();
  127. printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n");
  128. while(!cmd_exit) {
  129. cmd_exit |= cli_cmd_interrupt_received(cli);
  130. cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true);
  131. if(dev_cnt > 0) {
  132. printf("Found %d devices\r\n", dev_cnt);
  133. for(uint8_t i = 0; i < dev_cnt; i++) {
  134. printf("%d found: %s ", i, nfc_get_dev_type(dev_list[i].type));
  135. if(dev_list[i].type == RFAL_NFC_LISTEN_TYPE_NFCA) {
  136. printf("type: %s, ", nfc_get_nfca_type(dev_list[i].dev.nfca.type));
  137. }
  138. printf("UID length: %d, UID:", dev_list[i].nfcidLen);
  139. for(uint8_t j = 0; j < dev_list[i].nfcidLen; j++) {
  140. printf("%02X", dev_list[i].nfcid[j]);
  141. }
  142. printf("\r\n");
  143. }
  144. }
  145. osDelay(50);
  146. }
  147. }
  148. void nfc_cli_init() {
  149. Cli* cli = furi_record_open("cli");
  150. cli_add_command(cli, "nfc_detect", nfc_cli_detect, NULL);
  151. furi_record_close("cli");
  152. }
  153. void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
  154. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  155. if(state == NfcWorkerStateBroken) {
  156. with_view_model(
  157. nfc->view_error, (NfcViewErrorModel * model) {
  158. model->error = nfc_worker_get_error(nfc->worker);
  159. return true;
  160. });
  161. view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewError);
  162. } else if(state == NfcWorkerStateReady) {
  163. view_dispatcher_switch_to_view(nfc->view_dispatcher, view_id);
  164. nfc_worker_start(nfc->worker, worker_state);
  165. }
  166. }
  167. int32_t nfc_task(void* p) {
  168. Nfc* nfc = nfc_alloc();
  169. NfcMessage message;
  170. while(1) {
  171. furi_check(osMessageQueueGet(message_queue, &message, NULL, osWaitForever) == osOK);
  172. if(message.type == NfcMessageTypeDetect) {
  173. with_view_model(
  174. nfc->view_detect, (NfcViewReadModel * model) {
  175. model->found = false;
  176. return true;
  177. });
  178. nfc_start(nfc, NfcViewRead, NfcWorkerStatePoll);
  179. } else if(message.type == NfcMessageTypeReadEMV) {
  180. with_view_model(
  181. nfc->view_read_emv, (NfcViewReadModel * model) {
  182. model->found = false;
  183. return true;
  184. });
  185. nfc_start(nfc, NfcViewReadEmv, NfcWorkerStateReadEMV);
  186. } else if(message.type == NfcMessageTypeEmulate) {
  187. nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
  188. } else if(message.type == NfcMessageTypeField) {
  189. nfc_start(nfc, NfcViewField, NfcWorkerStateField);
  190. } else if(message.type == NfcMessageTypeStop) {
  191. nfc_worker_stop(nfc->worker);
  192. } else if(message.type == NfcMessageTypeDeviceFound) {
  193. with_view_model(
  194. nfc->view_detect, (NfcViewReadModel * model) {
  195. model->found = true;
  196. model->device = message.device;
  197. return true;
  198. });
  199. } else if(message.type == NfcMessageTypeDeviceNotFound) {
  200. with_view_model(
  201. nfc->view_detect, (NfcViewReadModel * model) {
  202. model->found = false;
  203. return true;
  204. });
  205. } else if(message.type == NfcMessageTypeEMVFound) {
  206. with_view_model(
  207. nfc->view_read_emv, (NfcViewReadModel * model) {
  208. model->found = true;
  209. model->device = message.device;
  210. return true;
  211. });
  212. } else if(message.type == NfcMessageTypeEMVNotFound) {
  213. with_view_model(
  214. nfc->view_read_emv, (NfcViewReadModel * model) {
  215. model->found = false;
  216. return true;
  217. });
  218. } else if(message.type == NfcMessageTypeExit) {
  219. nfc_free(nfc);
  220. break;
  221. }
  222. }
  223. return 0;
  224. }