nfc_debug_pcap.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include "nfc_debug_pcap.h"
  2. #include <furi_hal_rtc.h>
  3. #define TAG "NfcDebugPcap"
  4. #define PCAP_MAGIC 0xa1b2c3d4
  5. #define PCAP_MAJOR 2
  6. #define PCAP_MINOR 4
  7. #define DLT_ISO_14443 264
  8. #define DATA_PICC_TO_PCD 0xFF
  9. #define DATA_PCD_TO_PICC 0xFE
  10. #define DATA_PICC_TO_PCD_CRC_DROPPED 0xFB
  11. #define DATA_PCD_TO_PICC_CRC_DROPPED 0xFA
  12. File* nfc_debug_pcap_open(Storage* storage) {
  13. File* file = storage_file_alloc(storage);
  14. if(!storage_file_open(file, "/ext/nfc/debug.pcap", FSAM_WRITE, FSOM_OPEN_APPEND)) {
  15. storage_file_free(file);
  16. return NULL;
  17. }
  18. if(!storage_file_tell(file)) {
  19. struct {
  20. uint32_t magic;
  21. uint16_t major, minor;
  22. uint32_t reserved[2];
  23. uint32_t snaplen;
  24. uint32_t link_type;
  25. } __attribute__((__packed__)) pcap_hdr = {
  26. .magic = PCAP_MAGIC,
  27. .major = PCAP_MAJOR,
  28. .minor = PCAP_MINOR,
  29. .snaplen = FURI_HAL_NFC_DATA_BUFF_SIZE,
  30. .link_type = DLT_ISO_14443,
  31. };
  32. if(storage_file_write(file, &pcap_hdr, sizeof(pcap_hdr)) != sizeof(pcap_hdr)) {
  33. FURI_LOG_E(TAG, "Failed to write pcap header");
  34. }
  35. }
  36. return file;
  37. }
  38. void nfc_debug_pcap_write(Storage* storage, uint8_t event, uint8_t* data, uint16_t len) {
  39. File* file = nfc_debug_pcap_open(storage);
  40. if(!file) return;
  41. FuriHalRtcDateTime datetime;
  42. furi_hal_rtc_get_datetime(&datetime);
  43. struct {
  44. // https://wiki.wireshark.org/Development/LibpcapFileFormat#record-packet-header
  45. uint32_t ts_sec;
  46. uint32_t ts_usec;
  47. uint32_t incl_len;
  48. uint32_t orig_len;
  49. // https://www.kaiser.cx/posts/pcap-iso14443/#_packet_data
  50. uint8_t version;
  51. uint8_t event;
  52. uint16_t len;
  53. } __attribute__((__packed__)) pkt_hdr = {
  54. .ts_sec = furi_hal_rtc_datetime_to_timestamp(&datetime),
  55. .ts_usec = 0,
  56. .incl_len = len + 4,
  57. .orig_len = len + 4,
  58. .version = 0,
  59. .event = event,
  60. .len = len << 8 | len >> 8,
  61. };
  62. if(storage_file_write(file, &pkt_hdr, sizeof(pkt_hdr)) != sizeof(pkt_hdr)) {
  63. FURI_LOG_E(TAG, "Failed to write pcap packet header");
  64. } else if(storage_file_write(file, data, len) != len) {
  65. FURI_LOG_E(TAG, "Failed to write pcap packet data");
  66. }
  67. storage_file_free(file);
  68. }
  69. void nfc_debug_pcap_write_tx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  70. uint8_t event = crc_dropped ? DATA_PCD_TO_PICC_CRC_DROPPED : DATA_PCD_TO_PICC;
  71. nfc_debug_pcap_write(context, event, data, bits / 8);
  72. }
  73. void nfc_debug_pcap_write_rx(uint8_t* data, uint16_t bits, bool crc_dropped, void* context) {
  74. uint8_t event = crc_dropped ? DATA_PICC_TO_PCD_CRC_DROPPED : DATA_PICC_TO_PCD;
  75. nfc_debug_pcap_write(context, event, data, bits / 8);
  76. }
  77. void nfc_debug_pcap_prepare_tx_rx(FuriHalNfcTxRxContext* tx_rx, Storage* storage, bool is_picc) {
  78. if(furi_hal_rtc_is_flag_set(FuriHalRtcFlagDebug)) {
  79. if(is_picc) {
  80. tx_rx->sniff_tx = nfc_debug_pcap_write_rx;
  81. tx_rx->sniff_rx = nfc_debug_pcap_write_tx;
  82. } else {
  83. tx_rx->sniff_tx = nfc_debug_pcap_write_tx;
  84. tx_rx->sniff_rx = nfc_debug_pcap_write_rx;
  85. }
  86. tx_rx->sniff_context = storage;
  87. }
  88. }