diff --git a/script/pn532_cli_unit.py b/script/pn532_cli_unit.py index bf46399..700f1f1 100644 --- a/script/pn532_cli_unit.py +++ b/script/pn532_cli_unit.py @@ -908,7 +908,7 @@ def on_exec(self, args: argparse.Namespace): print(f"Config Gen2 Magic ISO15693 tag {CY}{'Success' if resp else 'Fail'}{C0}") -@hf_15.command("esetuid") +@hf_15.command("eSetUid") class HF15ESetUid(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() @@ -927,8 +927,8 @@ def args_parser(self) -> ArgumentParserNoExit: def on_exec(self, args: argparse.Namespace): if args.u is None: - print("usage: hf 15 esetuid [-h] -u [-s SLOT]") - print("hf 15 esetuid: error: the following arguments are required: -u") + print("usage: hf 15 eSetUid [-h] -u [-s SLOT]") + print("hf 15 eSetUid: error: the following arguments are required: -u") return uid = args.u if not re.match(r"^[a-fA-F0-9]{16}$", uid): @@ -944,7 +944,7 @@ def on_exec(self, args: argparse.Namespace): ) -@hf_15.command("esetblock") +@hf_15.command("eSetBlock") class HF15ESetBlock(DeviceRequiredUnit): # add parameter -b to set block data(4 bytes) def args_parser(self) -> ArgumentParserNoExit: @@ -980,7 +980,60 @@ def on_exec(self, args: argparse.Namespace): f"Set Slot {args.slot} block {args.b} to {block} {CY}{'Success' if resp else 'Fail'}{C0}" ) +@hf_15.command("eSetDump") +class HF15ESetDump(DeviceRequiredUnit): + def args_parser(self) -> ArgumentParserNoExit: + parser = ArgumentParserNoExit() + parser.description = "Set dump data of ISO15693 Emulation" + parser.add_argument( + "--json", + type=str, + required=False, + metavar="", + help="JSON file to load dump data", + ) + parser.add_argument( + "--bin", + type=str, + required=False, + metavar="", + help="BIN file to load dump data", + ) + parser.add_argument( + "-s", "--slot", default=1, type=int, help="Emulator slot(1-8)" + ) + return parser + + def on_exec(self, args: argparse.Namespace): + if not args.json and not args.bin: + print("Please choose either json file or bin file") + return + data = b"" + if args.json: + if not os.path.exists(args.json): + print(f"File {args.json} not exists") + return + with open(args.json, "r") as f: + dump_data = json.load(f) + if "blocks" in dump_data: + for block in range(len(dump_data["blocks"])): + if str(block) in dump_data["blocks"]: + data += bytes.fromhex(dump_data["blocks"][str(block)]) + else: + data += b'\x00\x00\x00\x00' + elif args.bin: + if not os.path.exists(args.bin): + print(f"File {args.bin} not exists") + return + with open(args.bin, "rb") as f: + data = f.read() + + resp = self.cmd.hf_15_eset_dump(args.slot - 1, data) + print( + f"Set Slot {args.slot} dump data {CY}{'Success' if resp else 'Fail'}{C0}" + ) + @hf_15.command("eSetwriteprotect") class HF15ESetWriteProtect(DeviceRequiredUnit): # add parameter -b to set block data(4 bytes) @@ -1257,7 +1310,7 @@ def get_block0(self, uid, args): return return str_to_bytes(block0) -@hf_mf.command("esetuid") +@hf_mf.command("eSetUid") class HfMfESetUid(DeviceRequiredUnit): def args_parser(self) -> ArgumentParserNoExit: parser = ArgumentParserNoExit() @@ -1276,8 +1329,8 @@ def args_parser(self) -> ArgumentParserNoExit: def on_exec(self, args: argparse.Namespace): if args.u is None: - print("usage: hf mf esetuid [-h] -u ") - print("hf mf esetuid: error: the following arguments are required: -u") + print("usage: hf mf eSetUid [-h] -u ") + print("hf mf eSetUid: error: the following arguments are required: -u") return uid = bytes.fromhex(args.u) if len(uid) not in [4, 7]: diff --git a/script/pn532_cmd.py b/script/pn532_cmd.py index e8a7d50..73baec8 100644 --- a/script/pn532_cmd.py +++ b/script/pn532_cmd.py @@ -775,6 +775,17 @@ def hf_15_eset_block(self, slot, index, data: bytes): resp_set = self.upload_data_block(type = 0x03, slot = slot + 0x1A, index = index, data = data) resp_save = self.hf_15_esave(slot) return resp_set and resp_save + + def hf_15_eset_dump(self, slot, bin_data): + """ + Set the whole dump for 15 emulator + """ + for block_index in range(0, len(bin_data), 4): + block_data = bin_data[block_index:block_index + 4] + resp = self.upload_data_block(type=0x03, slot=slot + 0x1A, index=block_index // 4, data=block_data) + print(f"Set block {block_index // 4:02d} {block_data.hex()}: {resp}") + resp_save = self.hf_15_esave(slot) + return resp_save def hf_15_eset_resv_eas_afi_dsfid(self, slot, data): """ diff --git a/script/pn532_com.py b/script/pn532_com.py index 22be78f..71f4ac3 100644 --- a/script/pn532_com.py +++ b/script/pn532_com.py @@ -70,9 +70,10 @@ def open(self, port) -> "Pn532Com": raise OpenFailException(error) assert self.serial_instance is not None try: - self.serial_instance.dtr = True # must make dtr enable + self.serial_instance.dtr = False + self.serial_instance.rts = False except Exception: - # not all serial support dtr, e.g. virtual serial over BLE + print("Failed to set DTR/RTS") pass self.serial_instance.timeout = THREAD_BLOCKING_TIMEOUT # clear variable @@ -83,7 +84,7 @@ def open(self, port) -> "Pn532Com": threading.Thread(target=self.thread_data_receive).start() threading.Thread(target=self.thread_data_transfer).start() threading.Thread(target=self.thread_check_timeout).start() - time.sleep(0.01) + self.set_normal_mode() time.sleep(0.01) is_pn532killer = self.is_pn532killer() diff --git a/script/pn532_enum.py b/script/pn532_enum.py index 07ad597..87f6035 100644 --- a/script/pn532_enum.py +++ b/script/pn532_enum.py @@ -81,6 +81,7 @@ class Pn532KillerCommand(enum.IntEnum): "HF15Gen2Config", "HF15ESetUid", "HF15ESetBlock", + "HF15ESetDump", "HF15ESetWriteProtect", "HF15ESetResvEasAfiDsfid", "HfMfESetUid",