From e211dd91bc1b80a921688e73da30961a12f36472 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=BD=D1=82=D0=BE=D0=BD=20=D0=A2=D1=80=D0=BE=D1=88?= =?UTF-8?q?=D0=B8=D0=BD?= Date: Wed, 12 Aug 2026 17:46:03 +0300 Subject: [PATCH] Add decode for change, fidi, atr, pps message types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit decode_sniff_msg() dispatches to type-specific decoders: - change: 4-byte flags bitmask → card insert/eject/reset/timeout - fidi: 1-byte Fi/Di index → decoded values - atr/pps: raw hex value database.py now decodes all message types, not just tpdu. --- simtrace2_pysniff/server/database.py | 6 +-- simtrace2_pysniff/server/decode.py | 68 ++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 3 deletions(-) diff --git a/simtrace2_pysniff/server/database.py b/simtrace2_pysniff/server/database.py index 48f958a..c9b0722 100644 --- a/simtrace2_pysniff/server/database.py +++ b/simtrace2_pysniff/server/database.py @@ -176,7 +176,7 @@ class Database: 'data': data_blob.hex(), 'flags': row[5], } - if row[3] == 'tpdu' and data_blob: - from .decode import decode_message - msg['decoded'] = decode_message(data_blob) + if row[3] in ('tpdu', 'change', 'fidi', 'atr', 'pps') and data_blob: + from .decode import decode_sniff_msg + msg['decoded'] = decode_sniff_msg(data_blob, row[3]) return msg diff --git a/simtrace2_pysniff/server/decode.py b/simtrace2_pysniff/server/decode.py index 8d17d0c..60d97fc 100644 --- a/simtrace2_pysniff/server/decode.py +++ b/simtrace2_pysniff/server/decode.py @@ -465,6 +465,74 @@ def decode_message(raw_data): return result +# ──────────────────── Sniff-level message types ──────────────────── + +CHANGE_FLAGS = { + 1 << 0: 'Card inserted', + 1 << 1: 'Card ejected', + 1 << 2: 'Reset asserted', + 1 << 3: 'Reset de-asserted', + 1 << 4: 'Waiting time timeout', +} + + +def decode_change(raw_data): + """Decode a SIMtrace2 sniff_change payload (4-byte flags).""" + if len(raw_data) < 4: + return None + import struct + flags = struct.unpack('> 4 + di = fidi & 0x0f + fi_table = {0: 372, 1: 372, 2: 558, 3: 744, 4: 1116, 5: 1488, 6: 1860, 7: 0, + 8: 0, 9: 512, 10: 768, 11: 1024, 12: 1536, 13: 2048, 14: 0, 15: 0} + di_table = {0: 0, 1: 1, 2: 2, 3: 4, 4: 8, 5: 16, 6: 32, 7: 64, + 8: 12, 9: 20, 10: 2, 11: 4, 12: 8, 13: 16, 14: 32, 15: 64} + return { + 'type': 'fidi', + 'fidi': f'{fidi:02x}', + 'fi': fi, + 'di': di, + 'fi_val': fi_table.get(fi, fi), + 'di_val': di_table.get(di, di), + } + + +def decode_sniff_msg(raw_data, msg_type): + """Decode a raw sniff message of the given type. + + Returns a structured dict with at least a 'type' key, or None if + the message type has no structured decode. + """ + if msg_type == 'tpdu' and raw_data: + return decode_message(raw_data) + if msg_type == 'change' and raw_data: + return decode_change(raw_data) + if msg_type == 'fidi' and raw_data: + return decode_fidi(raw_data) + if msg_type == 'atr': + return {'type': 'atr', 'hex': raw_data.hex() if raw_data else ''} + if msg_type == 'pps': + return {'type': 'pps', 'hex': raw_data.hex() if raw_data else ''} + return None + + def _decode_field(spec, value): """Decode a single P1 or P2 field from its byte value.""" result = {'raw': f'{value:02x}'}