diff --git a/applications/external/nfc_magic/nfc_magic_worker.c b/applications/external/nfc_magic/nfc_magic_worker.c index dc22b5d3ec6d..e7cf4672da87 100644 --- a/applications/external/nfc_magic/nfc_magic_worker.c +++ b/applications/external/nfc_magic/nfc_magic_worker.c @@ -92,30 +92,22 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { while(nfc_magic_worker->state == NfcMagicWorkerStateWrite) { do { - if(furi_hal_nfc_detect(&nfc_data, 200)) { - if(nfc_data.cuid != magic_dev->cuid) break; - if(!card_found_notified) { - nfc_magic_worker->callback( - NfcMagicWorkerEventCardDetected, nfc_magic_worker->context); - card_found_notified = true; - } - furi_hal_nfc_sleep(); - - magic_activate(); - if(magic_dev->type == MagicTypeClassicGen1) { - if(dev_protocol != NfcDeviceProtocolMifareClassic) break; - MfClassicData* mfc_data = &dev_data->mf_classic_data; - - if(mfc_data->type != MfClassicType1k) break; + if(magic_dev->type == MagicTypeClassicGen1) { + if(furi_hal_nfc_detect(&nfc_data, 200, false)) { + furi_hal_nfc_sleep(); if(!magic_gen1_wupa()) { - FURI_LOG_E(TAG, "Not Magic card"); + FURI_LOG_E(TAG, "No card response to WUPA (not a magic card)"); nfc_magic_worker->callback( NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); done = true; break; } + furi_hal_nfc_sleep(); + } + if(magic_gen1_wupa()) { if(!magic_gen1_data_access_cmd()) { - FURI_LOG_E(TAG, "Not Magic card"); + FURI_LOG_E( + TAG, "No card response to data access command (not a magic card)"); nfc_magic_worker->callback( NfcMagicWorkerEventWrongCard, nfc_magic_worker->context); done = true; @@ -123,20 +115,22 @@ void nfc_magic_worker_write(NfcMagicWorker* nfc_magic_worker) { } for(size_t i = 0; i < 64; i++) { FURI_LOG_D(TAG, "Writing block %d", i); - if(!magic_gen1_write_blk(i, &mfc_data->block[i])) { + if(!magic_gen1_write_blk(i, &src_data->block[i])) { FURI_LOG_E(TAG, "Failed to write %d block", i); + done = true; nfc_magic_worker->callback( NfcMagicWorkerEventFail, nfc_magic_worker->context); - done = true; break; } } + done = true; nfc_magic_worker->callback( NfcMagicWorkerEventSuccess, nfc_magic_worker->context); - done = true; break; - } else if(magic_dev->type == MagicTypeGen4) { + } + } else if(magic_dev->type == MagicTypeGen4) { + if(furi_hal_nfc_detect(&nfc_data, 200, false)) { uint8_t gen4_config[28]; uint32_t password = magic_dev->password; @@ -447,4 +441,4 @@ void nfc_magic_worker_wipe(NfcMagicWorker* nfc_magic_worker) { } } magic_deactivate(); -} +} \ No newline at end of file diff --git a/applications/main/nfc/nfc_cli.c b/applications/main/nfc/nfc_cli.c index 6e6e04ca928b..56c2453b36dd 100644 --- a/applications/main/nfc/nfc_cli.c +++ b/applications/main/nfc/nfc_cli.c @@ -33,7 +33,8 @@ static void nfc_cli_detect(Cli* cli, FuriString* args) { printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); while(!cmd_exit) { cmd_exit |= cli_cmd_interrupt_received(cli); - if(furi_hal_nfc_detect(&dev_data, 400)) { + if(furi_hal_nfc_detect(&dev_data, 400, true) || + furi_hal_nfc_detect(&dev_data, 400, false)) { printf("Found: %s ", nfc_get_dev_type(dev_data.type)); printf("UID length: %d, UID:", dev_data.uid_len); for(size_t i = 0; i < dev_data.uid_len; i++) { @@ -125,7 +126,7 @@ static void nfc_cli_apdu(Cli* cli, FuriString* args) { } printf("detecting tag\r\n"); - if(!furi_hal_nfc_detect(&dev_data, 300)) { + if(!furi_hal_nfc_detect(&dev_data, 300, true)) { printf("Failed to detect tag\r\n"); break; } diff --git a/firmware/targets/f7/api_symbols.csv b/firmware/targets/f7/api_symbols.csv index 15c19091e9ea..1618cb5afef1 100644 --- a/firmware/targets/f7/api_symbols.csv +++ b/firmware/targets/f7/api_symbols.csv @@ -1204,7 +1204,7 @@ Function,+,furi_hal_mpu_protect_no_access,void,"FuriHalMpuRegion, uint32_t, Furi Function,+,furi_hal_mpu_protect_read_only,void,"FuriHalMpuRegion, uint32_t, FuriHalMPURegionSize" Function,+,furi_hal_nfc_activate_nfca,_Bool,"uint32_t, uint32_t*" Function,-,furi_hal_nfc_deinit,void, -Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t" +Function,+,furi_hal_nfc_detect,_Bool,"FuriHalNfcDevData*, uint32_t, _Bool" Function,+,furi_hal_nfc_emulate_nfca,_Bool,"uint8_t*, uint8_t, uint8_t*, uint8_t, FuriHalNfcEmulateCallback, void*, uint32_t" Function,+,furi_hal_nfc_exit_sleep,void, Function,+,furi_hal_nfc_field_off,void, diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 8910d887bcb7..009b8299eb99 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -76,7 +76,7 @@ void furi_hal_nfc_exit_sleep() { rfalLowPowerModeStop(); } -bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) { +bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout, bool emv_compliance) { furi_assert(nfc_data); rfalNfcDevice* dev_list = NULL; @@ -90,7 +90,7 @@ bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) { rfalNfcInitialize(); } rfalNfcDiscoverParam params; - params.compMode = RFAL_COMPLIANCE_MODE_EMV; + params.compMode = emv_compliance ? RFAL_COMPLIANCE_MODE_EMV : RFAL_COMPLIANCE_MODE_NFC; params.techs2Find = RFAL_NFC_POLL_TECH_A | RFAL_NFC_POLL_TECH_B | RFAL_NFC_POLL_TECH_F | RFAL_NFC_POLL_TECH_V | RFAL_NFC_POLL_TECH_AP2P | RFAL_NFC_POLL_TECH_ST25TB; params.totalDuration = 1000; @@ -102,6 +102,7 @@ bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout) { params.maxBR = RFAL_BR_KEEP; params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; params.notifyCb = NULL; + params.skipRats = !emv_compliance; uint32_t start = DWT->CYCCNT; rfalNfcDiscover(¶ms); @@ -186,6 +187,7 @@ bool furi_hal_nfc_activate_nfca(uint32_t timeout, uint32_t* cuid) { .maxBR = RFAL_BR_KEEP, .GBLen = RFAL_NFCDEP_GB_MAX_LEN, .notifyCb = NULL, + .skipRats = true, }; uint32_t start = DWT->CYCCNT; rfalNfcDiscover(¶ms); @@ -246,7 +248,7 @@ bool furi_hal_nfc_listen( .maxBR = RFAL_BR_KEEP, .GBLen = RFAL_NFCDEP_GB_MAX_LEN, .notifyCb = NULL, - .activate_after_sak = activate_after_sak, + .activateAfterSak = activate_after_sak, }; if(FURI_BIT(sak, 5)) { params.compMode = RFAL_COMPLIANCE_MODE_EMV; diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.h b/firmware/targets/f7/furi_hal/furi_hal_nfc.h index dc3f873f3460..8781bfebafa8 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.h +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.h @@ -144,7 +144,7 @@ void furi_hal_nfc_exit_sleep(); * * @return true on success */ -bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout); +bool furi_hal_nfc_detect(FuriHalNfcDevData* nfc_data, uint32_t timeout, bool emv_compliance); /** Activate NFC-A tag * diff --git a/lib/ST25RFAL002/include/rfal_nfc.h b/lib/ST25RFAL002/include/rfal_nfc.h index 49cbe5f9cf8e..867bcb86a798 100644 --- a/lib/ST25RFAL002/include/rfal_nfc.h +++ b/lib/ST25RFAL002/include/rfal_nfc.h @@ -211,7 +211,8 @@ typedef struct { bool wakeupConfigDefault; /*!< Wake-Up mode default configuration */ rfalWakeUpConfig wakeupConfig; /*!< Wake-Up mode configuration */ - bool activate_after_sak; // Set device to Active mode after SAK responce + bool activateAfterSak; // Set device to Active mode after SAK responce + bool skipRats; // Skip RATS even if card supports it } rfalNfcDiscoverParam; /*! Buffer union, only one interface is used at a time */ diff --git a/lib/ST25RFAL002/source/rfal_nfc.c b/lib/ST25RFAL002/source/rfal_nfc.c index 9040b7f9d2a4..73a52a09d51b 100644 --- a/lib/ST25RFAL002/source/rfal_nfc.c +++ b/lib/ST25RFAL002/source/rfal_nfc.c @@ -568,7 +568,7 @@ ReturnCode rfalNfcDataExchangeStart( *rvdLen = (uint16_t*)&gNfcDev.rxLen; *rxData = (uint8_t*)( (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? gNfcDev.rxBuf.isoDepBuf.apdu : ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? gNfcDev.rxBuf.nfcDepBuf.pdu : gNfcDev.rxBuf.rfBuf)); - if(gNfcDev.disc.activate_after_sak) { + if(gNfcDev.disc.activateAfterSak) { gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; } return ERR_NONE; @@ -713,7 +713,7 @@ ReturnCode rfalNfcDataExchangeCustomStart( *rvdLen = (uint16_t*)&gNfcDev.rxLen; *rxData = (uint8_t*)( (gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_ISODEP) ? gNfcDev.rxBuf.isoDepBuf.apdu : ((gNfcDev.activeDev->rfInterface == RFAL_NFC_INTERFACE_NFCDEP) ? gNfcDev.rxBuf.nfcDepBuf.pdu : gNfcDev.rxBuf.rfBuf)); - if(gNfcDev.disc.activate_after_sak) { + if(gNfcDev.disc.activateAfterSak) { gNfcDev.state = RFAL_NFC_STATE_DATAEXCHANGE_DONE; } return ERR_NONE; @@ -1501,6 +1501,12 @@ static ReturnCode rfalNfcPollActivation(uint8_t devIt) { /*******************************************************************************/ case RFAL_NFCA_T4T: /* Device supports ISO-DEP */ + if(gNfcDev.disc.skipRats) { + // Don't preform 14443-4 activation + gNfcDev.devList[devIt].rfInterface = RFAL_NFC_INTERFACE_RF; + break; + } + #if RFAL_FEATURE_ISO_DEP && RFAL_FEATURE_ISO_DEP_POLL if(!gNfcDev.isOperOngoing) { /* Perform ISO-DEP (ISO14443-4) activation: RATS and PPS if supported */ @@ -1760,7 +1766,7 @@ static ReturnCode rfalNfcListenActivation(void) { &gNfcDev.rxLen)); } - else if(gNfcDev.disc.activate_after_sak) { + else if(gNfcDev.disc.activateAfterSak) { gNfcDev.devList->type = RFAL_NFC_POLL_TYPE_NFCA; rfalListenSetState(RFAL_LM_STATE_ACTIVE_A); return ERR_NONE; diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 28a1f6827977..0fbb4585531e 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -148,7 +148,7 @@ static bool nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker, FuriHalNfcTxRxC furi_hal_nfc_sleep(); // Otherwise, try to read as usual - if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200)) break; + if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 200, false)) break; if(!mf_ul_read_card(tx_rx, &reader, &data)) break; // Copy data nfc_worker->dev_data->mf_ul_data = data; @@ -217,7 +217,7 @@ static bool nfc_worker_read_mf_desfire(NfcWorker* nfc_worker, FuriHalNfcTxRxCont } do { - if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300)) break; + if(!furi_hal_nfc_detect(&nfc_worker->dev_data->nfc_data, 300, false)) break; if(!mf_df_read_card(tx_rx, data)) break; read_success = true; } while(false); @@ -272,7 +272,7 @@ void nfc_worker_read(NfcWorker* nfc_worker) { bool card_not_detected_notified = false; while(nfc_worker->state == NfcWorkerStateRead) { - if(furi_hal_nfc_detect(nfc_data, 300)) { + if(furi_hal_nfc_detect(nfc_data, 300, true) || furi_hal_nfc_detect(nfc_data, 300, false)) { // Process first found device nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); card_not_detected_notified = false; @@ -335,7 +335,8 @@ void nfc_worker_read_type(NfcWorker* nfc_worker) { bool card_not_detected_notified = false; while(nfc_worker->state == NfcWorkerStateRead) { - if(furi_hal_nfc_detect(nfc_data, 300)) { + if((read_mode == NfcReadModeMfClassic && furi_hal_nfc_detect(nfc_data, 300, false)) || + (read_mode != NfcReadModeMfClassic && furi_hal_nfc_detect(nfc_data, 300, true))) { FURI_LOG_D(TAG, "Card detected"); furi_hal_nfc_sleep(); // Process first found device @@ -772,7 +773,7 @@ void nfc_worker_write_mf_classic(NfcWorker* nfc_worker) { MfClassicData dest_data = *src_data; while(nfc_worker->state == NfcWorkerStateMfClassicWrite) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { + if(furi_hal_nfc_detect(&nfc_data, 200, false)) { if(!card_found_notified) { nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); card_found_notified = true; @@ -845,7 +846,7 @@ void nfc_worker_update_mf_classic(NfcWorker* nfc_worker) { MfClassicData new_data = *old_data; while(nfc_worker->state == NfcWorkerStateMfClassicUpdate) { - if(furi_hal_nfc_detect(&nfc_data, 200)) { + if(furi_hal_nfc_detect(&nfc_data, 200, false)) { if(!card_found_notified) { nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); card_found_notified = true; @@ -923,7 +924,7 @@ void nfc_worker_mf_ultralight_read_auth(NfcWorker* nfc_worker) { uint16_t pack = 0; while(nfc_worker->state == NfcWorkerStateReadMfUltralightReadAuth) { furi_hal_nfc_sleep(); - if(furi_hal_nfc_detect(nfc_data, 300) && nfc_data->type == FuriHalNfcTypeA) { + if(furi_hal_nfc_detect(nfc_data, 300, false) && nfc_data->type == FuriHalNfcTypeA) { if(mf_ul_check_card_type(nfc_data->atqa[0], nfc_data->atqa[1], nfc_data->sak)) { nfc_worker->callback(NfcWorkerEventCardDetected, nfc_worker->context); if(data->auth_method == MfUltralightAuthMethodManual ||