| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166 |
- #include "nfc_debug_pcap.h"
- #include <furi_hal_rtc.h>
- #include <stream_buffer.h>
- #define TAG "NfcDebugPcap"
- #define PCAP_MAGIC 0xa1b2c3d4
- #define PCAP_MAJOR 2
- #define PCAP_MINOR 4
- #define DLT_ISO_14443 264
- #define DATA_PICC_TO_PCD 0xFF
- #define DATA_PCD_TO_PICC 0xFE
- #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB
- #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA
- #define NFC_DEBUG_PCAP_FILENAME EXT_PATH("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, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
- storage_file_free(file);
- return NULL;
- }
- if(!storage_file_tell(file)) {
- struct {
- uint32_t magic;
- uint16_t major, minor;
- uint32_t reserved[2];
- uint32_t snaplen;
- uint32_t link_type;
- } __attribute__((__packed__)) pcap_hdr = {
- .magic = PCAP_MAGIC,
- .major = PCAP_MAJOR,
- .minor = PCAP_MINOR,
- .snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
- .link_type = DLT_ISO_14443,
- };
- if(storage_file_write(file, &pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
- FURI_LOG_E(TAG, "Failed to write pcap header");
- }
- }
- return file;
- }
- 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);
- struct {
- // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
- uint32_t ts_sec;
- uint32_t ts_usec;
- uint32_t incl_len;
- uint32_t orig_len;
- // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data
- uint8_t version;
- uint8_t event;
- uint16_t len;
- } __attribute__((__packed__)) pkt_hdr = {
- .ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime),
- .ts_usec = 0,
- .incl_len = len + 4,
- .orig_len = len + 4,
- .version = 0,
- .event = event,
- .len = len << 8 | len >> 8,
- };
- xStreamBufferSend(instance->stream, &pkt_hdr, sizeof(pkt_hdr), FuriWaitForever);
- xStreamBufferSend(instance->stream, data, len, FuriWaitForever);
- }
- 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(instance, event, data, bits / 8);
- }
- 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(instance, event, data, bits / 8);
- }
- 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");
- }
- }
- 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;
- }
|