feat(iso15): hf.iso15.raw() — send an arbitrary ISO15693 request frame
The 15693 catalog builds request frames (flags | command | [mfg] | [UID] | params) but there was no transport to send them — rawcli's hf15 raw path fetched a nonexistent hf.iso15.raw and got None, so nothing executed. Add it: raw() takes the frame without a CRC (appended host-side via _iso15_payload), sends CMD_HF_ISO15693_COMMAND, and returns the firmware-relayed tag response. long_wait selects the write-length tag-ack timeout for WRITE/LOCK-class commands. This is the foundation for the ICODE SLIX/SLIX2/NTAG5 catalogs. Hardware-verified against an ICODE SLIX: GET_SYSTEM_INFO (32 blocks, IC ref 0x96, no READ_SIGNATURE → SLIX-family), READ_BLOCK, GET_RANDOM_NUMBER, and the NXP custom 02 B2 04 form all round-trip. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -20,6 +20,24 @@ def test_15_scan():
|
||||
assert "uid" in result
|
||||
|
||||
|
||||
def test_15_raw():
|
||||
from pm3py.core.protocol import crc15_bytes
|
||||
t = AsyncMock()
|
||||
iso15 = HF15Commands(t)
|
||||
resp_data = bytes([0x00, 0x00, 0x11, 0x22, 0x33, 0x44, 0x96, 0x3A]) # flags + data + crc
|
||||
t.send_ng.return_value = PM3Response(cmd=Cmd.HF_ISO15693_COMMAND, status=0,
|
||||
reason=0, ng=True, data=resp_data)
|
||||
# send a raw request frame (no CRC); it should be CRC'd + wrapped, and the tag reply returned
|
||||
r = asyncio.get_event_loop().run_until_complete(iso15.raw(b"\x02\x20\x00"))
|
||||
assert r["status"] == 0 and r["raw"] == resp_data and r["data"] == resp_data.hex()
|
||||
payload = t.send_ng.call_args.args[1] # [flags(1)][len(2)][iso_cmd][crc15(2)]
|
||||
assert payload[3:6] == b"\x02\x20\x00" # the frame, verbatim
|
||||
assert payload[6:8] == crc15_bytes(b"\x02\x20\x00") # ISO15693 CRC appended host-side
|
||||
# a hex string is accepted too
|
||||
asyncio.get_event_loop().run_until_complete(iso15.raw("02 B2 04"))
|
||||
assert t.send_ng.call_args.args[1][3:6] == b"\x02\xB2\x04"
|
||||
|
||||
|
||||
# ---- Tracelog parsing ----
|
||||
|
||||
def _make_tracelog_entry(timestamp, duration, is_response, data):
|
||||
|
||||
Reference in New Issue
Block a user