metroflip_scene_auto.c 11 KB

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