nfc.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. #include "nfc_i.h"
  2. uint32_t nfc_view_exit(void* context) {
  3. furi_assert(context);
  4. Nfc* nfc = context;
  5. NfcMessage message;
  6. message.type = NfcMessageTypeStop;
  7. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  8. return VIEW_NONE;
  9. }
  10. Nfc* nfc_alloc() {
  11. Nfc* nfc = furi_alloc(sizeof(Nfc));
  12. nfc->message_queue = osMessageQueueNew(8, sizeof(NfcMessage), NULL);
  13. nfc->cli_message_queue = osMessageQueueNew(1, sizeof(NfcMessage), NULL);
  14. nfc->worker = nfc_worker_alloc(nfc->message_queue);
  15. nfc->icon = assets_icons_get(A_NFC_14);
  16. nfc->menu_vm = furi_record_open("menu");
  17. nfc->menu = menu_item_alloc_menu("NFC", nfc->icon);
  18. menu_item_subitem_add(
  19. nfc->menu, menu_item_alloc_function("Detect", NULL, nfc_menu_detect_callback, nfc));
  20. menu_item_subitem_add(
  21. nfc->menu, menu_item_alloc_function("Emulate", NULL, nfc_menu_emulate_callback, nfc));
  22. menu_item_subitem_add(
  23. nfc->menu, menu_item_alloc_function("Field", NULL, nfc_menu_field_callback, nfc));
  24. nfc->view_detect = view_alloc();
  25. view_set_context(nfc->view_detect, nfc);
  26. view_set_draw_callback(nfc->view_detect, nfc_view_read_draw);
  27. view_set_previous_callback(nfc->view_detect, nfc_view_exit);
  28. view_allocate_model(nfc->view_detect, ViewModelTypeLocking, sizeof(NfcViewReadModel));
  29. nfc->view_emulate = view_alloc();
  30. view_set_context(nfc->view_emulate, nfc);
  31. view_set_draw_callback(nfc->view_emulate, nfc_view_emulate_draw);
  32. view_set_previous_callback(nfc->view_emulate, nfc_view_exit);
  33. nfc->view_field = view_alloc();
  34. view_set_context(nfc->view_field, nfc);
  35. view_set_draw_callback(nfc->view_field, nfc_view_field_draw);
  36. view_set_previous_callback(nfc->view_field, nfc_view_exit);
  37. nfc->view_cli = view_alloc();
  38. view_set_context(nfc->view_cli, nfc);
  39. view_set_draw_callback(nfc->view_cli, nfc_view_cli_draw);
  40. nfc->view_error = view_alloc();
  41. view_set_context(nfc->view_error, nfc);
  42. view_set_draw_callback(nfc->view_error, nfc_view_error_draw);
  43. view_set_previous_callback(nfc->view_error, nfc_view_exit);
  44. view_allocate_model(nfc->view_error, ViewModelTypeLockFree, sizeof(NfcViewErrorModel));
  45. nfc->view_dispatcher = view_dispatcher_alloc();
  46. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewRead, nfc->view_detect);
  47. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewEmulate, nfc->view_emulate);
  48. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewField, nfc->view_field);
  49. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewCli, nfc->view_cli);
  50. view_dispatcher_add_view(nfc->view_dispatcher, NfcViewError, nfc->view_error);
  51. return nfc;
  52. }
  53. void nfc_menu_detect_callback(void* context) {
  54. furi_assert(context);
  55. Nfc* nfc = context;
  56. NfcMessage message;
  57. message.type = NfcMessageTypeDetect;
  58. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  59. }
  60. void nfc_menu_emulate_callback(void* context) {
  61. furi_assert(context);
  62. Nfc* nfc = context;
  63. NfcMessage message;
  64. message.type = NfcMessageTypeEmulate;
  65. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  66. }
  67. void nfc_menu_field_callback(void* context) {
  68. furi_assert(context);
  69. Nfc* nfc = context;
  70. NfcMessage message;
  71. message.type = NfcMessageTypeField;
  72. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  73. }
  74. void nfc_menu_field_off_callback(void* context) {
  75. furi_assert(context);
  76. Nfc* nfc = context;
  77. NfcMessage message;
  78. message.type = NfcMessageTypeField;
  79. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  80. }
  81. void nfc_cli_detect(string_t args, void* context) {
  82. furi_assert(context);
  83. Nfc* nfc = context;
  84. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  85. if(state != NfcWorkerStateReady) {
  86. printf("Nfc is busy");
  87. return;
  88. }
  89. NfcMessage message;
  90. message.type = NfcMessageTypeDetectCliCmd;
  91. furi_check(osMessageQueuePut(nfc->message_queue, &message, 0, osWaitForever) == osOK);
  92. // Wait until nfc task send response
  93. furi_check(osMessageQueueGet(nfc->cli_message_queue, &message, NULL, osWaitForever) == osOK);
  94. if(message.type == NfcMessageTypeDeviceFound) {
  95. if(message.device.type == NfcDeviceTypeNfca) {
  96. printf(
  97. "Found NFC-A, type: %s, UID length: %d, UID:",
  98. nfc_get_nfca_type(message.device.nfca.type),
  99. message.device.nfca.nfcId1Len);
  100. for(uint8_t i = 0; i < message.device.nfca.nfcId1Len; i++) {
  101. printf("%02X", message.device.nfca.nfcId1[i]);
  102. }
  103. printf(
  104. " SAK: %02X ATQA: %02X/%02X",
  105. message.device.nfca.selRes.sak,
  106. message.device.nfca.sensRes.anticollisionInfo,
  107. message.device.nfca.sensRes.platformInfo);
  108. } else if(message.device.type == NfcDeviceTypeNfcb) {
  109. printf("Found NFC-B, UID length: %d, UID:", RFAL_NFCB_NFCID0_LEN);
  110. for(uint8_t i = 0; i < RFAL_NFCB_NFCID0_LEN; i++) {
  111. printf("%02X", message.device.nfcb.sensbRes.nfcid0[i]);
  112. }
  113. } else if(message.device.type == NfcDeviceTypeNfcv) {
  114. printf("Found NFC-V, UID length: %d, UID:", RFAL_NFCV_UID_LEN);
  115. for(uint8_t i = 0; i < RFAL_NFCV_UID_LEN; i++) {
  116. printf("%02X", message.device.nfcv.InvRes.UID[i]);
  117. }
  118. } else if(message.device.type == NfcDeviceTypeNfcf) {
  119. printf("Found NFC-F, UID length: %d, UID:", RFAL_NFCF_NFCID2_LEN);
  120. for(uint8_t i = 0; i < RFAL_NFCF_NFCID2_LEN; i++) {
  121. printf("%02X", message.device.nfcf.sensfRes.NFCID2[i]);
  122. }
  123. }
  124. } else {
  125. printf("Device not found");
  126. }
  127. }
  128. void nfc_start(Nfc* nfc, NfcView view_id, NfcWorkerState worker_state) {
  129. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  130. if(state == NfcWorkerStateBroken) {
  131. with_view_model(
  132. nfc->view_error, (NfcViewErrorModel * model) {
  133. model->error = nfc_worker_get_error(nfc->worker);
  134. return true;
  135. });
  136. view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewError);
  137. } else if(state == NfcWorkerStateReady) {
  138. view_dispatcher_switch_to_view(nfc->view_dispatcher, view_id);
  139. nfc_worker_start(nfc->worker, worker_state);
  140. }
  141. }
  142. int32_t nfc_task(void* p) {
  143. Nfc* nfc = nfc_alloc();
  144. Gui* gui = furi_record_open("gui");
  145. view_dispatcher_attach_to_gui(nfc->view_dispatcher, gui, ViewDispatcherTypeFullscreen);
  146. nfc->cli = furi_record_open("cli");
  147. if(nfc->cli) {
  148. cli_add_command(nfc->cli, "nfc_detect", nfc_cli_detect, nfc);
  149. }
  150. with_value_mutex(
  151. nfc->menu_vm, (Menu * menu) { menu_item_add(menu, nfc->menu); });
  152. furi_record_create("nfc", nfc);
  153. NfcMessage message;
  154. while(1) {
  155. furi_check(osMessageQueueGet(nfc->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 == NfcMessageTypeDetectCliCmd) {
  164. nfc_start(nfc, NfcViewCli, NfcWorkerStatePollOnce);
  165. } else if(message.type == NfcMessageTypeEmulate) {
  166. nfc_start(nfc, NfcViewEmulate, NfcWorkerStateEmulate);
  167. } else if(message.type == NfcMessageTypeField) {
  168. nfc_start(nfc, NfcViewField, NfcWorkerStateField);
  169. } else if(message.type == NfcMessageTypeStop) {
  170. nfc_worker_stop(nfc->worker);
  171. } else if(message.type == NfcMessageTypeDeviceFound) {
  172. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  173. if(state == NfcWorkerStatePollOnce) {
  174. view_dispatcher_switch_to_view(nfc->view_dispatcher, VIEW_NONE);
  175. furi_check(
  176. osMessageQueuePut(nfc->cli_message_queue, &message, 0, osWaitForever) == osOK);
  177. nfc_worker_stop(nfc->worker);
  178. } else {
  179. with_view_model(
  180. nfc->view_detect, (NfcViewReadModel * model) {
  181. model->found = true;
  182. model->device = message.device;
  183. return true;
  184. });
  185. }
  186. } else if(message.type == NfcMessageTypeDeviceNotFound) {
  187. NfcWorkerState state = nfc_worker_get_state(nfc->worker);
  188. if(state == NfcWorkerStatePollOnce) {
  189. view_dispatcher_switch_to_view(nfc->view_dispatcher, VIEW_NONE);
  190. furi_check(
  191. osMessageQueuePut(nfc->cli_message_queue, &message, 0, osWaitForever) == osOK);
  192. nfc_worker_stop(nfc->worker);
  193. } else {
  194. with_view_model(
  195. nfc->view_detect, (NfcViewReadModel * model) {
  196. model->found = false;
  197. return true;
  198. });
  199. }
  200. }
  201. }
  202. return 0;
  203. }