diff --git a/applications/main/nfc/helpers/nfc_custom_event.h b/applications/main/nfc/helpers/nfc_custom_event.h index 4227a5b14..aa932a3d8 100644 --- a/applications/main/nfc/helpers/nfc_custom_event.h +++ b/applications/main/nfc/helpers/nfc_custom_event.h @@ -12,4 +12,6 @@ enum NfcCustomEvent { NfcCustomEventDictAttackSkip, NfcCustomEventRpcLoad, NfcCustomEventRpcSessionClose, + NfcCustomEventUpdateLog, + NfcCustomEventSaveShadow, }; diff --git a/applications/main/nfc/scenes/nfc_scene_nfcv_emulate.c b/applications/main/nfc/scenes/nfc_scene_nfcv_emulate.c index 53da36679..77d1d420d 100644 --- a/applications/main/nfc/scenes/nfc_scene_nfcv_emulate.c +++ b/applications/main/nfc/scenes/nfc_scene_nfcv_emulate.c @@ -1,6 +1,6 @@ #include "../nfc_i.h" -#define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (100) +#define NFC_SCENE_EMULATE_NFCV_LOG_SIZE_MAX (200) enum { NfcSceneNfcVEmulateStateWidget, @@ -11,7 +11,17 @@ bool nfc_scene_nfcv_emulate_worker_callback(NfcWorkerEvent event, void* context) UNUSED(event); furi_assert(context); Nfc* nfc = context; - view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventWorkerExit); + + switch(event) { + case NfcWorkerEventNfcVCommandExecuted: + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventUpdateLog); + break; + case NfcWorkerEventNfcVContentChanged: + view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventSaveShadow); + break; + default: + break; + } return true; } @@ -29,7 +39,6 @@ void nfc_scene_nfcv_emulate_textbox_callback(void* context) { view_dispatcher_send_custom_event(nfc->view_dispatcher, NfcCustomEventViewExit); } -// Add widget with device name or inform that data received static void nfc_scene_nfcv_emulate_widget_config(Nfc* nfc, bool data_received) { FuriHalNfcDevData* data = &nfc->dev->dev_data.nfc_data; Widget* widget = nfc->widget; @@ -91,7 +100,7 @@ bool nfc_scene_nfcv_emulate_on_event(void* context, SceneManagerEvent event) { bool consumed = false; if(event.type == SceneManagerEventTypeCustom) { - if(event.event == NfcCustomEventWorkerExit) { + if(event.event == NfcCustomEventUpdateLog) { // Add data button to widget if data is received for the first time if(!furi_string_size(nfc->text_box_store)) { nfc_scene_nfcv_emulate_widget_config(nfc, true); @@ -111,6 +120,11 @@ bool nfc_scene_nfcv_emulate_on_event(void* context, SceneManagerEvent event) { strcpy(nfcv_data->last_command, ""); } consumed = true; + } else if(event.event == NfcCustomEventSaveShadow) { + if(furi_string_size(nfc->dev->load_path)) { + nfc_device_save_shadow(nfc->dev, furi_string_get_cstr(nfc->dev->load_path)); + } + consumed = true; } else if(event.event == GuiButtonTypeCenter && state == NfcSceneNfcVEmulateStateWidget) { view_dispatcher_switch_to_view(nfc->view_dispatcher, NfcViewTextBox); scene_manager_set_scene_state( diff --git a/lib/nfc/nfc_worker.c b/lib/nfc/nfc_worker.c index 4e07c9ef2..efd10aab9 100644 --- a/lib/nfc/nfc_worker.c +++ b/lib/nfc/nfc_worker.c @@ -110,7 +110,7 @@ int32_t nfc_worker_task(void* context) { } else if(nfc_worker->state == NfcWorkerStateAnalyzeReader) { nfc_worker_analyze_reader(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - nfc_worker_emulate_nfcv(nfc_worker); + nfc_worker_nfcv_emulate(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateNfcVUnlock) { nfc_worker_nfcv_unlock(nfc_worker); } else if(nfc_worker->state == NfcWorkerStateNfcVUnlockAndSave) { @@ -122,13 +122,15 @@ int32_t nfc_worker_task(void* context) { return 0; } -static bool nfc_worker_read_nfcv_content(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { +static bool nfc_worker_read_nfcv(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { bool read_success = false; NfcVReader reader = {}; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; + furi_hal_nfc_sleep(); + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, tx_rx, false); reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); @@ -148,6 +150,36 @@ static bool nfc_worker_read_nfcv_content(NfcWorker* nfc_worker, FuriHalNfcTxRxCo return read_success; } +void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker) { + FuriHalNfcTxRxContext tx_rx = {}; + FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; + NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); + reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); + } + + nfcv_emu_init(nfc_data, nfcv_data); + while(nfc_worker->state == NfcWorkerStateNfcVEmulate) { + if(nfcv_emu_loop(&tx_rx, nfc_data, nfcv_data, 50)) { + if(nfc_worker->callback) { + nfc_worker->callback(NfcWorkerEventNfcVCommandExecuted, nfc_worker->context); + if(nfcv_data->modified) { + nfc_worker->callback(NfcWorkerEventNfcVContentChanged, nfc_worker->context); + nfcv_data->modified = false; + } + } + } + furi_delay_ms(0); + } + nfcv_emu_deinit(nfcv_data); + + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + reader_analyzer_stop(nfc_worker->reader_analyzer); + } +} + void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -508,20 +540,6 @@ static bool nfc_worker_read_nfca(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* t return card_read; } -static bool nfc_worker_read_nfcv(NfcWorker* nfc_worker, FuriHalNfcTxRxContext* tx_rx) { - furi_assert(nfc_worker); - furi_assert(tx_rx); - - bool card_read = false; - furi_hal_nfc_sleep(); - - /* until here the UID field is reversed from the reader IC. - we will read it here again and it will get placed in the right order. */ - card_read = nfc_worker_read_nfcv_content(nfc_worker, tx_rx); - - return card_read; -} - void nfc_worker_read(NfcWorker* nfc_worker) { furi_assert(nfc_worker); furi_assert(nfc_worker->callback); @@ -692,32 +710,6 @@ void nfc_worker_emulate_uid(NfcWorker* nfc_worker) { } } -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker) { - FuriHalNfcTxRxContext tx_rx = {}; - FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; - NfcVData* nfcv_data = &nfc_worker->dev_data->nfcv_data; - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_prepare_tx_rx(nfc_worker->reader_analyzer, &tx_rx, true); - reader_analyzer_start(nfc_worker->reader_analyzer, ReaderAnalyzerModeDebugLog); - } - - nfcv_emu_init(nfc_data, nfcv_data); - while(nfc_worker->state == NfcWorkerStateNfcVEmulate) { - if(nfcv_emu_loop(&tx_rx, nfc_data, nfcv_data, 50)) { - if(nfc_worker->callback) { - nfc_worker->callback(NfcWorkerEventSuccess, nfc_worker->context); - } - } - furi_delay_ms(0); - } - nfcv_emu_deinit(nfcv_data); - - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - reader_analyzer_stop(nfc_worker->reader_analyzer); - } -} - void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; FuriHalNfcDevData params = { diff --git a/lib/nfc/nfc_worker.h b/lib/nfc/nfc_worker.h index e707755de..39b6fa592 100644 --- a/lib/nfc/nfc_worker.h +++ b/lib/nfc/nfc_worker.h @@ -75,6 +75,8 @@ typedef enum { NfcWorkerEventMfUltralightPassKey, // NFC worker requesting manual key NfcWorkerEventMfUltralightPwdAuth, // Reader sent auth command NfcWorkerEventNfcVPassKey, // NFC worker requesting manual key + NfcWorkerEventNfcVCommandExecuted, + NfcWorkerEventNfcVContentChanged, } NfcWorkerEvent; typedef bool (*NfcWorkerCallback)(NfcWorkerEvent event, void* context); @@ -94,4 +96,4 @@ void nfc_worker_start( void nfc_worker_stop(NfcWorker* nfc_worker); void nfc_worker_nfcv_unlock(NfcWorker* nfc_worker); -void nfc_worker_emulate_nfcv(NfcWorker* nfc_worker); +void nfc_worker_nfcv_emulate(NfcWorker* nfc_worker); diff --git a/lib/nfc/protocols/nfcv.c b/lib/nfc/protocols/nfcv.c index 69f179b4b..66b14cbd3 100644 --- a/lib/nfc/protocols/nfcv.c +++ b/lib/nfc/protocols/nfcv.c @@ -561,6 +561,7 @@ void nfcv_emu_handle_packet( &nfcv_data->data[nfcv_data->block_size * block], &nfcv_data->frame[ctx->payload_offset + data_pos], data_len); + nfcv_data->modified = true; } nfcv_emu_send( tx_rx, nfcv_data, ctx->response_buffer, 1, ctx->response_flags, ctx->send_time); @@ -719,7 +720,9 @@ bool nfcv_emu_loop( pulse_reader_receive(nfcv_data->emu_air.reader_signal, timeout_ms * 1000); uint32_t timestamp = DWT->CYCCNT; + /* when timed out, reset to SOF state */ if(periods == PULSE_READER_NO_EDGE) { + frame_state = NFCV_FRAME_STATE_SOF1; break; } if(periods == PULSE_READER_LOST_EDGE) { diff --git a/lib/nfc/protocols/nfcv.h b/lib/nfc/protocols/nfcv.h index 9d7a56326..c349b6e95 100644 --- a/lib/nfc/protocols/nfcv.h +++ b/lib/nfc/protocols/nfcv.h @@ -161,6 +161,7 @@ typedef struct { uint16_t block_num; uint8_t block_size; uint8_t data[NFCV_MAX_DUMP_SIZE]; + bool modified; /* specfic variant infos */ NfcVSubtype sub_type; diff --git a/lib/nfc/protocols/slix.c b/lib/nfc/protocols/slix.c index 6c6deacdd..eaa75509f 100644 --- a/lib/nfc/protocols/slix.c +++ b/lib/nfc/protocols/slix.c @@ -236,6 +236,7 @@ bool slix_generic_protocol_filter( break; case SLIX_PASS_PRIVACY: slix->privacy = false; + nfcv_data->modified = true; break; case SLIX_PASS_DESTROY: FURI_LOG_D(TAG, "Pooof! Got destroyed");