diff --git a/pm3py/core/hf_iso14a.py b/pm3py/core/hf_iso14a.py index 58ec4a4..a910533 100644 --- a/pm3py/core/hf_iso14a.py +++ b/pm3py/core/hf_iso14a.py @@ -63,10 +63,16 @@ class HF14ACommands: payload=data, timeout=5.0, ) + # The firmware replies with its whole receive buffer; oldarg[0] is the number of bytes + # actually received (0 = the tag didn't answer). Trim to it so a no-response is empty, + # not a buffer of zeros. + received = resp.oldarg[0] if resp.oldarg else 0 + payload = resp.data[:received] if resp.data else b"" return { "status": resp.status, - "data": resp.data.hex() if resp.data else None, - "raw": resp.data, + "received": received, + "data": payload.hex() if payload else None, + "raw": payload, } async def sniff(self, param: int = 0) -> dict: diff --git a/tests/test_hf_14a.py b/tests/test_hf_14a.py index 636f26a..3bf8fb2 100644 --- a/tests/test_hf_14a.py +++ b/tests/test_hf_14a.py @@ -25,6 +25,31 @@ def test_14a_scan(): assert result["sak"] == 0x08 +def test_14a_raw_trims_to_received_length(): + t = AsyncMock() + hf14a = HF14ACommands(t) + # firmware replies with its whole (padded) buffer; oldarg[0] = bytes actually received + version = bytes.fromhex("0004040201000f03") + b"\x80\x91" # 8-byte version + 2-byte CRC + t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, + data=version + b"\x00" * 30, oldarg=[10, 0, 0]) + result = asyncio.get_event_loop().run_until_complete(hf14a.raw(b"\x60")) + assert result["received"] == 10 + assert result["raw"] == version # trimmed to the received length, not the padding + assert result["data"] == version.hex() + + +def test_14a_raw_no_response_is_empty(): + t = AsyncMock() + hf14a = HF14ACommands(t) + # tag didn't answer: received length 0, buffer full of zeros -> must come back empty + t.send_mix.return_value = PM3Response(cmd=Cmd.ACK, status=0, reason=0, ng=False, + data=b"\x00" * 40, oldarg=[0, 0, 0]) + result = asyncio.get_event_loop().run_until_complete(hf14a.raw(b"\x30\x99")) + assert result["received"] == 0 + assert result["raw"] == b"" # not 40 bytes of zeros + assert result["data"] is None + + def test_14a_sim_packs_ng_struct(): t = AsyncMock() hf14a = HF14ACommands(t)