Nfc: async pcap worker (#1315)

* Nfc: async pcap worker
* nfc: add pcap save to classic emulation

Co-authored-by: gornekich <n.gorbadey@gmail.com>
This commit is contained in:
あく
2022-06-14 04:14:13 +03:00
committed by GitHub
parent fb8c8ae21c
commit b2132b2ec7
7 changed files with 152 additions and 48 deletions

View File

@@ -1,6 +1,7 @@
#include "nfc_debug_pcap.h"
#include <furi_hal_rtc.h>
#include <stream_buffer.h>
#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;
}

View File

@@ -3,10 +3,19 @@
#include <furi_hal_nfc.h>
#include <storage/storage.h>
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);