#!/usr/bin/env python3 # Copyright 2019 Oticon A/S # Copyright 2023 Nordic Semiconductor ASA # SPDX-License-Identifier: Apache-2.0 # For information on the pcapng format see https://pcapng.com/ & https://www.ietf.org/staging/draft-tuexen-opsawg-pcapng-02.html # You may also want to check # https://tshark.dev/ # https://wiki.wireshark.org/Development/PcapNg import time import argparse import struct from csv_common import * # default max packet length (phdr + access address + pdu + crc) SNAPLEN = 512 def write(outfile, *inputs, snaplen = SNAPLEN, basetime=None): buf = bytearray(64) zeroes = bytearray(4) # Write pcapng SHB (section header block) (We create just 1 for the whole file) Block_len = 28 struct.pack_into('= 1.0 and freq < 81.0: rf_channel = int((freq - 1.0) / 2) elif freq >= 2401.0 and freq < 2481.0: rf_channel = int((freq - 2401.0) / 2) else: raise ValueError try: pdu_crc = bytes.fromhex(row['packet']) except: #In case the packet is broken mid byte pdu_crc = bytes.fromhex("00") if len(pdu_crc) != orig_len: # Let's handle this somehow gracefully print("Truncated input file (partial packet), writing partial packet in output") orig_len = len(pdu_crc) if is_ble: orig_len += 14; # 10 bytes phdr + 4 bytes access address else: orig_len += 5; # 4 bytes preamble + 1 bytes address/SFD incl_len = min(orig_len, snaplen) packet_padding = (4 - incl_len % 4) % 4 access_address = int(row['phy_address'], 16) ts = basetime + min_ts ts_upper = ts // 2**32; ts_lower = ts % 2**32; # Enhanced Packet Block (EPB) (header) EPB_header = 28 EPB_tail = 4 Block_len = EPB_header + incl_len + packet_padding + EPB_tail struct.pack_into('