From 9943c931890ba953d6e8a0883355f719e27c699c Mon Sep 17 00:00:00 2001 From: gornekich Date: Wed, 16 Jun 2021 17:45:35 +0300 Subject: [PATCH] [FL-1442] Fix nfc emulation (#520) * api-hal-nfc: rework nfc detection * nfc: increase nfc detection timeout * api-hal-nfc: add 2 emulation parameters for mifare and emv * nfc: choose emulation parameters --- applications/nfc/nfc_cli.c | 4 +- applications/nfc/nfc_worker.c | 12 +- .../targets/api-hal-include/api-hal-nfc.h | 10 +- firmware/targets/f5/api-hal/api-hal-nfc.c | 125 +++++++++++------- firmware/targets/f6/api-hal/api-hal-nfc.c | 125 +++++++++++------- 5 files changed, 168 insertions(+), 108 deletions(-) diff --git a/applications/nfc/nfc_cli.c b/applications/nfc/nfc_cli.c index 6b4414ea..6a5c8162 100755 --- a/applications/nfc/nfc_cli.c +++ b/applications/nfc/nfc_cli.c @@ -24,7 +24,7 @@ void nfc_cli_detect(Cli* cli, string_t args, void* context) { printf("Detecting nfc...\r\nPress Ctrl+C to abort\r\n"); while(!cmd_exit) { cmd_exit |= cli_cmd_interrupt_received(cli); - cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true); + cmd_exit |= api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true); if(dev_cnt > 0) { printf("Found %d devices\r\n", dev_cnt); for(uint8_t i = 0; i < dev_cnt; i++) { @@ -57,7 +57,7 @@ void nfc_cli_emulate(Cli* cli, string_t args, void* context) { printf("Press Ctrl+C to abort\r\n"); while(!cli_cmd_interrupt_received(cli)) { - if(api_hal_nfc_listen(100)) { + if(api_hal_nfc_listen(ApiHalNfcEmulateParamsMifare, 100)) { printf("Reader detected\r\n"); api_hal_nfc_deactivate(); } diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index b2957608..36681ce9 100755 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -97,7 +97,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { furi_check( osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); memset(&emv_app, 0, sizeof(emv_app)); - if(api_hal_nfc_detect(&dev_list, &dev_cnt, 100, false)) { + if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) { // Card was found. Check that it supports EMV if(dev_list[0].rfInterface == RFAL_NFC_INTERFACE_ISODEP) { FURI_LOG_I(NFC_WORKER_TAG, "Send select PPSE command"); @@ -224,7 +224,7 @@ void nfc_worker_emulate_emv(NfcWorker* nfc_worker) { uint16_t* rx_len; while(nfc_worker->state == NfcWorkerStateEmulateEMV) { - if(api_hal_nfc_listen(1000)) { + if(api_hal_nfc_listen(ApiHalNfcEmulateParamsEMV, 1000)) { FURI_LOG_I(NFC_WORKER_TAG, "POS terminal detected"); // Read data from POS terminal err = api_hal_nfc_data_exchange(NULL, 0, &rx_buff, &rx_len, false); @@ -279,7 +279,7 @@ void nfc_worker_poll(NfcWorker* nfc_worker) { furi_check(osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); while(nfc_worker->state == NfcWorkerStatePoll) { - if(api_hal_nfc_detect(&dev_list, &dev_cnt, 100, true)) { + if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, true)) { // Send message with first device found message.type = NfcMessageTypeDeviceFound; if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA) { @@ -326,7 +326,7 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) { osMessageQueuePut(nfc_worker->message_queue, &message, 0, osWaitForever) == osOK); api_hal_nfc_deactivate(); memset(&mf_ul_read, 0, sizeof(mf_ul_read)); - if(api_hal_nfc_detect(&dev_list, &dev_cnt, 100, false)) { + if(api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) { if(dev_list[0].type == RFAL_NFC_LISTEN_TYPE_NFCA && mf_ul_check_card_type( dev_list[0].dev.nfca.sensRes.anticollisionInfo, @@ -352,7 +352,7 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) { mf_ul_set_default_version(&mf_ul_read); // Reinit device api_hal_nfc_deactivate(); - if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 100, false)) { + if(!api_hal_nfc_detect(&dev_list, &dev_cnt, 1000, false)) { FURI_LOG_E(NFC_WORKER_TAG, "Lost connection. Restarting search"); message.type = NfcMessageTypeMfUlNotFound; continue; @@ -431,7 +431,7 @@ void nfc_worker_read_mf_ultralight(NfcWorker* nfc_worker) { void nfc_worker_emulate(NfcWorker* nfc_worker) { while(nfc_worker->state == NfcWorkerStateEmulate) { - if(api_hal_nfc_listen(100)) { + if(api_hal_nfc_listen(ApiHalNfcEmulateParamsMifare, 100)) { FURI_LOG_I(NFC_WORKER_TAG, "Reader detected"); api_hal_nfc_deactivate(); } diff --git a/firmware/targets/api-hal-include/api-hal-nfc.h b/firmware/targets/api-hal-include/api-hal-nfc.h index 08767d03..9b3c21c5 100644 --- a/firmware/targets/api-hal-include/api-hal-nfc.h +++ b/firmware/targets/api-hal-include/api-hal-nfc.h @@ -9,6 +9,12 @@ extern "C" { #endif +/** Nfc emulation parameters */ +typedef enum { + ApiHalNfcEmulateParamsMifare, + ApiHalNfcEmulateParamsEMV, +} ApiHalNfcEmulateParams; + /** * Init nfc */ @@ -42,12 +48,12 @@ void api_hal_nfc_exit_sleep(); /** * NFC poll */ -bool api_hal_nfc_detect(rfalNfcDevice** dev_list, uint8_t* dev_cnt, uint32_t cycles, bool deactivate); +bool api_hal_nfc_detect(rfalNfcDevice** dev_list, uint8_t* dev_cnt, uint32_t timeout, bool deactivate); /** * NFC listen */ -bool api_hal_nfc_listen(uint32_t timeout); +bool api_hal_nfc_listen(ApiHalNfcEmulateParams params, uint32_t timeout); /** * NFC data exchange diff --git a/firmware/targets/f5/api-hal/api-hal-nfc.c b/firmware/targets/f5/api-hal/api-hal-nfc.c index 6980c277..1af00aa0 100644 --- a/firmware/targets/f5/api-hal/api-hal-nfc.c +++ b/firmware/targets/f5/api-hal/api-hal-nfc.c @@ -1,8 +1,54 @@ #include "api-hal-nfc.h" #include -static bool dev_is_found = false; -const uint32_t clocks_in_ms = 64 * 1000; +static const uint32_t clocks_in_ms = 64 * 1000; + +static const rfalNfcDiscoverParam api_hal_nfc_emulate_params_mifare = { + .compMode = RFAL_COMPLIANCE_MODE_NFC, + .techs2Find = RFAL_NFC_LISTEN_TECH_A, + .totalDuration = 1000, + .devLimit = 1, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + .lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_07, + .lmConfigPA.nfcid[0] = 0X36, + .lmConfigPA.nfcid[1] = 0x9C, + .lmConfigPA.nfcid[2] = 0xE7, + .lmConfigPA.nfcid[3] = 0xB1, + .lmConfigPA.nfcid[4] = 0x0A, + .lmConfigPA.nfcid[5] = 0xC1, + .lmConfigPA.nfcid[6] = 0x34, + .lmConfigPA.SENS_RES[0] = 0x44, + .lmConfigPA.SENS_RES[1] = 0x00, + .lmConfigPA.SEL_RES = 0x00, +}; + +static const rfalNfcDiscoverParam api_hal_nfc_emulate_params_emv = { + .compMode = RFAL_COMPLIANCE_MODE_EMV, + .techs2Find = RFAL_NFC_LISTEN_TECH_A, + .totalDuration = 1000, + .devLimit = 1, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + .lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_04, + .lmConfigPA.nfcid[0] = 0XCF, + .lmConfigPA.nfcid[1] = 0x72, + .lmConfigPA.nfcid[2] = 0xD4, + .lmConfigPA.nfcid[3] = 0x40, + .lmConfigPA.SENS_RES[0] = 0x04, + .lmConfigPA.SENS_RES[1] = 0x00, + .lmConfigPA.SEL_RES = 0x20, +}; ReturnCode api_hal_nfc_init() { // Check if Nfc worker was started @@ -34,19 +80,13 @@ void api_hal_nfc_exit_sleep() { rfalLowPowerModeStop(); } -static void api_hal_nfc_change_state_cb(rfalNfcState st) { - FURI_LOG_D("HAL NFC", "NFC worker state: %d", st); - if(st >= RFAL_NFC_STATE_POLL_SELECT) { - dev_is_found = true; - } -} - -bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cycles, bool deactivate) { +bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t timeout, bool deactivate) { furi_assert(dev_list); furi_assert(dev_cnt); rfalLowPowerModeStop(); - if(rfalNfcGetState() == RFAL_NFC_STATE_NOTINIT) { + rfalNfcState state = rfalNfcGetState(); + if(state == RFAL_NFC_STATE_NOTINIT) { rfalNfcInitialize(); } rfalNfcDiscoverParam params; @@ -61,33 +101,37 @@ bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cyc params.ap2pBR = RFAL_BR_424; params.maxBR = RFAL_BR_KEEP; params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; - params.notifyCb = api_hal_nfc_change_state_cb; + params.notifyCb = NULL; - dev_is_found = false; + uint32_t start = DWT->CYCCNT; rfalNfcDiscover(¶ms); - while(--cycles) { + while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); - FURI_LOG_D("HAL NFC", "Current state %d", rfalNfcGetState()); - if(dev_is_found) { - rfalNfcGetDevicesFound(dev_list, dev_cnt); - FURI_LOG_D("HAL NFC", "Found %d devices", dev_cnt); - break; + state = rfalNfcGetState(); + FURI_LOG_D("HAL NFC", "Current state %d", state); + if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { + start = DWT->CYCCNT; + continue; } - osDelay(10); + if(state == RFAL_NFC_STATE_POLL_SELECT) { + rfalNfcSelect(0); + } + if(DWT->CYCCNT - start > timeout * clocks_in_ms) { + rfalNfcDeactivate(true); + FURI_LOG_D("HAL NFC", "Timeout"); + return false; + } + osThreadYield(); } + rfalNfcGetDevicesFound(dev_list, dev_cnt); if(deactivate) { rfalNfcDeactivate(false); rfalLowPowerModeStart(); } - if(!cycles) { - FURI_LOG_D("HAL NFC", "Timeout"); - return false; - } - return true; } -bool api_hal_nfc_listen(uint32_t timeout) { +bool api_hal_nfc_listen(ApiHalNfcEmulateParams params, uint32_t timeout) { api_hal_nfc_exit_sleep(); rfalNfcState state = rfalNfcGetState(); @@ -96,30 +140,14 @@ bool api_hal_nfc_listen(uint32_t timeout) { } else if(state >= RFAL_NFC_STATE_ACTIVATED) { rfalNfcDeactivate(false); } - rfalNfcDiscoverParam params; - params.compMode = RFAL_COMPLIANCE_MODE_EMV; - params.techs2Find = RFAL_NFC_LISTEN_TECH_A; - params.totalDuration = 1000; - params.devLimit = 1; - params.wakeupEnabled = false; - params.wakeupConfigDefault = true; - params.nfcfBR = RFAL_BR_212; - params.ap2pBR = RFAL_BR_424; - params.maxBR = RFAL_BR_KEEP; - params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; - params.notifyCb = NULL; - params.lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_04; - params.lmConfigPA.nfcid[0] = 0XCF; - params.lmConfigPA.nfcid[1] = 0x72; - params.lmConfigPA.nfcid[2] = 0xD4; - params.lmConfigPA.nfcid[3] = 0x40; - params.lmConfigPA.SENS_RES[0] = 0x04; - params.lmConfigPA.SENS_RES[1] = 0x00; - params.lmConfigPA.SEL_RES = 0x20; + if(params == ApiHalNfcEmulateParamsMifare) { + rfalNfcDiscover(&api_hal_nfc_emulate_params_mifare); + } else if(params == ApiHalNfcEmulateParamsEMV) { + rfalNfcDiscover(&api_hal_nfc_emulate_params_emv); + } uint32_t start = DWT->CYCCNT; - rfalNfcDiscover(¶ms); while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); state = rfalNfcGetState(); @@ -132,9 +160,8 @@ bool api_hal_nfc_listen(uint32_t timeout) { start = DWT->CYCCNT; continue; } - taskYIELD(); + osThreadYield(); } - return true; } diff --git a/firmware/targets/f6/api-hal/api-hal-nfc.c b/firmware/targets/f6/api-hal/api-hal-nfc.c index 6980c277..1af00aa0 100644 --- a/firmware/targets/f6/api-hal/api-hal-nfc.c +++ b/firmware/targets/f6/api-hal/api-hal-nfc.c @@ -1,8 +1,54 @@ #include "api-hal-nfc.h" #include -static bool dev_is_found = false; -const uint32_t clocks_in_ms = 64 * 1000; +static const uint32_t clocks_in_ms = 64 * 1000; + +static const rfalNfcDiscoverParam api_hal_nfc_emulate_params_mifare = { + .compMode = RFAL_COMPLIANCE_MODE_NFC, + .techs2Find = RFAL_NFC_LISTEN_TECH_A, + .totalDuration = 1000, + .devLimit = 1, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + .lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_07, + .lmConfigPA.nfcid[0] = 0X36, + .lmConfigPA.nfcid[1] = 0x9C, + .lmConfigPA.nfcid[2] = 0xE7, + .lmConfigPA.nfcid[3] = 0xB1, + .lmConfigPA.nfcid[4] = 0x0A, + .lmConfigPA.nfcid[5] = 0xC1, + .lmConfigPA.nfcid[6] = 0x34, + .lmConfigPA.SENS_RES[0] = 0x44, + .lmConfigPA.SENS_RES[1] = 0x00, + .lmConfigPA.SEL_RES = 0x00, +}; + +static const rfalNfcDiscoverParam api_hal_nfc_emulate_params_emv = { + .compMode = RFAL_COMPLIANCE_MODE_EMV, + .techs2Find = RFAL_NFC_LISTEN_TECH_A, + .totalDuration = 1000, + .devLimit = 1, + .wakeupEnabled = false, + .wakeupConfigDefault = true, + .nfcfBR = RFAL_BR_212, + .ap2pBR = RFAL_BR_424, + .maxBR = RFAL_BR_KEEP, + .GBLen = RFAL_NFCDEP_GB_MAX_LEN, + .notifyCb = NULL, + .lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_04, + .lmConfigPA.nfcid[0] = 0XCF, + .lmConfigPA.nfcid[1] = 0x72, + .lmConfigPA.nfcid[2] = 0xD4, + .lmConfigPA.nfcid[3] = 0x40, + .lmConfigPA.SENS_RES[0] = 0x04, + .lmConfigPA.SENS_RES[1] = 0x00, + .lmConfigPA.SEL_RES = 0x20, +}; ReturnCode api_hal_nfc_init() { // Check if Nfc worker was started @@ -34,19 +80,13 @@ void api_hal_nfc_exit_sleep() { rfalLowPowerModeStop(); } -static void api_hal_nfc_change_state_cb(rfalNfcState st) { - FURI_LOG_D("HAL NFC", "NFC worker state: %d", st); - if(st >= RFAL_NFC_STATE_POLL_SELECT) { - dev_is_found = true; - } -} - -bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cycles, bool deactivate) { +bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t timeout, bool deactivate) { furi_assert(dev_list); furi_assert(dev_cnt); rfalLowPowerModeStop(); - if(rfalNfcGetState() == RFAL_NFC_STATE_NOTINIT) { + rfalNfcState state = rfalNfcGetState(); + if(state == RFAL_NFC_STATE_NOTINIT) { rfalNfcInitialize(); } rfalNfcDiscoverParam params; @@ -61,33 +101,37 @@ bool api_hal_nfc_detect(rfalNfcDevice **dev_list, uint8_t* dev_cnt, uint32_t cyc params.ap2pBR = RFAL_BR_424; params.maxBR = RFAL_BR_KEEP; params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; - params.notifyCb = api_hal_nfc_change_state_cb; + params.notifyCb = NULL; - dev_is_found = false; + uint32_t start = DWT->CYCCNT; rfalNfcDiscover(¶ms); - while(--cycles) { + while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); - FURI_LOG_D("HAL NFC", "Current state %d", rfalNfcGetState()); - if(dev_is_found) { - rfalNfcGetDevicesFound(dev_list, dev_cnt); - FURI_LOG_D("HAL NFC", "Found %d devices", dev_cnt); - break; + state = rfalNfcGetState(); + FURI_LOG_D("HAL NFC", "Current state %d", state); + if(state == RFAL_NFC_STATE_POLL_ACTIVATION) { + start = DWT->CYCCNT; + continue; } - osDelay(10); + if(state == RFAL_NFC_STATE_POLL_SELECT) { + rfalNfcSelect(0); + } + if(DWT->CYCCNT - start > timeout * clocks_in_ms) { + rfalNfcDeactivate(true); + FURI_LOG_D("HAL NFC", "Timeout"); + return false; + } + osThreadYield(); } + rfalNfcGetDevicesFound(dev_list, dev_cnt); if(deactivate) { rfalNfcDeactivate(false); rfalLowPowerModeStart(); } - if(!cycles) { - FURI_LOG_D("HAL NFC", "Timeout"); - return false; - } - return true; } -bool api_hal_nfc_listen(uint32_t timeout) { +bool api_hal_nfc_listen(ApiHalNfcEmulateParams params, uint32_t timeout) { api_hal_nfc_exit_sleep(); rfalNfcState state = rfalNfcGetState(); @@ -96,30 +140,14 @@ bool api_hal_nfc_listen(uint32_t timeout) { } else if(state >= RFAL_NFC_STATE_ACTIVATED) { rfalNfcDeactivate(false); } - rfalNfcDiscoverParam params; - params.compMode = RFAL_COMPLIANCE_MODE_EMV; - params.techs2Find = RFAL_NFC_LISTEN_TECH_A; - params.totalDuration = 1000; - params.devLimit = 1; - params.wakeupEnabled = false; - params.wakeupConfigDefault = true; - params.nfcfBR = RFAL_BR_212; - params.ap2pBR = RFAL_BR_424; - params.maxBR = RFAL_BR_KEEP; - params.GBLen = RFAL_NFCDEP_GB_MAX_LEN; - params.notifyCb = NULL; - params.lmConfigPA.nfcidLen = RFAL_LM_NFCID_LEN_04; - params.lmConfigPA.nfcid[0] = 0XCF; - params.lmConfigPA.nfcid[1] = 0x72; - params.lmConfigPA.nfcid[2] = 0xD4; - params.lmConfigPA.nfcid[3] = 0x40; - params.lmConfigPA.SENS_RES[0] = 0x04; - params.lmConfigPA.SENS_RES[1] = 0x00; - params.lmConfigPA.SEL_RES = 0x20; + if(params == ApiHalNfcEmulateParamsMifare) { + rfalNfcDiscover(&api_hal_nfc_emulate_params_mifare); + } else if(params == ApiHalNfcEmulateParamsEMV) { + rfalNfcDiscover(&api_hal_nfc_emulate_params_emv); + } uint32_t start = DWT->CYCCNT; - rfalNfcDiscover(¶ms); while(state != RFAL_NFC_STATE_ACTIVATED) { rfalNfcWorker(); state = rfalNfcGetState(); @@ -132,9 +160,8 @@ bool api_hal_nfc_listen(uint32_t timeout) { start = DWT->CYCCNT; continue; } - taskYIELD(); + osThreadYield(); } - return true; }