Show T=15 as PPS capability, not a transport protocol
T=15 in the ATR is a Protocol-and-Parameter-Selection capability, not a data protocol like T=0/T=1. Previously 'Protocols: T=0, T=15' was misleading. - _decode_atr: exclude T=15 from protocols, set pps=True instead - TCK presence: only-t0 rule now also requires no PPS (T=15 implies TCK) - PWA ATR detail: 'Protocol: T=0' + 'PPS: supported' rows - +1 test with the real UICC ATR (3B 9F 95 80 1F C7 ...) - Bump 1.22.2, SW cache v33->v34
This commit is contained in:
1 parent
6376fb1591
commit
6bdbbea209
7 files changed
+29
-7
No files matched your search
+5
-2
@@ -1450,7 +1450,10 @@ function atrPpsRows(decoded) {
|
||||
rows.push(['Convention', decoded.convention || 'unknown']);
|
||||
if (decoded.ts) rows.push(['TS', '0x' + decoded.ts]);
|
||||
if (decoded.t0) rows.push(['T0', '0x' + decoded.t0 + ' — ' + decoded.historical_len + ' historical bytes']);
|
||||
if (decoded.protocols) rows.push(['Protocols', decoded.protocols.join(', ')]);
|
||||
if (decoded.protocols && decoded.protocols.length) {
|
||||
rows.push([decoded.protocols.length > 1 ? 'Protocols' : 'Protocol', decoded.protocols.join(', ')]);
|
||||
}
|
||||
if (decoded.pps) rows.push(['PPS', 'supported']);
|
||||
if (decoded.interface) {
|
||||
for (const ifc of decoded.interface) {
|
||||
rows.push([ifc.name, ifaceValue(ifc)]);
|
||||
@@ -2511,7 +2514,7 @@ function onFilterChange() {
|
||||
}
|
||||
|
||||
// ──────────────────── Versioning ────────────────────
|
||||
const PWA_VERSION = '1.22.1';
|
||||
const PWA_VERSION = '1.22.2';
|
||||
const MIN_SERVER_VERSION = '1.0.0';
|
||||
|
||||
function parseVersion(v) {
|
||||
|
||||
+1
-1
@@ -1,4 +1,4 @@
|
||||
const CACHE = 'simtrace-analyser-v33';
|
||||
const CACHE = 'simtrace-analyser-v34';
|
||||
|
||||
const PRECACHE = [
|
||||
'index.html',
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
|
||||
|
||||
[project]
|
||||
name = "simtrace2-pysniff"
|
||||
version = "1.22.1"
|
||||
version = "1.22.2"
|
||||
description = "Python-based sniffing tool for SIMtrace2 hardware (SIM card communication sniffer)"
|
||||
readme = {file = "README.md", content-type = "text/markdown"}
|
||||
license = {text = "GPL-2.0-or-later"}
|
||||
|
||||
@@ -6,7 +6,7 @@ from .gsmtap import GsmtapSender, GsmtapReceiver
|
||||
from .pcap import PcapWriter
|
||||
from .dump import FileDumper, format_message
|
||||
|
||||
__version__ = '1.22.1'
|
||||
__version__ = '1.22.2'
|
||||
__all__ = [
|
||||
'SniffSession',
|
||||
'DeviceDisconnected',
|
||||
|
||||
@@ -4177,6 +4177,7 @@ def _decode_atr(data):
|
||||
|
||||
interface = []
|
||||
protocols = []
|
||||
pps = False
|
||||
flags = t0 & 0xF0
|
||||
i = 1
|
||||
level = 1
|
||||
@@ -4229,6 +4230,9 @@ def _decode_atr(data):
|
||||
b = body[i]
|
||||
i += 1
|
||||
cur_t = b & 0x0F
|
||||
if cur_t == 15:
|
||||
pps = True
|
||||
else:
|
||||
protocols.append(_T_PROTOCOLS.get(cur_t, f'T={cur_t}'))
|
||||
flags = b & 0xF0
|
||||
level += 1
|
||||
@@ -4239,6 +4243,8 @@ def _decode_atr(data):
|
||||
result['interface'] = interface
|
||||
if protocols:
|
||||
result['protocols'] = protocols
|
||||
if pps:
|
||||
result['pps'] = True
|
||||
|
||||
k = result['historical_len']
|
||||
if k and i + k <= len(body):
|
||||
@@ -4246,7 +4252,7 @@ def _decode_atr(data):
|
||||
i += k
|
||||
|
||||
# TCK present unless only T=0 is proposed (ISO 7816-3 §8.2.5).
|
||||
only_t0 = not protocols or protocols == ['T=0']
|
||||
only_t0 = (not protocols or protocols == ['T=0']) and not pps
|
||||
if not only_t0 and i < len(body):
|
||||
tck = body[i]
|
||||
check = 0
|
||||
|
||||
@@ -898,6 +898,19 @@ class TestAtrPps(unittest.TestCase):
|
||||
self.assertEqual(r['historical']['category'], 'status information (life cycle)')
|
||||
self.assertEqual(r['historical']['life_cycle'], 'operational state (activated)')
|
||||
|
||||
def test_atr_t15_is_pps_capability(self):
|
||||
from simtrace2_pysniff.server.decode import _decode_atr
|
||||
# Real UICC ATR: T0=9F (TA1+TD1, 15 hist bytes), TA1=95, TD1=80 (T=0),
|
||||
# TD2=1F (T=15 → PPS capability), TA3=C7 (clock stop + classes A/B/C).
|
||||
r = _decode_atr(bytes.fromhex('3B9F95801FC78031E073FE21136364035B83079000F7'))
|
||||
self.assertEqual(r['protocols'], ['T=0'])
|
||||
self.assertTrue(r['pps'])
|
||||
ta3 = r['interface'][1]
|
||||
self.assertEqual(ta3['name'], 'TA3')
|
||||
self.assertEqual(ta3['clock_stop'], 'no preference')
|
||||
self.assertEqual(ta3['classes'], ['A', 'B', 'C'])
|
||||
self.assertTrue(r['tck_valid'])
|
||||
|
||||
def test_pps(self):
|
||||
from simtrace2_pysniff.server.decode import _decode_pps
|
||||
# FF 10 11 xx: PPS0=10 (T=0, PPS1 present), PPS1=11 (Fi=1,Di=1), PCK=XOR(FF,10,11)=FE
|
||||
|
||||
@@ -224,7 +224,7 @@ class TestImportEndpoint(unittest.TestCase):
|
||||
class TestVersion(unittest.TestCase):
|
||||
def test_package_version(self):
|
||||
from simtrace2_pysniff import __version__
|
||||
self.assertEqual(__version__, '1.22.1')
|
||||
self.assertEqual(__version__, '1.22.2')
|
||||
|
||||
def test_status_includes_version(self):
|
||||
import os
|
||||
|
||||
Reference in new issue
Block a user