diff --git a/pm3py/core/hf_iso15.py b/pm3py/core/hf_iso15.py index 090b4ed..bb10f56 100644 --- a/pm3py/core/hf_iso15.py +++ b/pm3py/core/hf_iso15.py @@ -21,17 +21,22 @@ ISO15_READ_RESPONSE = 0x20 ISO15_LONG_WAIT = 0x40 -def _iso15_payload(iso_cmd: bytes) -> bytes: +# Default transport flags for read/inventory (C client CmdHF15Info/getUID). +_READ_FLAGS = ISO15_CONNECT | ISO15_HIGH_SPEED | ISO15_READ_RESPONSE # 0x31 +# Write needs the long (~22ms) tag-ack timeout and does not set HIGH_SPEED +# (mirrors the C client's hf_15_write_blk). +_WRITE_FLAGS = ISO15_CONNECT | ISO15_READ_RESPONSE | ISO15_LONG_WAIT # 0x61 + + +def _iso15_payload(iso_cmd: bytes, flags: int = _READ_FLAGS) -> bytes: """Build a HF_ISO15693_COMMAND payload from a raw ISO15693 command. Appends the ISO15693 CRC host-side (the ARM firmware ignores ISO15_APPEND_CRC — the client must add it, like the C client's AddCrc15) and prefixes the PM3 transport - flags. HIGH_SPEED + READ_RESPONSE make the firmware receive at high data rate and - actually listen for the tag's answer — without READ_RESPONSE (0x20) the firmware - passes a NULL rx buffer and replies empty. + flags. READ_RESPONSE (0x20) makes the firmware actually listen for the tag's answer; + without it the firmware passes a NULL rx buffer and replies empty. """ raw = iso_cmd + crc15_bytes(iso_cmd) - flags = ISO15_CONNECT | ISO15_HIGH_SPEED | ISO15_READ_RESPONSE return struct.pack(" dict: """Read a single block.""" + # OPTION (0x40) makes the tag return the block-security (lock) byte this parser + # expects: addressed 0x22|0x40=0x62, unaddressed 0x02|0x40=0x42. if uid: uid_bytes = bytes.fromhex(uid)[::-1] # reverse for wire - iso_cmd = bytes([0x22, 0x20]) + uid_bytes + bytes([block]) + iso_cmd = bytes([0x62, 0x20]) + uid_bytes + bytes([block]) else: - iso_cmd = bytes([0x02, 0x20, block]) # addressed without UID + iso_cmd = bytes([0x42, 0x20, block]) # unaddressed payload = _iso15_payload(iso_cmd) resp = await self._t.send_ng(Cmd.HF_ISO15693_COMMAND, payload, timeout=5.0) - if resp.status != 0 or len(resp.data) < 2: + if resp.status != 0 or len(resp.data) < 4: return {"success": False, "error": resp.status} resp_flags = resp.data[0] @@ -96,7 +103,7 @@ class HF15Commands: return {"success": False, "error_flag": resp_flags} lock_status = resp.data[1] - block_data = resp.data[2:] + block_data = resp.data[2:-2] # strip the 2-byte ISO15693 CRC the firmware relays return { "success": True, @@ -117,7 +124,7 @@ class HF15Commands: else: iso_cmd = bytes([0x02, 0x21, block]) + data - payload = _iso15_payload(iso_cmd) + payload = _iso15_payload(iso_cmd, flags=_WRITE_FLAGS) # LONG_WAIT for the ~22ms write ack resp = await self._t.send_ng(Cmd.HF_ISO15693_COMMAND, payload, timeout=5.0) success = resp.status == 0 and len(resp.data) > 0 and resp.data[0] == 0