diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 0c161866..45a97746 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -152,7 +152,7 @@ jobs: with: issue-number: ${{ github.event.pull_request.number }} comment-author: 'github-actions[bot]' - body-includes: 'to flash the' + body-includes: 'Install with web updater' - name: 'Create or update comment' if: ${{ !github.event.pull_request.head.repo.fork && github.event.pull_request}} @@ -161,7 +161,7 @@ jobs: comment-id: ${{ steps.fc.outputs.comment-id }} issue-number: ${{ github.event.pull_request.number }} body: | - [Install with web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}) + [Install with web updater](https://my.flipp.dev/?url=https://update.flipperzero.one/builds/firmware/${{steps.names.outputs.artifacts-path}}/flipper-z-${{steps.names.outputs.default-target}}-update-${{steps.names.outputs.suffix}}.tgz&channel=${{steps.names.outputs.artifacts-path}}&version=${{steps.names.outputs.short-hash}}). edit-mode: replace compact: diff --git a/applications/nfc/helpers/nfc_debug_pcap.c b/applications/nfc/helpers/nfc_debug_pcap.c index c54dbedd..85e020b6 100644 --- a/applications/nfc/helpers/nfc_debug_pcap.c +++ b/applications/nfc/helpers/nfc_debug_pcap.c @@ -1,6 +1,7 @@ #include "nfc_debug_pcap.h" #include +#include #define TAG "NfcDebugPcap" @@ -14,9 +15,20 @@ #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA -File* nfc_debug_pcap_open(Storage* storage) { +#define NFC_DEBUG_PCAP_FILENAME "/ext/nfc/debug.pcap" +#define NFC_DEBUG_PCAP_BUFFER_SIZE 64 + +struct NfcDebugPcapWorker { + bool alive; + Storage* storage; + File* file; + StreamBufferHandle_t stream; + FuriThread* thread; +}; + +static File* nfc_debug_pcap_open(Storage* storage) { File* file = storage_file_alloc(storage); - if(!storage_file_open(file, "/ext/nfc/debug.pcap", FSAM_WRITE, FSOM_OPEN_APPEND)) { + if(!storage_file_open(file, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) { storage_file_free(file); return NULL; } @@ -41,10 +53,8 @@ File* nfc_debug_pcap_open(Storage* storage) { return file; } -void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16_t len) { - File* file = nfc_debug_pcap_open(storage); - if(!file) return; - +static void + nfc_debug_pcap_write(NfcDebugPcapWorker* instance, uint8_t event, uint8_t* data, uint16_t len) { FuriHalRtcDateTime datetime; furi_hal_rtc_get_datetime(&datetime); @@ -67,33 +77,90 @@ void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16 .event = event, .len = len << 8 | len >> 8, }; - if(storage_file_write(file, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr)) { - FURI_LOG_E(TAG, "Failed to write pcap packet header"); - } else if(storage_file_write(file, data, len) != len) { - FURI_LOG_E(TAG, "Failed to write pcap packet data"); - } - storage_file_free(file); + xStreamBufferSend(instance->stream, &pkt_hdr, sizeof(pkt_hdr), osWaitForever); + xStreamBufferSend(instance->stream, data, len, osWaitForever); } -void nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { +static void + nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { + NfcDebugPcapWorker* instance = context; uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC; - nfc_debug_pcap_write(context, event, data, bits / 8); + nfc_debug_pcap_write(instance, event, data, bits / 8); } -void nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { +static void + nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) { + NfcDebugPcapWorker* instance = context; uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD; - nfc_debug_pcap_write(context, event, data, bits / 8); + nfc_debug_pcap_write(instance, event, data, bits / 8); } -void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc) { - if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { - if(is_picc) { - tx_rx->sniff_tx = nfc_debug_pcap_write_rx; - tx_rx->sniff_rx = nfc_debug_pcap_write_tx; - } else { - tx_rx->sniff_tx = nfc_debug_pcap_write_tx; - tx_rx->sniff_rx = nfc_debug_pcap_write_rx; +int32_t nfc_debug_pcap_thread(void* context) { + NfcDebugPcapWorker* instance = context; + uint8_t buffer[NFC_DEBUG_PCAP_BUFFER_SIZE]; + + while(instance->alive) { + size_t ret = + xStreamBufferReceive(instance->stream, buffer, NFC_DEBUG_PCAP_BUFFER_SIZE, 50); + if(storage_file_write(instance->file, buffer, ret) != ret) { + FURI_LOG_E(TAG, "Failed to write pcap data"); } - tx_rx->sniff_context = storage; } + + return 0; +} + +NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage) { + NfcDebugPcapWorker* instance = malloc(sizeof(NfcDebugPcapWorker)); + + instance->alive = true; + + instance->storage = storage; + + instance->file = nfc_debug_pcap_open(storage); + + instance->stream = xStreamBufferCreate(4096, 1); + + instance->thread = furi_thread_alloc(); + furi_thread_set_name(instance->thread, "PcapWorker"); + furi_thread_set_stack_size(instance->thread, 1024); + furi_thread_set_callback(instance->thread, nfc_debug_pcap_thread); + furi_thread_set_context(instance->thread, instance); + furi_thread_start(instance->thread); + + return instance; +} + +void nfc_debug_pcap_free(NfcDebugPcapWorker* instance) { + furi_assert(instance); + + instance->alive = false; + + furi_thread_join(instance->thread); + furi_thread_free(instance->thread); + + vStreamBufferDelete(instance->stream); + + if(instance->file) storage_file_free(instance->file); + + instance->storage = NULL; + + free(instance); +} + +void nfc_debug_pcap_prepare_tx_rx( + NfcDebugPcapWorker* instance, + FuriHalNfcTxRxContext* tx_rx, + bool is_picc) { + if(!instance || !instance->file) return; + + if(is_picc) { + tx_rx->sniff_tx = nfc_debug_pcap_write_rx; + tx_rx->sniff_rx = nfc_debug_pcap_write_tx; + } else { + tx_rx->sniff_tx = nfc_debug_pcap_write_tx; + tx_rx->sniff_rx = nfc_debug_pcap_write_rx; + } + + tx_rx->sniff_context = instance; } diff --git a/applications/nfc/helpers/nfc_debug_pcap.h b/applications/nfc/helpers/nfc_debug_pcap.h index 69ba86eb..6d2a449a 100644 --- a/applications/nfc/helpers/nfc_debug_pcap.h +++ b/applications/nfc/helpers/nfc_debug_pcap.h @@ -3,10 +3,19 @@ #include #include +typedef struct NfcDebugPcapWorker NfcDebugPcapWorker; + +NfcDebugPcapWorker* nfc_debug_pcap_alloc(Storage* storage); + +void nfc_debug_pcap_free(NfcDebugPcapWorker* instance); + /** Prepare tx/rx context for debug pcap logging, if enabled. * + * @param instance NfcDebugPcapWorker* instance, can be NULL * @param tx_rx TX/RX context to log - * @param storage Storage to log to * @param is_picc if true, record Flipper as PICC, else PCD. */ -void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc); +void nfc_debug_pcap_prepare_tx_rx( + NfcDebugPcapWorker* instance, + FuriHalNfcTxRxContext* tx_rx, + bool is_picc); diff --git a/applications/nfc/nfc_worker.c b/applications/nfc/nfc_worker.c index 907f5a4c..8c8512f3 100644 --- a/applications/nfc/nfc_worker.c +++ b/applications/nfc/nfc_worker.c @@ -1,17 +1,6 @@ #include "nfc_worker_i.h" #include -#include -#include -#include -#include -#include -#include -#include - -#include "helpers/nfc_mf_classic_dict.h" -#include "helpers/nfc_debug_pcap.h" - #define TAG "NfcWorker" /***************************** NFC Worker API *******************************/ @@ -36,13 +25,22 @@ NfcWorker* nfc_worker_alloc() { } nfc_worker_change_state(nfc_worker, NfcWorkerStateReady); + if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) { + nfc_worker->debug_pcap_worker = nfc_debug_pcap_alloc(nfc_worker->storage); + } + return nfc_worker; } void nfc_worker_free(NfcWorker* nfc_worker) { furi_assert(nfc_worker); + furi_thread_free(nfc_worker->thread); + furi_record_close("storage"); + + if(nfc_worker->debug_pcap_worker) nfc_debug_pcap_free(nfc_worker->debug_pcap_worker); + free(nfc_worker); } @@ -154,7 +152,7 @@ void nfc_worker_detect(NfcWorker* nfc_worker) { void nfc_worker_emulate(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData* data = &nfc_worker->dev_data->nfc_data; NfcReaderRequestData* reader_data = &nfc_worker->dev_data->reader_data; @@ -177,7 +175,7 @@ void nfc_worker_emulate(NfcWorker* nfc_worker) { void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); EmvApplication emv_app = {}; NfcDeviceData* result = nfc_worker->dev_data; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; @@ -209,7 +207,7 @@ void nfc_worker_read_emv_app(NfcWorker* nfc_worker) { void nfc_worker_read_emv(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); EmvApplication emv_app = {}; NfcDeviceData* result = nfc_worker->dev_data; FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; @@ -258,7 +256,7 @@ void nfc_worker_read_emv(NfcWorker* nfc_worker) { void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, true); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData params = { .uid = {0xCF, 0x72, 0xd4, 0x40}, .uid_len = 4, @@ -283,7 +281,7 @@ void nfc_worker_emulate_apdu(NfcWorker* nfc_worker) { void nfc_worker_read_mifare_ultralight(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); MfUltralightReader reader = {}; MfUltralightData data = {}; NfcDeviceData* result = nfc_worker->dev_data; @@ -348,7 +346,7 @@ void nfc_worker_emulate_mifare_ul(NfcWorker* nfc_worker) { void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { furi_assert(nfc_worker->callback); FuriHalNfcTxRxContext tx_rx_ctx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx_ctx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx_ctx, false); MfClassicAuthContext auth_ctx = {}; MfClassicReader reader = {}; uint64_t curr_key = 0; @@ -491,6 +489,7 @@ void nfc_worker_mifare_classic_dict_attack(NfcWorker* nfc_worker) { void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, true); FuriHalNfcDevData* nfc_data = &nfc_worker->dev_data->nfc_data; MfClassicEmulator emulator = { .cuid = nfc_util_bytes2num(&nfc_data->uid[nfc_data->uid_len - 4], 4), @@ -519,7 +518,7 @@ void nfc_worker_emulate_mifare_classic(NfcWorker* nfc_worker) { void nfc_worker_read_mifare_desfire(NfcWorker* nfc_worker) { FuriHalNfcTxRxContext tx_rx = {}; - nfc_debug_pcap_prepare_tx_rx(&tx_rx, nfc_worker->storage, false); + nfc_debug_pcap_prepare_tx_rx(nfc_worker->debug_pcap_worker, &tx_rx, false); NfcDeviceData* result = nfc_worker->dev_data; nfc_device_data_clear(result); MifareDesfireData* data = &result->mf_df_data; diff --git a/applications/nfc/nfc_worker_i.h b/applications/nfc/nfc_worker_i.h old mode 100755 new mode 100644 index a6f937f7..18c495a4 --- a/applications/nfc/nfc_worker_i.h +++ b/applications/nfc/nfc_worker_i.h @@ -1,11 +1,22 @@ #pragma once -#include "nfc_i.h" #include "nfc_worker.h" +#include "nfc_i.h" #include #include +#include +#include +#include +#include +#include +#include +#include + +#include "helpers/nfc_mf_classic_dict.h" +#include "helpers/nfc_debug_pcap.h" + struct NfcWorker { FuriThread* thread; Storage* storage; @@ -17,6 +28,8 @@ struct NfcWorker { void* context; NfcWorkerState state; + + NfcDebugPcapWorker* debug_pcap_worker; }; void nfc_worker_change_state(NfcWorker* nfc_worker, NfcWorkerState state); diff --git a/applications/storage/storage_external_api.c b/applications/storage/storage_external_api.c index 7f600af2..77bb6550 100644 --- a/applications/storage/storage_external_api.c +++ b/applications/storage/storage_external_api.c @@ -134,6 +134,10 @@ bool storage_file_close(File* file) { } uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { + if(bytes_to_read == 0) { + return 0; + } + S_FILE_API_PROLOGUE; S_API_PROLOGUE; @@ -150,6 +154,10 @@ uint16_t storage_file_read(File* file, void* buff, uint16_t bytes_to_read) { } uint16_t storage_file_write(File* file, const void* buff, uint16_t bytes_to_write) { + if(bytes_to_write == 0) { + return 0; + } + S_FILE_API_PROLOGUE; S_API_PROLOGUE; diff --git a/firmware/targets/f7/furi_hal/furi_hal_nfc.c b/firmware/targets/f7/furi_hal/furi_hal_nfc.c index 070a33f6..6ffb6e3a 100644 --- a/firmware/targets/f7/furi_hal/furi_hal_nfc.c +++ b/firmware/targets/f7/furi_hal/furi_hal_nfc.c @@ -392,6 +392,10 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ furi_hal_spi_bus_handle_init(&furi_hal_spi_bus_handle_nfc); st25r3916ExecuteCommand(ST25R3916_CMD_UNMASK_RECEIVE_DATA); + if(tx_rx->sniff_tx) { + tx_rx->sniff_tx(tx_rx->tx_data, tx_rx->tx_bits, false, tx_rx->sniff_context); + } + // Manually wait for interrupt furi_hal_gpio_init(&gpio_rfid_pull, GpioModeInput, GpioPullDown, GpioSpeedVeryHigh); st25r3916ClearAndEnableInterrupts(ST25R3916_IRQ_MASK_RXE); @@ -428,6 +432,10 @@ static bool furi_hal_nfc_transparent_tx_rx(FuriHalNfcTxRxContext* tx_rx, uint16_ tx_rx->rx_bits = len * 8; memcpy(tx_rx->rx_data, rx, len); + if(tx_rx->sniff_rx) { + tx_rx->sniff_rx(tx_rx->rx_data, tx_rx->rx_bits, false, tx_rx->sniff_context); + } + ret = true; } else { FURI_LOG_E(TAG, "Timeout error");