nfc_debug_pcap.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130
  1. #include "nfc_debug_pcap.h"
  2. #include <storage/storage.h>
  3. #include <stream/buffered_file_stream.h>
  4. #include <furi_hal_nfc.h>
  5. #include <furi_hal_rtc.h>
  6. #define TAG "NfcDebugPcap"
  7. #define PCAP_MAGIC 0xa1b2c3d4
  8. #define PCAP_MAJOR 2
  9. #define PCAP_MINOR 4
  10. #define DLT_ISO_14443 264
  11. #define DATA_PICC_TO_PCD 0xFF
  12. #define DATA_PCD_TO_PICC 0xFE
  13. #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB
  14. #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA
  15. #define NFC_DEBUG_PCAP_FILENAME EXT_PATH("nfc/debug.pcap")
  16. struct NfcDebugPcap {
  17. Stream* file_stream;
  18. };
  19. static Stream* nfc_debug_pcap_open(Storage* storage) {
  20. Stream* stream = NULL;
  21. stream = buffered_file_stream_alloc(storage);
  22. if(!buffered_file_stream_open(stream, NFC_DEBUG_PCAP_FILENAME, FSAM_WRITE, FSOM_OPEN_APPEND)) {
  23. buffered_file_stream_close(stream);
  24. stream_free(stream);
  25. stream = NULL;
  26. } else {
  27. if(!stream_tell(stream)) {
  28. struct {
  29. uint32_t magic;
  30. uint16_t major, minor;
  31. uint32_t reserved[2];
  32. uint32_t snaplen;
  33. uint32_t link_type;
  34. } __attribute__((__packed__)) pcap_hdr = {
  35. .magic = PCAP_MAGIC,
  36. .major = PCAP_MAJOR,
  37. .minor = PCAP_MINOR,
  38. .snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
  39. .link_type = DLT_ISO_14443,
  40. };
  41. if(stream_write(stream, (uint8_t*)&pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
  42. FURI_LOG_E(TAG, "Failed to write pcap header");
  43. buffered_file_stream_close(stream);
  44. stream_free(stream);
  45. stream = NULL;
  46. }
  47. }
  48. }
  49. return stream;
  50. }
  51. NfcDebugPcap* nfc_debug_pcap_alloc() {
  52. NfcDebugPcap* instance = malloc(sizeof(NfcDebugPcap));
  53. Storage* storage = furi_record_open(RECORD_STORAGE);
  54. instance->file_stream = nfc_debug_pcap_open(storage);
  55. if(!instance->file_stream) {
  56. free(instance);
  57. instance = NULL;
  58. }
  59. furi_record_close(RECORD_STORAGE);
  60. return instance;
  61. }
  62. void nfc_debug_pcap_free(NfcDebugPcap* instance) {
  63. furi_assert(instance);
  64. furi_assert(instance->file_stream);
  65. buffered_file_stream_close(instance->file_stream);
  66. stream_free(instance->file_stream);
  67. free(instance);
  68. }
  69. void nfc_debug_pcap_process_data(
  70. NfcDebugPcap* instance,
  71. uint8_t* data,
  72. uint16_t len,
  73. bool reader_to_tag,
  74. bool crc_dropped) {
  75. furi_assert(instance);
  76. furi_assert(data);
  77. FuriHalRtcDateTime datetime;
  78. furi_hal_rtc_get_datetime(&datetime);
  79. uint8_t event = 0;
  80. if(reader_to_tag) {
  81. if(crc_dropped) {
  82. event = DATA_PCD_TO_PICC_CRC_DROPPED;
  83. } else {
  84. event = DATA_PCD_TO_PICC;
  85. }
  86. } else {
  87. if(crc_dropped) {
  88. event = DATA_PICC_TO_PCD_CRC_DROPPED;
  89. } else {
  90. event = DATA_PICC_TO_PCD;
  91. }
  92. }
  93. struct {
  94. // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
  95. uint32_t ts_sec;
  96. uint32_t ts_usec;
  97. uint32_t incl_len;
  98. uint32_t orig_len;
  99. // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data
  100. uint8_t version;
  101. uint8_t event;
  102. uint16_t len;
  103. } __attribute__((__packed__)) pkt_hdr = {
  104. .ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime),
  105. .ts_usec = 0,
  106. .incl_len = len + 4,
  107. .orig_len = len + 4,
  108. .version = 0,
  109. .event = event,
  110. .len = len << 8 | len >> 8,
  111. };
  112. stream_write(instance->file_stream, (uint8_t*)&pkt_hdr, sizeof(pkt_hdr));
  113. stream_write(instance->file_stream, data, len);
  114. }