gen2_poller.c 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594
  1. #include "gen2_poller_i.h"
  2. #include <nfc/helpers/nfc_data_generator.h>
  3. #include <furi/furi.h>
  4. #define GEN2_POLLER_THREAD_FLAG_DETECTED (1U << 0)
  5. #define TAG "GEN2"
  6. typedef NfcCommand (*Gen2PollerStateHandler)(Gen2Poller* instance);
  7. typedef struct {
  8. NfcPoller* poller;
  9. BitBuffer* tx_buffer;
  10. BitBuffer* rx_buffer;
  11. FuriThreadId thread_id;
  12. bool detected;
  13. Gen2PollerError error;
  14. } Gen2PollerDetectContext;
  15. // Array of known Gen2 ATS responses
  16. // 0978009102DABC1910F005 - flavour 2
  17. // 0978009102DABC1910F005 - flavour 4
  18. // 0D780071028849A13020150608563D - flavour 6
  19. // Other flavours can't be detected other than by just trying to write to block 0
  20. const uint8_t GEN2_ATS[3][16] = {
  21. {0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0xF0, 0x05},
  22. {0x09, 0x78, 0x00, 0x91, 0x02, 0xDA, 0xBC, 0x19, 0x10, 0xF0, 0x05},
  23. {0x0D, 0x78, 0x00, 0x71, 0x02, 0x88, 0x49, 0xA1, 0x30, 0x20, 0x15, 0x06, 0x08, 0x56, 0x3D}};
  24. static const MfClassicBlock gen2_poller_default_block_0 = {
  25. .data =
  26. {0x00,
  27. 0x01,
  28. 0x02,
  29. 0x03,
  30. 0x00, // BCC - IMPORTANT
  31. 0x08, // SAK
  32. 0x04, // ATQA0
  33. 0x00, // ATQA1
  34. 0x00,
  35. 0x00,
  36. 0x00,
  37. 0x00,
  38. 0x00,
  39. 0x00,
  40. 0x00,
  41. 0x00},
  42. };
  43. static const MfClassicBlock gen2_poller_default_empty_block = {
  44. .data =
  45. {0x00,
  46. 0x00,
  47. 0x00,
  48. 0x00,
  49. 0x00,
  50. 0x00,
  51. 0x00,
  52. 0x00,
  53. 0x00,
  54. 0x00,
  55. 0x00,
  56. 0x00,
  57. 0x00,
  58. 0x00,
  59. 0x00,
  60. 0x00},
  61. };
  62. static MfClassicBlock gen2_poller_default_sector_trailer_block = {
  63. .data =
  64. {0xFF,
  65. 0xFF,
  66. 0xFF,
  67. 0xFF,
  68. 0xFF,
  69. 0xFF,
  70. 0xFF,
  71. 0x07,
  72. 0x80,
  73. 0x69,
  74. 0xFF,
  75. 0xFF,
  76. 0xFF,
  77. 0xFF,
  78. 0xFF,
  79. 0xFF},
  80. };
  81. const char* const gen2_problem_strings[] = {
  82. "UID may be non-\nrewritable. Check data after writing",
  83. "No data in selected file",
  84. "Some sectors are locked",
  85. "Can't find keys to some sectors",
  86. "The selected file is incomplete",
  87. };
  88. Gen2Poller* gen2_poller_alloc(Nfc* nfc) {
  89. Gen2Poller* instance = malloc(sizeof(Gen2Poller));
  90. instance->poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a);
  91. instance->data = mf_classic_alloc();
  92. instance->crypto = crypto1_alloc();
  93. instance->tx_plain_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE);
  94. instance->tx_encrypted_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE);
  95. instance->rx_plain_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE);
  96. instance->rx_encrypted_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE);
  97. instance->card_state = Gen2CardStateLost;
  98. instance->gen2_event.data = &instance->gen2_event_data;
  99. instance->mode_ctx.write_ctx.mfc_data_source = malloc(sizeof(MfClassicData));
  100. instance->mode_ctx.write_ctx.mfc_data_target = malloc(sizeof(MfClassicData));
  101. instance->mode_ctx.write_ctx.need_halt_before_write = true;
  102. return instance;
  103. }
  104. void gen2_poller_free(Gen2Poller* instance) {
  105. furi_assert(instance);
  106. furi_assert(instance->data);
  107. furi_assert(instance->crypto);
  108. furi_assert(instance->tx_plain_buffer);
  109. furi_assert(instance->rx_plain_buffer);
  110. furi_assert(instance->tx_encrypted_buffer);
  111. furi_assert(instance->rx_encrypted_buffer);
  112. nfc_poller_free(instance->poller);
  113. mf_classic_free(instance->data);
  114. crypto1_free(instance->crypto);
  115. bit_buffer_free(instance->tx_plain_buffer);
  116. bit_buffer_free(instance->rx_plain_buffer);
  117. bit_buffer_free(instance->tx_encrypted_buffer);
  118. bit_buffer_free(instance->rx_encrypted_buffer);
  119. free(instance->mode_ctx.write_ctx.mfc_data_source);
  120. free(instance->mode_ctx.write_ctx.mfc_data_target);
  121. free(instance);
  122. }
  123. NfcCommand gen2_poller_detect_callback(NfcGenericEvent event, void* context) {
  124. furi_assert(context);
  125. furi_assert(event.protocol == NfcProtocolIso14443_3a);
  126. furi_assert(event.event_data);
  127. furi_assert(event.instance);
  128. NfcCommand command = NfcCommandStop;
  129. Gen2PollerDetectContext* detect_ctx = context;
  130. Iso14443_3aPoller* iso3_poller = event.instance;
  131. Iso14443_3aPollerEvent* iso3_event = event.event_data;
  132. detect_ctx->error = Gen2PollerErrorTimeout;
  133. bit_buffer_reset(detect_ctx->tx_buffer);
  134. bit_buffer_append_byte(detect_ctx->tx_buffer, GEN2_CMD_READ_ATS);
  135. bit_buffer_append_byte(detect_ctx->tx_buffer, GEN2_FSDI_256 << 4);
  136. if(iso3_event->type == Iso14443_3aPollerEventTypeReady) {
  137. do {
  138. const Iso14443_3aError iso14443_3a_error = iso14443_3a_poller_send_standard_frame(
  139. iso3_poller, detect_ctx->tx_buffer, detect_ctx->rx_buffer, GEN2_POLLER_MAX_FWT);
  140. if(iso14443_3a_error != Iso14443_3aErrorNone &&
  141. iso14443_3a_error != Iso14443_3aErrorWrongCrc) {
  142. FURI_LOG_E(TAG, "ATS request failed");
  143. detect_ctx->error = Gen2PollerErrorProtocol;
  144. break;
  145. } else {
  146. FURI_LOG_D(TAG, "ATS request succeeded:");
  147. // Check against known ATS responses
  148. for(size_t i = 0; i < COUNT_OF(GEN2_ATS); i++) {
  149. if(memcmp(
  150. bit_buffer_get_data(detect_ctx->rx_buffer),
  151. GEN2_ATS[i],
  152. sizeof(GEN2_ATS[i])) == 0) {
  153. detect_ctx->error = Gen2PollerErrorNone;
  154. break;
  155. }
  156. }
  157. }
  158. } while(false);
  159. } else if(iso3_event->type == Iso14443_3aPollerEventTypeError) {
  160. detect_ctx->error = Gen2PollerErrorTimeout;
  161. }
  162. furi_thread_flags_set(detect_ctx->thread_id, GEN2_POLLER_THREAD_FLAG_DETECTED);
  163. return command;
  164. }
  165. Gen2PollerError gen2_poller_detect(Nfc* nfc) {
  166. furi_assert(nfc);
  167. Gen2PollerDetectContext detect_ctx = {
  168. .poller = nfc_poller_alloc(nfc, NfcProtocolIso14443_3a),
  169. .tx_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE),
  170. .rx_buffer = bit_buffer_alloc(GEN2_POLLER_MAX_BUFFER_SIZE),
  171. .thread_id = furi_thread_get_current_id(),
  172. .detected = false,
  173. .error = Gen2PollerErrorNone,
  174. };
  175. nfc_poller_start(detect_ctx.poller, gen2_poller_detect_callback, &detect_ctx);
  176. uint32_t flags =
  177. furi_thread_flags_wait(GEN2_POLLER_THREAD_FLAG_DETECTED, FuriFlagWaitAny, FuriWaitForever);
  178. if(flags & GEN2_POLLER_THREAD_FLAG_DETECTED) {
  179. furi_thread_flags_clear(GEN2_POLLER_THREAD_FLAG_DETECTED);
  180. }
  181. nfc_poller_stop(detect_ctx.poller);
  182. bit_buffer_free(detect_ctx.tx_buffer);
  183. bit_buffer_free(detect_ctx.rx_buffer);
  184. nfc_poller_free(detect_ctx.poller);
  185. return detect_ctx.error;
  186. }
  187. NfcCommand gen2_poller_idle_handler(Gen2Poller* instance) {
  188. furi_assert(instance);
  189. NfcCommand command = NfcCommandContinue;
  190. instance->mode_ctx.write_ctx.current_block = 0;
  191. instance->gen2_event.type = Gen2PollerEventTypeDetected;
  192. command = instance->callback(instance->gen2_event, instance->context);
  193. instance->state = Gen2PollerStateRequestMode;
  194. return command;
  195. }
  196. NfcCommand gen2_poller_request_mode_handler(Gen2Poller* instance) {
  197. furi_assert(instance);
  198. NfcCommand command = NfcCommandContinue;
  199. instance->gen2_event.type = Gen2PollerEventTypeRequestMode;
  200. command = instance->callback(instance->gen2_event, instance->context);
  201. instance->mode = instance->gen2_event_data.poller_mode.mode;
  202. if(instance->gen2_event_data.poller_mode.mode == Gen2PollerModeWipe) {
  203. instance->state = Gen2PollerStateWriteTargetDataRequest;
  204. } else {
  205. instance->state = Gen2PollerStateWriteSourceDataRequest;
  206. }
  207. return command;
  208. }
  209. NfcCommand gen2_poller_write_source_data_request_handler(Gen2Poller* instance) {
  210. NfcCommand command = NfcCommandContinue;
  211. instance->gen2_event.type = Gen2PollerEventTypeRequestDataToWrite;
  212. command = instance->callback(instance->gen2_event, instance->context);
  213. memcpy(
  214. instance->mode_ctx.write_ctx.mfc_data_source,
  215. instance->gen2_event_data.data_to_write.mfc_data,
  216. sizeof(MfClassicData));
  217. instance->state = Gen2PollerStateWriteTargetDataRequest;
  218. return command;
  219. }
  220. NfcCommand gen2_poller_write_target_data_request_handler(Gen2Poller* instance) {
  221. NfcCommand command = NfcCommandContinue;
  222. instance->gen2_event.type = Gen2PollerEventTypeRequestTargetData;
  223. command = instance->callback(instance->gen2_event, instance->context);
  224. memcpy(
  225. instance->mode_ctx.write_ctx.mfc_data_target,
  226. instance->gen2_event_data.target_data.mfc_data,
  227. sizeof(MfClassicData));
  228. if(instance->mode == Gen2PollerModeWipe) {
  229. instance->state = Gen2PollerStateWipe;
  230. } else {
  231. instance->state = Gen2PollerStateWrite;
  232. }
  233. return command;
  234. }
  235. Gen2PollerError gen2_poller_write_block_handler(
  236. Gen2Poller* instance,
  237. uint8_t block_num,
  238. const MfClassicBlock* block) {
  239. furi_assert(instance);
  240. Gen2PollerError error = Gen2PollerErrorNone;
  241. Gen2PollerWriteContext* write_ctx = &instance->mode_ctx.write_ctx;
  242. MfClassicKey auth_key = write_ctx->auth_key;
  243. do {
  244. // Compare the target and source data
  245. if(memcmp(block->data, write_ctx->mfc_data_target->block[block_num].data, 16) == 0) {
  246. FURI_LOG_D(TAG, "Block %d is the same, skipping", block_num);
  247. break;
  248. }
  249. // Reauth if necessary
  250. if(write_ctx->need_halt_before_write) {
  251. FURI_LOG_D(TAG, "Auth before writing block %d", write_ctx->current_block);
  252. error = gen2_poller_auth(
  253. instance, write_ctx->current_block, &auth_key, write_ctx->write_key, NULL);
  254. if(error != Gen2PollerErrorNone) {
  255. FURI_LOG_D(
  256. TAG, "Failed to auth to block %d for writing", write_ctx->current_block);
  257. break;
  258. }
  259. }
  260. // Write the block
  261. error = gen2_poller_write_block(instance, write_ctx->current_block, block);
  262. if(error != Gen2PollerErrorNone) {
  263. FURI_LOG_D(TAG, "Failed to write block %d", write_ctx->current_block);
  264. break;
  265. }
  266. } while(false);
  267. FURI_LOG_D(TAG, "Block %d finished, halting", write_ctx->current_block);
  268. gen2_poller_halt(instance);
  269. return error;
  270. }
  271. NfcCommand gen2_poller_wipe_handler(Gen2Poller* instance) {
  272. NfcCommand command = NfcCommandContinue;
  273. Gen2PollerError error = Gen2PollerErrorNone;
  274. Gen2PollerWriteContext* write_ctx = &instance->mode_ctx.write_ctx;
  275. uint8_t block_num = write_ctx->current_block;
  276. do {
  277. // Check whether the ACs for that block are known in target data
  278. if(!mf_classic_is_block_read(
  279. write_ctx->mfc_data_target,
  280. mf_classic_get_sector_trailer_num_by_block(block_num))) {
  281. FURI_LOG_E(TAG, "Sector trailer for block %d not present in target data", block_num);
  282. break;
  283. }
  284. // Check whether ACs need to be reset and whether they can be reset
  285. if(!gen2_poller_can_write_block(write_ctx->mfc_data_target, block_num)) {
  286. if(!gen2_can_reset_access_conditions(write_ctx->mfc_data_target, block_num)) {
  287. FURI_LOG_E(TAG, "Block %d cannot be written", block_num);
  288. break;
  289. } else {
  290. FURI_LOG_D(TAG, "Resetting ACs for block %d", block_num);
  291. // Generate a block with old keys and default ACs (0xFF, 0x07, 0x80)
  292. MfClassicBlock block;
  293. memset(&block, 0, sizeof(block));
  294. memcpy(block.data, write_ctx->mfc_data_target->block[block_num].data, 16);
  295. memcpy(block.data + 6, "\xFF\x07\x80", 3);
  296. error = gen2_poller_write_block_handler(instance, block_num, &block);
  297. if(error != Gen2PollerErrorNone) {
  298. FURI_LOG_E(TAG, "Failed to reset ACs for block %d", block_num);
  299. break;
  300. } else {
  301. FURI_LOG_D(TAG, "ACs for block %d reset", block_num);
  302. memcpy(write_ctx->mfc_data_target->block[block_num].data, block.data, 16);
  303. }
  304. }
  305. }
  306. // Figure out which key to use for writing
  307. write_ctx->write_key =
  308. gen2_poller_get_key_type_to_write(write_ctx->mfc_data_target, block_num);
  309. // Get the key to use for writing from the target data
  310. MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(
  311. write_ctx->mfc_data_target, mf_classic_get_sector_by_block(block_num));
  312. if(write_ctx->write_key == MfClassicKeyTypeA) {
  313. write_ctx->auth_key = sec_tr->key_a;
  314. } else {
  315. write_ctx->auth_key = sec_tr->key_b;
  316. }
  317. // Write the default block depending on the block type
  318. if(block_num == 0) {
  319. error =
  320. gen2_poller_write_block_handler(instance, block_num, &gen2_poller_default_block_0);
  321. } else if(mf_classic_is_sector_trailer(block_num)) {
  322. error = gen2_poller_write_block_handler(
  323. instance, block_num, &gen2_poller_default_sector_trailer_block);
  324. } else {
  325. error = gen2_poller_write_block_handler(
  326. instance, block_num, &gen2_poller_default_empty_block);
  327. }
  328. if(error != Gen2PollerErrorNone) {
  329. FURI_LOG_E(TAG, "Couldn't write block %d", block_num);
  330. }
  331. } while(false);
  332. write_ctx->current_block++;
  333. if(error != Gen2PollerErrorNone) {
  334. FURI_LOG_D(TAG, "Error occurred: %d", error);
  335. }
  336. if(write_ctx->current_block ==
  337. mf_classic_get_total_block_num(write_ctx->mfc_data_target->type)) {
  338. instance->state = Gen2PollerStateSuccess;
  339. }
  340. return command;
  341. }
  342. NfcCommand gen2_poller_write_handler(Gen2Poller* instance) {
  343. NfcCommand command = NfcCommandContinue;
  344. Gen2PollerError error = Gen2PollerErrorNone;
  345. Gen2PollerWriteContext* write_ctx = &instance->mode_ctx.write_ctx;
  346. uint8_t block_num = write_ctx->current_block;
  347. do {
  348. // Check whether the block is present in the source data
  349. if(!mf_classic_is_block_read(write_ctx->mfc_data_source, block_num)) {
  350. // FURI_LOG_E(TAG, "Block %d not present in source data", block_num);
  351. break;
  352. }
  353. // Check whether the ACs for that block are known in target data
  354. if(!mf_classic_is_block_read(
  355. write_ctx->mfc_data_target,
  356. mf_classic_get_sector_trailer_num_by_block(block_num))) {
  357. FURI_LOG_E(TAG, "Sector trailer for block %d not present in target data", block_num);
  358. break;
  359. }
  360. // Check whether ACs need to be reset and whether they can be reset
  361. if(!gen2_poller_can_write_block(write_ctx->mfc_data_target, block_num)) {
  362. if(!gen2_can_reset_access_conditions(write_ctx->mfc_data_target, block_num)) {
  363. FURI_LOG_E(TAG, "Block %d cannot be written", block_num);
  364. break;
  365. } else {
  366. FURI_LOG_D(TAG, "Resetting ACs for block %d", block_num);
  367. // Generate a block with old keys and default ACs (0xFF, 0x07, 0x80)
  368. MfClassicBlock block;
  369. memset(&block, 0, sizeof(block));
  370. memcpy(block.data, write_ctx->mfc_data_target->block[block_num].data, 16);
  371. memcpy(block.data + 6, "\xFF\x07\x80", 3);
  372. error = gen2_poller_write_block_handler(instance, block_num, &block);
  373. if(error != Gen2PollerErrorNone) {
  374. FURI_LOG_E(TAG, "Failed to reset ACs for block %d", block_num);
  375. break;
  376. } else {
  377. FURI_LOG_D(TAG, "ACs for block %d reset", block_num);
  378. memcpy(write_ctx->mfc_data_target->block[block_num].data, block.data, 16);
  379. }
  380. }
  381. }
  382. // Figure out which key to use for writing
  383. write_ctx->write_key =
  384. gen2_poller_get_key_type_to_write(write_ctx->mfc_data_target, block_num);
  385. // Get the key to use for writing from the target data
  386. MfClassicSectorTrailer* sec_tr = mf_classic_get_sector_trailer_by_sector(
  387. write_ctx->mfc_data_target, mf_classic_get_sector_by_block(block_num));
  388. if(write_ctx->write_key == MfClassicKeyTypeA) {
  389. write_ctx->auth_key = sec_tr->key_a;
  390. } else {
  391. write_ctx->auth_key = sec_tr->key_b;
  392. }
  393. // Write the block
  394. error = gen2_poller_write_block_handler(
  395. instance, block_num, &write_ctx->mfc_data_source->block[block_num]);
  396. if(error != Gen2PollerErrorNone) {
  397. FURI_LOG_E(TAG, "Couldn't write block %d", block_num);
  398. }
  399. } while(false);
  400. write_ctx->current_block++;
  401. if(error != Gen2PollerErrorNone) {
  402. FURI_LOG_D(TAG, "Error occurred: %d", error);
  403. } else if(
  404. write_ctx->current_block ==
  405. mf_classic_get_total_block_num(write_ctx->mfc_data_source->type)) {
  406. instance->state = Gen2PollerStateSuccess;
  407. }
  408. return command;
  409. }
  410. NfcCommand gen2_poller_success_handler(Gen2Poller* instance) {
  411. furi_assert(instance);
  412. NfcCommand command = NfcCommandContinue;
  413. instance->gen2_event.type = Gen2PollerEventTypeSuccess;
  414. command = instance->callback(instance->gen2_event, instance->context);
  415. instance->state = Gen2PollerStateIdle;
  416. return command;
  417. }
  418. NfcCommand gen2_poller_fail_handler(Gen2Poller* instance) {
  419. furi_assert(instance);
  420. NfcCommand command = NfcCommandContinue;
  421. instance->gen2_event.type = Gen2PollerEventTypeFail;
  422. command = instance->callback(instance->gen2_event, instance->context);
  423. instance->state = Gen2PollerStateIdle;
  424. return command;
  425. }
  426. static const Gen2PollerStateHandler gen2_poller_state_handlers[Gen2PollerStateNum] = {
  427. [Gen2PollerStateIdle] = gen2_poller_idle_handler,
  428. [Gen2PollerStateRequestMode] = gen2_poller_request_mode_handler,
  429. [Gen2PollerStateWipe] = gen2_poller_wipe_handler,
  430. [Gen2PollerStateWriteSourceDataRequest] = gen2_poller_write_source_data_request_handler,
  431. [Gen2PollerStateWriteTargetDataRequest] = gen2_poller_write_target_data_request_handler,
  432. [Gen2PollerStateWrite] = gen2_poller_write_handler,
  433. [Gen2PollerStateSuccess] = gen2_poller_success_handler,
  434. [Gen2PollerStateFail] = gen2_poller_fail_handler,
  435. };
  436. NfcCommand gen2_poller_callback(NfcGenericEvent event, void* context) {
  437. furi_assert(context);
  438. furi_assert(event.protocol == NfcProtocolIso14443_3a);
  439. furi_assert(event.event_data);
  440. furi_assert(event.instance);
  441. NfcCommand command = NfcCommandContinue;
  442. Gen2Poller* instance = context;
  443. instance->iso3_poller = event.instance;
  444. Iso14443_3aPollerEvent* iso3_event = event.event_data;
  445. if(iso3_event->type == Iso14443_3aPollerEventTypeReady) {
  446. command = gen2_poller_state_handlers[instance->state](instance);
  447. }
  448. return command;
  449. }
  450. void gen2_poller_start(Gen2Poller* instance, Gen2PollerCallback callback, void* context) {
  451. furi_assert(instance);
  452. furi_assert(callback);
  453. instance->callback = callback;
  454. instance->context = context;
  455. nfc_poller_start(instance->poller, gen2_poller_callback, instance);
  456. return;
  457. }
  458. void gen2_poller_stop(Gen2Poller* instance) {
  459. furi_assert(instance);
  460. FURI_LOG_D(TAG, "Stopping Gen2 poller");
  461. nfc_poller_stop(instance->poller);
  462. return;
  463. }
  464. Gen2PollerWriteProblems gen2_poller_check_target_problems(NfcDevice* target_dev) {
  465. furi_assert(target_dev);
  466. Gen2PollerWriteProblems problems = {0};
  467. const MfClassicData* mfc_data = nfc_device_get_data(target_dev, NfcProtocolMfClassic);
  468. if(mfc_data) {
  469. uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
  470. for(uint16_t i = 0; i < total_block_num; i++) {
  471. if(mf_classic_is_sector_trailer(i)) {
  472. problems.all_problems |=
  473. gen2_poller_can_write_sector_trailer(mfc_data, i).all_problems;
  474. } else {
  475. problems.all_problems |=
  476. gen2_poller_can_write_data_block(mfc_data, i).all_problems;
  477. }
  478. }
  479. } else {
  480. problems.no_data = true;
  481. }
  482. return problems;
  483. }
  484. Gen2PollerWriteProblems gen2_poller_check_source_problems(NfcDevice* source_dev) {
  485. furi_assert(source_dev);
  486. Gen2PollerWriteProblems problems = {0};
  487. const MfClassicData* mfc_data = nfc_device_get_data(source_dev, NfcProtocolMfClassic);
  488. if(mfc_data) {
  489. uint16_t total_block_num = mf_classic_get_total_block_num(mfc_data->type);
  490. for(uint16_t i = 0; i < total_block_num; i++) {
  491. if(!mf_classic_is_block_read(mfc_data, i)) {
  492. problems.missing_source_data = true;
  493. }
  494. }
  495. }
  496. return problems;
  497. }