Files
pm3py/pm3py/sniff/trace.py
michael 7c43a142e6 refactor: extract sniff infrastructure into pm3py/sniff/ sub-package
Phase 2 of package refactor. Extracts trace parsing, ISO 15693
decoders, NDEF annotation, and ANSI formatting from core/hf_iso15.py
into dedicated sniff/ modules:
- sniff/trace.py — parse_tracelog (protocol-agnostic)
- sniff/ndef.py — NDEF TLV/record decode
- sniff/decode_iso15.py — 15693 command/response decoders
- sniff/format.py — ANSI color formatting
- sniff/session.py — SniffSession with iso15() method

core/hf_iso15.py re-exports sniff symbols for backward compat.
Also fixes NTAG 5 placement (iso15693, not iso14443a4) in design doc.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-18 19:44:54 -07:00

42 lines
1.2 KiB
Python

"""Protocol-agnostic trace buffer parsing."""
import struct
# tracelog_hdr_t size: timestamp(4) + duration(2) + data_len_flags(2) = 8
TRACELOG_HDR_SIZE = 8
def parse_tracelog(raw: bytes) -> list[dict]:
"""Parse PM3 trace buffer into a list of trace entries.
Each entry: {timestamp, duration, is_response, data, parity}
"""
entries = []
offset = 0
while offset + TRACELOG_HDR_SIZE <= len(raw):
timestamp, duration, data_len_flags = struct.unpack_from("<IHH", raw, offset)
is_response = bool(data_len_flags & 0x8000)
data_len = data_len_flags & 0x7FFF
offset += TRACELOG_HDR_SIZE
if data_len == 0:
break # end of trace / sentinel
if offset + data_len > len(raw):
break
data = raw[offset:offset + data_len]
offset += data_len
parity_len = (data_len + 7) // 8 if data_len > 0 else 0
parity = raw[offset:offset + parity_len] if parity_len else b""
offset += parity_len
entries.append({
"timestamp": timestamp,
"duration": duration,
"is_response": is_response,
"data": data,
"parity": parity,
})
return entries