feat(registers): ICODE feature-flags decoder (GET NXP SYSTEM INFO)
Add IcodeFeatureFlags (Register) for the 16-bit ICODE feature word reported by GET NXP SYSTEM INFO (ICODE 3 Table 113; DNA/SLIX2 report a subset). Read-only capability decoder — decode a captured word to see what a tag supports. Fields mirror the existing _FEATURE_* constants one-to-one (asserted in a test). 3 new tests. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -46,7 +46,7 @@ from pm3py.transponders.hf.iso15693.type5 import NfcType5Tag, ndef_text, ndef_ur
|
||||
from pm3py.transponders.hf.iso15693.nxp.nxp_icode import NxpIcodeTag
|
||||
from pm3py.transponders.hf.iso15693.nxp.icode_slix import IcodeSlixTag
|
||||
from pm3py.transponders.hf.iso15693.nxp.icode_slix2 import IcodeSlix2Tag
|
||||
from pm3py.transponders.hf.iso15693.nxp.icode3 import Icode3Tag
|
||||
from pm3py.transponders.hf.iso15693.nxp.icode3 import Icode3Tag, IcodeFeatureFlags
|
||||
from pm3py.transponders.hf.iso15693.nxp.icode_dna import IcodeDnaTag
|
||||
from pm3py.transponders.hf.iso15693.nxp.auth_aes import NxpKeyPrivileges
|
||||
from pm3py.transponders.hf.iso15693.nxp.ntag5_platform import (
|
||||
@@ -115,7 +115,7 @@ __all__ = [
|
||||
"Icode3Tag", "IcodeDnaTag",
|
||||
"Ntag5PlatformTag", "Ntag5SwitchTag", "Ntag5LinkTag", "Ntag5BoostTag",
|
||||
"Ntag5StatusReg", "Ntag5ConfigReg",
|
||||
"NxpKeyPrivileges",
|
||||
"NxpKeyPrivileges", "IcodeFeatureFlags",
|
||||
"DesfireTag", "DesfireReader",
|
||||
"xEM", "xNT", "xM1", "FlexDF", "NExT", "MagicMifareClassicTag",
|
||||
"MutationFuzzer", "GrammarFuzzer",
|
||||
|
||||
@@ -16,6 +16,7 @@ import os
|
||||
import struct
|
||||
|
||||
from pm3py.sim.frame import RFFrame
|
||||
from pm3py.transponders.bitfield import BitField, Register
|
||||
from .icode_slix2 import IcodeSlix2Tag, PWD_READ, PWD_WRITE
|
||||
from .nxp_icode import NXP_MFG
|
||||
|
||||
@@ -44,6 +45,33 @@ _FEATURE_WRITE_CID = 1 << 14
|
||||
_FEATURE_HIGH_DATA_RATES = 1 << 15
|
||||
|
||||
|
||||
class IcodeFeatureFlags(Register):
|
||||
"""The NXP ICODE feature-flags word reported by GET NXP SYSTEM INFO (ICODE 3 Table 113;
|
||||
ICODE DNA / SLIX2 report a subset). Read-only capability bits — decode a word you captured
|
||||
to see what a tag supports. 16-bit little-endian on the wire, but treated here as one word
|
||||
(bit N is feature flag N)."""
|
||||
|
||||
_width_bits = 16
|
||||
_label = "ICODE feature flags"
|
||||
|
||||
um_pp = BitField(0, doc="user-memory password protection")
|
||||
counter = BitField(1, doc="single-block read counter")
|
||||
eas_id = BitField(2, doc="EAS ID")
|
||||
eas_pp = BitField(3, doc="EAS password protection")
|
||||
afi_pp = BitField(4, doc="AFI password protection")
|
||||
inventory_read_ext = BitField(5, doc="extended INVENTORY READ")
|
||||
eas_ir = BitField(6, doc="EAS in INVENTORY READ")
|
||||
cid = BitField(7, doc="configurable customer ID")
|
||||
originality_sig = BitField(8, doc="ECC originality signature")
|
||||
tagtamper = BitField(9, doc="tag-tamper feature")
|
||||
p_quiet = BitField(10, doc="persistent QUIET state")
|
||||
nfc_mirror = BitField(11, doc="NFC ASCII mirror")
|
||||
privacy = BitField(12, doc="privacy mode")
|
||||
destroy = BitField(13, doc="DESTROY command")
|
||||
write_cid = BitField(14, doc="writeable customer ID")
|
||||
high_data_rates = BitField(15, doc="high data-rate support")
|
||||
|
||||
|
||||
class Icode3Tag(IcodeSlix2Tag):
|
||||
"""ICODE 3 transponder (SL2S3003 / SL2S3003TT).
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@ from pm3py.sim import (
|
||||
NtagI2CConfig, NtagI2CSession, NtagI2CPtI2C, NT3H2111, NT3H2211,
|
||||
Ntag5StatusReg, Ntag5ConfigReg, Ntag5LinkTag,
|
||||
NxpKeyPrivileges, IcodeDnaTag,
|
||||
IcodeFeatureFlags,
|
||||
)
|
||||
|
||||
|
||||
@@ -467,3 +468,26 @@ class TestNxpKeyPrivileges:
|
||||
text = repr(NxpKeyPrivileges.build(read=True, destroy=True))
|
||||
assert "NXP key privileges" in text
|
||||
assert "read" in text and "destroy" in text
|
||||
|
||||
|
||||
class TestIcodeFeatureFlags:
|
||||
def test_bits_match_module_constants(self):
|
||||
import pm3py.transponders.hf.iso15693.nxp.icode3 as ic3
|
||||
# every declared field must line up with the _FEATURE_* constant of the same name
|
||||
for name, bf in IcodeFeatureFlags.fields():
|
||||
const = getattr(ic3, f"_FEATURE_{name.upper()}")
|
||||
assert (1 << bf.lo) == const, name
|
||||
|
||||
def test_decode(self):
|
||||
# um_pp(0) + counter(1) + originality_sig(8) + high_data_rates(15)
|
||||
w = (1 << 0) | (1 << 1) | (1 << 8) | (1 << 15)
|
||||
f = IcodeFeatureFlags(w)
|
||||
assert f.um_pp is True and f.counter is True
|
||||
assert f.originality_sig is True and f.high_data_rates is True
|
||||
assert f.privacy is False
|
||||
assert int(f) == w
|
||||
|
||||
def test_repr(self):
|
||||
text = repr(IcodeFeatureFlags(0x0001))
|
||||
assert "ICODE feature flags" in text
|
||||
assert "um_pp" in text
|
||||
|
||||
Reference in New Issue
Block a user