metroflip_scene_auto.c 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232
  1. #include "../metroflip_i.h"
  2. #include <dolphin/dolphin.h>
  3. #include <furi.h>
  4. #include <bit_lib.h>
  5. #include <lib/nfc/protocols/nfc_protocol.h>
  6. #include <nfc/protocols/mf_classic/mf_classic_poller_sync.h>
  7. #include <nfc/protocols/mf_classic/mf_classic.h>
  8. #include <nfc/protocols/mf_classic/mf_classic_poller.h>
  9. #include "keys.h"
  10. #include "desfire.h"
  11. #include <nfc/protocols/mf_desfire/mf_desfire_poller.h>
  12. #include <lib/nfc/protocols/mf_desfire/mf_desfire.h>
  13. #define TAG "Metroflip:Scene:Auto"
  14. static NfcCommand
  15. metroflip_scene_detect_desfire_poller_callback(NfcGenericEvent event, void* context) {
  16. furi_assert(event.protocol == NfcProtocolMfDesfire);
  17. Metroflip* app = context;
  18. NfcCommand command = NfcCommandContinue;
  19. FuriString* parsed_data = furi_string_alloc();
  20. furi_string_reset(app->text_box_store);
  21. const MfDesfirePollerEvent* mf_desfire_event = event.event_data;
  22. if(mf_desfire_event->type == MfDesfirePollerEventTypeReadSuccess) {
  23. nfc_device_set_data(
  24. app->nfc_device, NfcProtocolMfDesfire, nfc_poller_get_data(app->poller));
  25. if(clipper_parse(app->nfc_device, parsed_data)) {
  26. furi_string_reset(app->text_box_store);
  27. view_dispatcher_send_custom_event(
  28. app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  29. app->desfire_card_type = CARD_TYPE_CLIPPER;
  30. } else if(itso_parse(app->nfc_device, parsed_data)) {
  31. furi_string_reset(app->text_box_store);
  32. view_dispatcher_send_custom_event(
  33. app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  34. app->desfire_card_type = CARD_TYPE_ITSO;
  35. } else if(myki_parse(app->nfc_device, parsed_data)) {
  36. furi_string_reset(app->text_box_store);
  37. view_dispatcher_send_custom_event(
  38. app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  39. app->desfire_card_type = CARD_TYPE_MYKI;
  40. } else if(opal_parse(app->nfc_device, parsed_data)) {
  41. furi_string_reset(app->text_box_store);
  42. view_dispatcher_send_custom_event(
  43. app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  44. app->desfire_card_type = CARD_TYPE_OPAL;
  45. } else {
  46. furi_string_reset(app->text_box_store);
  47. view_dispatcher_send_custom_event(
  48. app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  49. app->desfire_card_type = CARD_TYPE_DESFIRE_UNKNOWN;
  50. }
  51. furi_string_free(parsed_data);
  52. command = NfcCommandStop;
  53. } else if(mf_desfire_event->type == MfDesfirePollerEventTypeReadFailed) {
  54. view_dispatcher_send_custom_event(app->view_dispatcher, MetroflipCustomEventPollerSuccess);
  55. app->desfire_card_type = CARD_TYPE_DESFIRE_UNKNOWN;
  56. command = NfcCommandContinue;
  57. }
  58. return command;
  59. }
  60. void metroflip_scene_detect_scan_callback(NfcScannerEvent event, void* context) {
  61. furi_assert(context);
  62. Metroflip* app = context;
  63. if(event.type == NfcScannerEventTypeDetected) {
  64. view_dispatcher_send_custom_event(app->view_dispatcher, MetroflipCustomEventCardDetected);
  65. if(event.data.protocols && *event.data.protocols == NfcProtocolMfClassic) {
  66. nfc_detected_protocols_set(
  67. app->detected_protocols, event.data.protocols, event.data.protocol_num);
  68. view_dispatcher_send_custom_event(
  69. app->view_dispatcher, MetroflipCustomEventPollerDetect);
  70. } else if(event.data.protocols && *event.data.protocols == NfcProtocolIso14443_4b) {
  71. nfc_detected_protocols_set(
  72. app->detected_protocols, event.data.protocols, event.data.protocol_num);
  73. view_dispatcher_send_custom_event(
  74. app->view_dispatcher, MetroflipCustomEventPollerDetect);
  75. } else if(event.data.protocols && *event.data.protocols == NfcProtocolMfDesfire) {
  76. nfc_detected_protocols_set(
  77. app->detected_protocols, event.data.protocols, event.data.protocol_num);
  78. view_dispatcher_send_custom_event(
  79. app->view_dispatcher, MetroflipCustomEventPollerDetect);
  80. } else {
  81. const NfcProtocol* invalid_protocol = (const NfcProtocol*)NfcProtocolInvalid;
  82. nfc_detected_protocols_set(
  83. app->detected_protocols, invalid_protocol, event.data.protocol_num);
  84. }
  85. }
  86. }
  87. void metroflip_scene_auto_on_enter(void* context) {
  88. Metroflip* app = context;
  89. dolphin_deed(DolphinDeedNfcRead);
  90. app->sec_num = 0;
  91. // Setup view
  92. Popup* popup = app->popup;
  93. popup_set_header(popup, "Apply\n card to\nthe back", 68, 30, AlignLeft, AlignTop);
  94. popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
  95. // Start worker
  96. view_dispatcher_switch_to_view(app->view_dispatcher, MetroflipViewPopup);
  97. app->scanner = nfc_scanner_alloc(app->nfc);
  98. nfc_scanner_start(app->scanner, metroflip_scene_detect_scan_callback, app);
  99. metroflip_app_blink_start(app);
  100. }
  101. bool metroflip_scene_auto_on_event(void* context, SceneManagerEvent event) {
  102. Metroflip* app = context;
  103. UNUSED(app);
  104. bool consumed = false;
  105. if(event.type == SceneManagerEventTypeCustom) {
  106. if(event.event == MetroflipCustomEventCardDetected) {
  107. Popup* popup = app->popup;
  108. popup_set_header(popup, "DON'T\nMOVE", 68, 30, AlignLeft, AlignTop);
  109. consumed = true;
  110. } else if(event.event == MetroflipCustomEventPollerSuccess) {
  111. nfc_poller_stop(app->poller);
  112. nfc_poller_free(app->poller);
  113. if(app->desfire_card_type == CARD_TYPE_CLIPPER) {
  114. scene_manager_next_scene(app->scene_manager, MetroflipSceneClipper);
  115. } else if(app->desfire_card_type == CARD_TYPE_OPAL) {
  116. scene_manager_next_scene(app->scene_manager, MetroflipSceneOpal);
  117. } else if(app->desfire_card_type == CARD_TYPE_MYKI) {
  118. scene_manager_next_scene(app->scene_manager, MetroflipSceneClipper);
  119. } else if(app->desfire_card_type == CARD_TYPE_ITSO) {
  120. scene_manager_next_scene(app->scene_manager, MetroflipSceneItso);
  121. } else if(app->desfire_card_type == CARD_TYPE_DESFIRE_UNKNOWN) {
  122. Popup* popup = app->popup;
  123. popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  124. } else {
  125. Popup* popup = app->popup;
  126. popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  127. }
  128. consumed = true;
  129. } else if(event.event == MetroflipCustomEventCardLost) {
  130. Popup* popup = app->popup;
  131. popup_set_header(popup, "Card \n lost", 68, 30, AlignLeft, AlignTop);
  132. consumed = true;
  133. } else if(event.event == MetroflipCustomEventWrongCard) {
  134. Popup* popup = app->popup;
  135. popup_set_header(popup, "WRONG \n CARD", 68, 30, AlignLeft, AlignTop);
  136. consumed = true;
  137. } else if(event.event == MetroflipCustomEventPollerFail) {
  138. Popup* popup = app->popup;
  139. popup_set_header(popup, "Failed", 68, 30, AlignLeft, AlignTop);
  140. consumed = true;
  141. } else if(event.event == MetroflipCustomEventPollerDetect) {
  142. nfc_scanner_stop(app->scanner);
  143. nfc_scanner_free(app->scanner);
  144. app->auto_mode = true;
  145. if(nfc_detected_protocols_get_protocol(app->detected_protocols, 0) ==
  146. NfcProtocolMfClassic) {
  147. CardType card_type = determine_card_type(app->nfc);
  148. app->mfc_card_type = card_type;
  149. Popup* popup = app->popup;
  150. UNUSED(popup);
  151. switch(card_type) {
  152. case CARD_TYPE_METROMONEY:
  153. FURI_LOG_I(TAG, "Detected: Metromoney\n");
  154. scene_manager_next_scene(app->scene_manager, MetroflipSceneMetromoney);
  155. break;
  156. case CARD_TYPE_CHARLIECARD:
  157. FURI_LOG_I(TAG, "Detected: CharlieCard\n");
  158. scene_manager_next_scene(app->scene_manager, MetroflipSceneCharlieCard);
  159. break;
  160. case CARD_TYPE_SMARTRIDER:
  161. FURI_LOG_I(TAG, "Detected: SmartRider\n");
  162. scene_manager_next_scene(app->scene_manager, MetroflipSceneSmartrider);
  163. break;
  164. case CARD_TYPE_TROIKA:
  165. FURI_LOG_I(TAG, "Detected: Troika\n");
  166. scene_manager_next_scene(app->scene_manager, MetroflipSceneTroika);
  167. break;
  168. case CARD_TYPE_UNKNOWN:
  169. popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  170. break;
  171. default:
  172. FURI_LOG_I(TAG, "Detected: Unknown card type\n");
  173. popup_set_header(popup, "Unsupported\n card", 58, 31, AlignLeft, AlignTop);
  174. break;
  175. }
  176. consumed = true;
  177. } else if(
  178. nfc_detected_protocols_get_protocol(app->detected_protocols, 0) ==
  179. NfcProtocolIso14443_4b) {
  180. scene_manager_next_scene(app->scene_manager, MetroflipSceneCalypso);
  181. consumed = true;
  182. } else if(
  183. nfc_detected_protocols_get_protocol(app->detected_protocols, 0) ==
  184. NfcProtocolMfDesfire) {
  185. app->poller = nfc_poller_alloc(app->nfc, NfcProtocolMfDesfire);
  186. nfc_poller_start(app->poller, metroflip_scene_detect_desfire_poller_callback, app);
  187. consumed = true;
  188. } else if(
  189. nfc_detected_protocols_get_protocol(app->detected_protocols, 0) ==
  190. NfcProtocolInvalid) {
  191. Popup* popup = app->popup;
  192. popup_set_header(
  193. popup, "protocol\n currently\n unsupported", 58, 31, AlignLeft, AlignTop);
  194. consumed = true;
  195. } else {
  196. Popup* popup = app->popup;
  197. popup_set_header(popup, "error", 68, 30, AlignLeft, AlignTop);
  198. consumed = true;
  199. }
  200. }
  201. } else if(event.type == SceneManagerEventTypeBack) {
  202. scene_manager_search_and_switch_to_previous_scene(app->scene_manager, MetroflipSceneStart);
  203. consumed = true;
  204. }
  205. return consumed;
  206. }
  207. void metroflip_scene_auto_on_exit(void* context) {
  208. Metroflip* app = context;
  209. if(!app->auto_mode) {
  210. nfc_scanner_stop(app->scanner);
  211. nfc_scanner_free(app->scanner);
  212. }
  213. app->auto_mode = false;
  214. popup_reset(app->popup);
  215. metroflip_app_blink_stop(app);
  216. }