picopass_scene_read_card.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. #include "../picopass_i.h"
  2. #include <dolphin/dolphin.h>
  3. #include "../picopass_keys.h"
  4. enum {
  5. PicopassSceneReadCardDictStandard,
  6. PicopassSceneReadCardDictElite,
  7. };
  8. static bool picopass_read_card_change_dict(Picopass* picopass) {
  9. bool success = false;
  10. do {
  11. uint32_t scene_state =
  12. scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneReadCard);
  13. keys_dict_free(picopass->dict);
  14. picopass->dict = NULL;
  15. if(scene_state == PicopassSceneReadCardDictElite) break;
  16. if(!keys_dict_check_presence(PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME)) break;
  17. picopass->dict = keys_dict_alloc(
  18. PICOPASS_ICLASS_ELITE_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN);
  19. scene_manager_set_scene_state(
  20. picopass->scene_manager, PicopassSceneReadCard, PicopassSceneReadCardDictElite);
  21. success = true;
  22. } while(false);
  23. return success;
  24. }
  25. NfcCommand picopass_read_card_worker_callback(PicopassPollerEvent event, void* context) {
  26. furi_assert(context);
  27. NfcCommand command = NfcCommandContinue;
  28. Picopass* picopass = context;
  29. if(event.type == PicopassPollerEventTypeRequestMode) {
  30. event.data->req_mode.mode = PicopassPollerModeRead;
  31. } else if(event.type == PicopassPollerEventTypeRequestKey) {
  32. uint8_t key[PICOPASS_KEY_LEN] = {};
  33. bool is_key_provided = true;
  34. if(!keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN)) {
  35. if(picopass_read_card_change_dict(picopass)) {
  36. is_key_provided = keys_dict_get_next_key(picopass->dict, key, PICOPASS_KEY_LEN);
  37. } else {
  38. is_key_provided = false;
  39. }
  40. }
  41. uint32_t scene_state =
  42. scene_manager_get_scene_state(picopass->scene_manager, PicopassSceneReadCard);
  43. memcpy(event.data->req_key.key, key, PICOPASS_KEY_LEN);
  44. event.data->req_key.is_elite_key = (scene_state == PicopassSceneReadCardDictElite);
  45. event.data->req_key.is_key_provided = is_key_provided;
  46. } else if(
  47. event.type == PicopassPollerEventTypeSuccess ||
  48. event.type == PicopassPollerEventTypeAuthFail) {
  49. const PicopassDeviceData* data = picopass_poller_get_data(picopass->poller);
  50. memcpy(&picopass->dev->dev_data, data, sizeof(PicopassDeviceData));
  51. view_dispatcher_send_custom_event(
  52. picopass->view_dispatcher, PicopassCustomEventPollerSuccess);
  53. } else if(event.type == PicopassPollerEventTypeFail) {
  54. // the poller will retry, but provide some feedback to the user
  55. uint32_t ticks = furi_get_tick();
  56. if(picopass->last_error_notify_ticks + furi_ms_to_ticks(500) < ticks) {
  57. picopass->last_error_notify_ticks = ticks;
  58. notification_message(picopass->notifications, &sequence_error);
  59. }
  60. }
  61. return command;
  62. }
  63. void picopass_scene_read_card_on_enter(void* context) {
  64. Picopass* picopass = context;
  65. dolphin_deed(DolphinDeedNfcRead);
  66. picopass->last_error_notify_ticks = 0;
  67. // Setup view
  68. Popup* popup = picopass->popup;
  69. popup_set_header(popup, "Detecting\npicopass\ncard", 68, 30, AlignLeft, AlignTop);
  70. popup_set_icon(popup, 0, 3, &I_RFIDDolphinReceive_97x61);
  71. picopass->dict = keys_dict_alloc(
  72. PICOPASS_ICLASS_STANDARD_DICT_FLIPPER_NAME, KeysDictModeOpenExisting, PICOPASS_KEY_LEN);
  73. scene_manager_set_scene_state(
  74. picopass->scene_manager, PicopassSceneReadCard, PicopassSceneReadCardDictStandard);
  75. // Start worker
  76. picopass->poller = picopass_poller_alloc(picopass->nfc);
  77. picopass_poller_start(picopass->poller, picopass_read_card_worker_callback, picopass);
  78. view_dispatcher_switch_to_view(picopass->view_dispatcher, PicopassViewPopup);
  79. picopass_blink_start(picopass);
  80. }
  81. bool picopass_scene_read_card_on_event(void* context, SceneManagerEvent event) {
  82. Picopass* picopass = context;
  83. bool consumed = false;
  84. if(event.type == SceneManagerEventTypeCustom) {
  85. if(event.event == PicopassCustomEventPollerSuccess) {
  86. if(memcmp(
  87. picopass->dev->dev_data.pacs.key,
  88. picopass_factory_debit_key,
  89. PICOPASS_BLOCK_LEN) == 0) {
  90. scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadFactorySuccess);
  91. } else {
  92. scene_manager_next_scene(picopass->scene_manager, PicopassSceneReadCardSuccess);
  93. }
  94. consumed = true;
  95. }
  96. }
  97. return consumed;
  98. }
  99. void picopass_scene_read_card_on_exit(void* context) {
  100. Picopass* picopass = context;
  101. if(picopass->dict) {
  102. keys_dict_free(picopass->dict);
  103. picopass->dict = NULL;
  104. }
  105. picopass_poller_stop(picopass->poller);
  106. picopass_poller_free(picopass->poller);
  107. // Clear view
  108. popup_reset(picopass->popup);
  109. scene_manager_set_scene_state(
  110. picopass->scene_manager, PicopassSceneReadCard, PicopassSceneReadCardDictStandard);
  111. picopass_blink_stop(picopass);
  112. }