mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
Replace the PositiveChameleonCMD class with an exception decorator
This commit is contained in:
@@ -59,12 +59,8 @@ class BaseCLIUnit:
|
||||
self._device_com = com
|
||||
|
||||
@property
|
||||
def cmd_positive(self) -> chameleon_cmd.BaseChameleonCMD:
|
||||
return chameleon_cmd.PositiveChameleonCMD(self.device_com)
|
||||
|
||||
@property
|
||||
def cmd_standard(self) -> chameleon_cmd.BaseChameleonCMD:
|
||||
return chameleon_cmd.BaseChameleonCMD(self.device_com)
|
||||
def cmd(self) -> chameleon_cmd.ChameleonCMD:
|
||||
return chameleon_cmd.ChameleonCMD(self.device_com)
|
||||
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
"""
|
||||
@@ -172,7 +168,7 @@ class ReaderRequiredUnit(DeviceRequiredUnit):
|
||||
|
||||
def before_exec(self, args: argparse.Namespace):
|
||||
if super(ReaderRequiredUnit, self).before_exec(args):
|
||||
ret = self.cmd_standard.is_reader_device_mode()
|
||||
ret = self.cmd.is_reader_device_mode()
|
||||
if ret:
|
||||
return True
|
||||
else:
|
||||
@@ -221,10 +217,10 @@ class HWModeSet(DeviceRequiredUnit):
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
if args.mode == 'reader' or args.mode == 'r':
|
||||
self.cmd_standard.set_reader_device_mode(True)
|
||||
self.cmd.set_reader_device_mode(True)
|
||||
print("Switch to { Tag Reader } mode successfully.")
|
||||
else:
|
||||
self.cmd_standard.set_reader_device_mode(False)
|
||||
self.cmd.set_reader_device_mode(False)
|
||||
print("Switch to { Tag Emulator } mode successfully.")
|
||||
|
||||
|
||||
@@ -233,7 +229,7 @@ class HWModeGet(DeviceRequiredUnit):
|
||||
pass
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
print(f"- Device Mode ( Tag {'Reader' if self.cmd_standard.is_reader_device_mode() else 'Emulator'} )")
|
||||
print(f"- Device Mode ( Tag {'Reader' if self.cmd.is_reader_device_mode() else 'Emulator'} )")
|
||||
|
||||
|
||||
class HWChipIdGet(DeviceRequiredUnit):
|
||||
@@ -242,7 +238,7 @@ class HWChipIdGet(DeviceRequiredUnit):
|
||||
return None
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
print(f' - Device chip ID: ' + self.cmd_positive.get_device_chip_id())
|
||||
print(f' - Device chip ID: ' + self.cmd.get_device_chip_id())
|
||||
|
||||
|
||||
class HWAddressGet(DeviceRequiredUnit):
|
||||
@@ -251,7 +247,7 @@ class HWAddressGet(DeviceRequiredUnit):
|
||||
return None
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
print(f' - Device address: ' + self.cmd_positive.get_device_address())
|
||||
print(f' - Device address: ' + self.cmd.get_device_address())
|
||||
|
||||
|
||||
class HF14AScan(ReaderRequiredUnit):
|
||||
@@ -259,7 +255,7 @@ class HF14AScan(ReaderRequiredUnit):
|
||||
pass
|
||||
|
||||
def scan(self):
|
||||
resp: chameleon_com.Response = self.cmd_standard.scan_tag_14a()
|
||||
resp: chameleon_com.Response = self.cmd.scan_tag_14a()
|
||||
if resp.status == chameleon_status.Device.HF_TAG_OK:
|
||||
info = chameleon_cstruct.parse_14a_scan_tag_result(resp.data)
|
||||
print(f"- UID Size: {info['uid_size']}")
|
||||
@@ -282,11 +278,11 @@ class HF14AInfo(ReaderRequiredUnit):
|
||||
|
||||
def info(self):
|
||||
# detect mf1 support
|
||||
resp = self.cmd_positive.detect_mf1_support()
|
||||
resp = self.cmd.detect_mf1_support()
|
||||
if resp.status == chameleon_status.Device.HF_TAG_OK:
|
||||
# detect prng
|
||||
print("- Mifare Classic technology")
|
||||
resp = self.cmd_standard.detect_mf1_nt_level()
|
||||
resp = self.cmd.detect_mf1_nt_level()
|
||||
if resp.status == 0x00:
|
||||
prng_level = "Weak"
|
||||
elif resp.status == 0x24:
|
||||
@@ -336,8 +332,8 @@ class HFMFNested(ReaderRequiredUnit):
|
||||
:return:
|
||||
"""
|
||||
# acquire
|
||||
dist_resp = self.cmd_positive.detect_nt_distance(block_known, type_known, key_known)
|
||||
nt_resp = self.cmd_positive.acquire_nested(block_known, type_known, key_known, block_target, type_target)
|
||||
dist_resp = self.cmd.detect_nt_distance(block_known, type_known, key_known)
|
||||
nt_resp = self.cmd.acquire_nested(block_known, type_known, key_known, block_target, type_target)
|
||||
# parse
|
||||
dist_obj = chameleon_cstruct.parse_nt_distance_detect_result(dist_resp.data)
|
||||
nt_obj = chameleon_cstruct.parse_nested_nt_acquire_group(nt_resp.data)
|
||||
@@ -371,7 +367,7 @@ class HFMFNested(ReaderRequiredUnit):
|
||||
print(f" - [{len(key_list)} candidate keys found ]")
|
||||
for key in key_list:
|
||||
key_bytes = bytearray.fromhex(key)
|
||||
ret = self.cmd_standard.auth_mf1_key(block_target, type_target, key_bytes)
|
||||
ret = self.cmd.auth_mf1_key(block_target, type_target, key_bytes)
|
||||
if ret.status == chameleon_status.Device.HF_TAG_OK:
|
||||
return key
|
||||
else:
|
||||
@@ -429,7 +425,7 @@ class HFMFDarkside(ReaderRequiredUnit):
|
||||
first_recover = True
|
||||
retry_count = 0
|
||||
while retry_count < 0xFF:
|
||||
darkside_resp = self.cmd_positive.acquire_darkside(block_target, type_target, first_recover, 15)
|
||||
darkside_resp = self.cmd.acquire_darkside(block_target, type_target, first_recover, 15)
|
||||
first_recover = False # not first run.
|
||||
darkside_obj = chameleon_cstruct.parse_darkside_acquire_result(darkside_resp.data)
|
||||
self.darkside_list.append(darkside_obj)
|
||||
@@ -462,7 +458,7 @@ class HFMFDarkside(ReaderRequiredUnit):
|
||||
# auth key
|
||||
for key in key_list:
|
||||
key_bytes = bytearray.fromhex(key)
|
||||
auth_ret = self.cmd_positive.auth_mf1_key(block_target, type_target, key_bytes)
|
||||
auth_ret = self.cmd.auth_mf1_key(block_target, type_target, key_bytes)
|
||||
if auth_ret.status == chameleon_status.Device.HF_TAG_OK:
|
||||
return key
|
||||
return None
|
||||
@@ -509,7 +505,7 @@ class HFMFRDBL(BaseMF1AuthOpera):
|
||||
# hf mf rdbl -b 2 -t A -k FFFFFFFFFFFF
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
param = self.get_param(args)
|
||||
resp = self.cmd_positive.read_mf1_block(param.block, param.type, param.key)
|
||||
resp = self.cmd.read_mf1_block(param.block, param.type, param.key)
|
||||
print(f" - Data: {resp.data.hex()}")
|
||||
|
||||
|
||||
@@ -527,7 +523,7 @@ class HFMFWRBL(BaseMF1AuthOpera):
|
||||
if not re.match(r"^[a-fA-F0-9]{32}$", args.data):
|
||||
raise ArgsParserError("Data must include 32 HEX symbols")
|
||||
param.data = bytearray.fromhex(args.data)
|
||||
resp = self.cmd_standard.write_mf1_block(param.block, param.type, param.key, param.data)
|
||||
resp = self.cmd.write_mf1_block(param.block, param.type, param.key, param.data)
|
||||
if resp.status == chameleon_status.Device.HF_TAG_OK:
|
||||
print(f" - {colorama.Fore.GREEN}Write done.{colorama.Style.RESET_ALL}")
|
||||
else:
|
||||
@@ -545,7 +541,7 @@ class HFMFDetectionEnable(DeviceRequiredUnit):
|
||||
# hf mf detection enable -e 1
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
enable = True if args.enable == 1 else False
|
||||
self.cmd_positive.set_mf1_detection_enable(enable)
|
||||
self.cmd.set_mf1_detection_enable(enable)
|
||||
print(f" - Set mf1 detection { 'enable' if enable else 'disable'}.")
|
||||
|
||||
|
||||
@@ -556,7 +552,7 @@ class HFMFDetectionLogCount(DeviceRequiredUnit):
|
||||
|
||||
# hf mf detection count
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
data_bytes = self.cmd_standard.get_mf1_detection_count().data
|
||||
data_bytes = self.cmd.get_mf1_detection_count().data
|
||||
count = int.from_bytes(data_bytes, "little", signed=False)
|
||||
print(f" - MF1 detection log count = {count}")
|
||||
|
||||
@@ -604,13 +600,13 @@ class HFMFDetectionDecrypt(DeviceRequiredUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
buffer = bytearray()
|
||||
index = 0
|
||||
count = int.from_bytes(self.cmd_standard.get_mf1_detection_count().data, "little", signed=False)
|
||||
count = int.from_bytes(self.cmd.get_mf1_detection_count().data, "little", signed=False)
|
||||
if count == 0:
|
||||
print(" - No detection log to download")
|
||||
return
|
||||
print(f" - MF1 detection log count = {count}, start download", end="")
|
||||
while index < count:
|
||||
tmp = self.cmd_positive.get_mf1_detection_log(index).data
|
||||
tmp = self.cmd.get_mf1_detection_log(index).data
|
||||
recv_count = int(len(tmp) / HFMFDetectionDecrypt.detection_log_size)
|
||||
index += recv_count
|
||||
buffer.extend(tmp)
|
||||
@@ -684,7 +680,7 @@ class HFMFELoad(DeviceRequiredUnit):
|
||||
block_data = buffer[index: index + 16]
|
||||
index += 16
|
||||
# load to device
|
||||
self.cmd_positive.set_mf1_block_data(block, block_data)
|
||||
self.cmd.set_mf1_block_data(block, block_data)
|
||||
print('.', end='')
|
||||
block += 1
|
||||
print("\n - Load success")
|
||||
@@ -723,7 +719,7 @@ class HFMFSim(DeviceRequiredUnit):
|
||||
else:
|
||||
raise Exception("UID must be hex")
|
||||
|
||||
self.cmd_positive.set_mf1_anti_collision_res(sak, atqa, uid)
|
||||
self.cmd.set_mf1_anti_collision_res(sak, atqa, uid)
|
||||
print(" - Set anti-collision resources success")
|
||||
|
||||
|
||||
@@ -733,7 +729,7 @@ class LFEMRead(ReaderRequiredUnit):
|
||||
return None
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
resp = self.cmd_positive.read_em_410x()
|
||||
resp = self.cmd.read_em_410x()
|
||||
id_hex = resp.data.hex()
|
||||
print(f" - EM410x ID(10H): {colorama.Fore.GREEN}{id_hex}{colorama.Style.RESET_ALL}")
|
||||
|
||||
@@ -774,7 +770,7 @@ class LFEMWriteT55xx(LFEMCardRequiredUnit, ReaderRequiredUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
id_hex = args.id
|
||||
id_bytes = bytearray.fromhex(id_hex)
|
||||
self.cmd_positive.write_em_410x_to_t55xx(id_bytes)
|
||||
self.cmd.write_em_410x_to_t55xx(id_bytes)
|
||||
print(f" - EM410x ID(10H): {id_hex} write done.")
|
||||
|
||||
|
||||
@@ -818,7 +814,7 @@ class HWSlotSet(SlotIndexRequireUnit):
|
||||
# hw slot change -s 1
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
slot_index = args.slot
|
||||
self.cmd_positive.set_slot_activated(slot_index)
|
||||
self.cmd.set_slot_activated(slot_index)
|
||||
print(f" - Set slot {slot_index} activated success.")
|
||||
|
||||
|
||||
@@ -855,7 +851,7 @@ class HWSlotTagType(TagTypeRequiredUnit, SlotIndexRequireUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
tag_type = args.type
|
||||
slot_index = args.slot
|
||||
self.cmd_positive.set_slot_tag_type(slot_index, tag_type)
|
||||
self.cmd.set_slot_tag_type(slot_index, tag_type)
|
||||
print(f' - Set slot tag type success.')
|
||||
|
||||
|
||||
@@ -872,7 +868,7 @@ class HWSlotDataDefault(TagTypeRequiredUnit, SlotIndexRequireUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
tag_type = args.type
|
||||
slot_num = args.slot
|
||||
self.cmd_positive.set_slot_data_default(slot_num, tag_type)
|
||||
self.cmd.set_slot_data_default(slot_num, tag_type)
|
||||
print(f' - Set slot tag data init success.')
|
||||
|
||||
|
||||
@@ -887,7 +883,7 @@ class HWSlotEnableSet(SlotIndexRequireUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
slot_num = args.slot
|
||||
enable = args.enable
|
||||
self.cmd_positive.set_slot_enable(slot_num, enable)
|
||||
self.cmd.set_slot_enable(slot_num, enable)
|
||||
print(f' - Set slot {slot_num} {"enable" if enable else "disable"} success.')
|
||||
|
||||
|
||||
@@ -901,7 +897,7 @@ class LFEMSim(LFEMCardRequiredUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
id_hex = args.id
|
||||
id_bytes = bytearray.fromhex(id_hex)
|
||||
self.cmd_positive.set_em140x_sim_id(id_bytes)
|
||||
self.cmd.set_em140x_sim_id(id_bytes)
|
||||
print(f' - Set em410x tag id success.')
|
||||
|
||||
|
||||
@@ -920,7 +916,7 @@ class HWSlotNickSet(SlotIndexRequireUnit, SenseTypeRequireUnit):
|
||||
name: str = args.name
|
||||
if len(name.encode(encoding="gbk")) > 32:
|
||||
raise ValueError("Your tag nick name too long.")
|
||||
self.cmd_positive.set_slot_tag_nick_name(slot_num, sense_type, name)
|
||||
self.cmd.set_slot_tag_nick_name(slot_num, sense_type, name)
|
||||
print(f' - Set tag nick name for slot {slot_num} success.')
|
||||
|
||||
|
||||
@@ -935,7 +931,7 @@ class HWSlotNickGet(SlotIndexRequireUnit, SenseTypeRequireUnit):
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
slot_num = args.slot
|
||||
sense_type = args.sense_type
|
||||
res = self.cmd_positive.get_slot_tag_nick_name(slot_num, sense_type)
|
||||
res = self.cmd.get_slot_tag_nick_name(slot_num, sense_type)
|
||||
print(f' - Get tag nick name for slot {slot_num}: {res.data.decode(encoding="gbk")}')
|
||||
|
||||
|
||||
@@ -946,7 +942,7 @@ class HWSlotUpdate(DeviceRequiredUnit):
|
||||
|
||||
# hw slot update
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
self.cmd_positive.update_slot_data_config()
|
||||
self.cmd.update_slot_data_config()
|
||||
print(f' - Update config and data from device memory to flash success.')
|
||||
|
||||
|
||||
@@ -965,17 +961,17 @@ class HWSlotOpenAll(DeviceRequiredUnit):
|
||||
for slot in range(1,9):
|
||||
print(f' Slot{slot} setting...')
|
||||
# first to set tag type
|
||||
self.cmd_positive.set_slot_tag_type(slot, hf_type)
|
||||
self.cmd_positive.set_slot_tag_type(slot, lf_type)
|
||||
self.cmd.set_slot_tag_type(slot, hf_type)
|
||||
self.cmd.set_slot_tag_type(slot, lf_type)
|
||||
# to init default data
|
||||
self.cmd_positive.set_slot_data_default(slot, hf_type)
|
||||
self.cmd_positive.set_slot_data_default(slot, lf_type)
|
||||
self.cmd.set_slot_data_default(slot, hf_type)
|
||||
self.cmd.set_slot_data_default(slot, lf_type)
|
||||
# finally, we can enable this slot.
|
||||
self.cmd_positive.set_slot_enable(slot, True)
|
||||
self.cmd.set_slot_enable(slot, True)
|
||||
print(f' Open slot{slot} finish')
|
||||
|
||||
# update config and save to flash
|
||||
self.cmd_positive.update_slot_data_config()
|
||||
self.cmd.update_slot_data_config()
|
||||
print(f' - Open all slot and set data to default success.')
|
||||
|
||||
|
||||
@@ -987,7 +983,7 @@ class HWDFU(DeviceRequiredUnit):
|
||||
# hw dfu
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
print("Application restarting...")
|
||||
self.cmd_standard.enter_dfu_mode()
|
||||
self.cmd.enter_dfu_mode()
|
||||
# 理论上,上面的指令执行完成后,dfu模式会进入,然后USB会重启,
|
||||
# 我们判断是否成功进入USB,只需要判断USB是否变成DFU设备的VID和PID即可,
|
||||
# 同时我们记得确认设备的信息,一致时才是同一个设备。
|
||||
|
||||
@@ -2,6 +2,7 @@ import enum
|
||||
|
||||
import chameleon_com
|
||||
import chameleon_status
|
||||
from chameleon_utils import NegativeResponseError, expect_response
|
||||
|
||||
DATA_CMD_GET_APP_VERSION = 1000
|
||||
DATA_CMD_CHANGE_MODE = 1001
|
||||
@@ -77,7 +78,7 @@ class TagSpecificType(enum.IntEnum):
|
||||
return enum_list
|
||||
|
||||
|
||||
class BaseChameleonCMD:
|
||||
class ChameleonCMD:
|
||||
"""
|
||||
Chameleon cmd function
|
||||
"""
|
||||
@@ -126,6 +127,7 @@ class BaseChameleonCMD:
|
||||
"""
|
||||
return self.device.send_cmd_sync(DATA_CMD_CHANGE_MODE, 0x00, 0x0001 if reader_mode else 0x0000)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def scan_tag_14a(self):
|
||||
"""
|
||||
扫描场内的14a标签
|
||||
@@ -154,6 +156,7 @@ class BaseChameleonCMD:
|
||||
"""
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_DETECT, 0x00, None, timeout=20)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def detect_nt_distance(self, block_known, type_known, key_known):
|
||||
"""
|
||||
检测卡片的随机数距离
|
||||
@@ -165,6 +168,7 @@ class BaseChameleonCMD:
|
||||
data.extend(key_known)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_NT_DIST_DETECT, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def acquire_nested(self, block_known, type_known, key_known, block_target, type_target):
|
||||
"""
|
||||
采集Nested解密需要的关键NT参数
|
||||
@@ -178,6 +182,7 @@ class BaseChameleonCMD:
|
||||
data.append(block_target)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_NESTED_ACQUIRE, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max):
|
||||
"""
|
||||
采集Darkside解密需要的关键参数
|
||||
@@ -196,6 +201,10 @@ class BaseChameleonCMD:
|
||||
data.append(sync_max)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_ACQUIRE, 0x00, data, timeout=sync_max + 5)
|
||||
|
||||
@expect_response([
|
||||
chameleon_status.Device.HF_TAG_OK,
|
||||
chameleon_status.Device.MF_ERRAUTH,
|
||||
])
|
||||
def auth_mf1_key(self, block, type_value, key):
|
||||
"""
|
||||
验证mf1秘钥,只验证单个扇区的指定类型的秘钥
|
||||
@@ -210,6 +219,7 @@ class BaseChameleonCMD:
|
||||
data.extend(key)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_CHECK_ONE_KEY_BLOCK, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def read_mf1_block(self, block, type_value, key):
|
||||
"""
|
||||
读取mf1单块
|
||||
@@ -224,6 +234,7 @@ class BaseChameleonCMD:
|
||||
data.extend(key)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_READ_ONE_BLOCK, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def write_mf1_block(self, block, type_value, key, block_data):
|
||||
"""
|
||||
写入mf1单块
|
||||
@@ -240,6 +251,7 @@ class BaseChameleonCMD:
|
||||
data.extend(block_data)
|
||||
return self.device.send_cmd_sync(DATA_CMD_MF1_WRITE_ONE_BLOCK, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.LF_TAG_OK)
|
||||
def read_em_410x(self):
|
||||
"""
|
||||
读取EM410X的卡号
|
||||
@@ -247,6 +259,7 @@ class BaseChameleonCMD:
|
||||
"""
|
||||
return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00, None)
|
||||
|
||||
@expect_response(chameleon_status.Device.LF_TAG_OK)
|
||||
def write_em_410x_to_t55xx(self, id_bytes: bytearray):
|
||||
"""
|
||||
写入EM410X卡号到T55XX中
|
||||
@@ -267,6 +280,7 @@ class BaseChameleonCMD:
|
||||
data.extend(key)
|
||||
return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_slot_activated(self, slot_index):
|
||||
"""
|
||||
设置当前激活使用的卡槽
|
||||
@@ -279,6 +293,7 @@ class BaseChameleonCMD:
|
||||
data.append(slot_index - 1)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ACTIVATED, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_slot_tag_type(self, slot_index: int, tag_type: TagSpecificType):
|
||||
"""
|
||||
设置当前卡槽的模拟卡的标签类型
|
||||
@@ -294,6 +309,7 @@ class BaseChameleonCMD:
|
||||
data.append(tag_type)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_TYPE, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_slot_data_default(self, slot_index: int, tag_type: TagSpecificType):
|
||||
"""
|
||||
设置指定卡槽的模拟卡的数据为缺省数据
|
||||
@@ -309,6 +325,7 @@ class BaseChameleonCMD:
|
||||
data.append(tag_type)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_DATA_DEFAULT, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_slot_enable(self, slot_index: int, enable: bool):
|
||||
"""
|
||||
设置指定的卡槽是否使能
|
||||
@@ -323,6 +340,7 @@ class BaseChameleonCMD:
|
||||
data.append(0x01 if enable else 0x00)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_ENABLE, 0X00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||||
"""
|
||||
设置EM410x模拟的卡号
|
||||
@@ -333,6 +351,7 @@ class BaseChameleonCMD:
|
||||
raise ValueError("The id bytes length must equal 5")
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_EM410X_EMU_ID, 0x00, id_bytes)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_mf1_detection_enable(self, enable: bool):
|
||||
"""
|
||||
设置是否使能当前卡槽的侦测
|
||||
@@ -350,6 +369,7 @@ class BaseChameleonCMD:
|
||||
"""
|
||||
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00, None)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def get_mf1_detection_log(self, index: int):
|
||||
"""
|
||||
从指定的index位置开始获取侦测日志
|
||||
@@ -360,6 +380,7 @@ class BaseChameleonCMD:
|
||||
data.extend(index.to_bytes(4, "big", signed=False))
|
||||
return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_RESULT, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_mf1_block_data(self, block_start: int, block_data: bytearray):
|
||||
"""
|
||||
设置MF1的模拟卡的块数据
|
||||
@@ -372,6 +393,7 @@ class BaseChameleonCMD:
|
||||
data.extend(block_data)
|
||||
return self.device.send_cmd_sync(DATA_CMD_LOAD_MF1_BLOCK_DATA, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray):
|
||||
"""
|
||||
设置MF1的模拟卡的防冲撞资源信息
|
||||
@@ -386,6 +408,7 @@ class BaseChameleonCMD:
|
||||
data.extend(uid)
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_MF1_ANTI_COLLISION_RES, 0X00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str):
|
||||
"""
|
||||
设置MF1的模拟卡的防冲撞资源信息
|
||||
@@ -399,6 +422,7 @@ class BaseChameleonCMD:
|
||||
data.extend(name.encode(encoding="gbk"))
|
||||
return self.device.send_cmd_sync(DATA_CMD_SET_SLOT_TAG_NICK, 0x00, data)
|
||||
|
||||
@expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
def get_slot_tag_nick_name(self, slot: int, sense_type: int):
|
||||
"""
|
||||
设置MF1的模拟卡的防冲撞资源信息
|
||||
@@ -426,145 +450,11 @@ class BaseChameleonCMD:
|
||||
return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True)
|
||||
|
||||
|
||||
class NegativeResponseError(Exception):
|
||||
"""
|
||||
Not positive response
|
||||
"""
|
||||
|
||||
|
||||
class PositiveChameleonCMD(BaseChameleonCMD):
|
||||
"""
|
||||
子类重写基础指令交互实现类,针对每个指令进行单独封装结果处理
|
||||
如果结果是成功状态,那么就返回对应的数据,否则直接抛出异常
|
||||
"""
|
||||
|
||||
@staticmethod
|
||||
def check_status(status_ret, status_except):
|
||||
"""
|
||||
检查状态码,如果在接受为成功的
|
||||
:param status_ret: 执行指令之后返回的状态码
|
||||
:param status_except: 可以认为是执行成功的状态码
|
||||
:return:
|
||||
"""
|
||||
if isinstance(status_except, int):
|
||||
status_except = [status_except]
|
||||
if status_ret not in status_except:
|
||||
if status_ret in chameleon_status.Device and status_ret in chameleon_status.message:
|
||||
raise NegativeResponseError(chameleon_status.message[status_ret])
|
||||
else:
|
||||
raise NegativeResponseError(f"Not positive response and unknown status {status_ret}")
|
||||
return
|
||||
|
||||
def scan_tag_14a(self):
|
||||
ret = super(PositiveChameleonCMD, self).scan_tag_14a()
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def detect_nt_distance(self, block_known, type_known, key_known):
|
||||
ret = super(PositiveChameleonCMD, self).detect_nt_distance(block_known, type_known, key_known)
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def acquire_nested(self, block_known, type_known, key_known, block_target, type_target):
|
||||
ret = super(PositiveChameleonCMD, self).acquire_nested(
|
||||
block_known, type_known, key_known, block_target, type_target)
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max):
|
||||
ret = super(PositiveChameleonCMD, self).acquire_darkside(block_target, type_target, first_recover, sync_max)
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def auth_mf1_key(self, block, type_value, key):
|
||||
ret = super(PositiveChameleonCMD, self).auth_mf1_key(block, type_value, key)
|
||||
self.check_status(ret.status, [
|
||||
chameleon_status.Device.HF_TAG_OK,
|
||||
chameleon_status.Device.MF_ERRAUTH,
|
||||
])
|
||||
return ret
|
||||
|
||||
def read_mf1_block(self, block, type_value, key):
|
||||
ret = super(PositiveChameleonCMD, self).read_mf1_block(block, type_value, key)
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def write_mf1_block(self, block, type_value, key, block_data):
|
||||
ret = super(PositiveChameleonCMD, self).write_mf1_block(block, type_value, key, block_data)
|
||||
self.check_status(ret.status, chameleon_status.Device.HF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def read_em_410x(self):
|
||||
ret = super(PositiveChameleonCMD, self).read_em_410x()
|
||||
self.check_status(ret.status, chameleon_status.Device.LF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def write_em_410x_to_t55xx(self, id_bytes: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).write_em_410x_to_t55xx(id_bytes)
|
||||
self.check_status(ret.status, chameleon_status.Device.LF_TAG_OK)
|
||||
return ret
|
||||
|
||||
def set_slot_activated(self, slot_index):
|
||||
ret = super(PositiveChameleonCMD, self).set_slot_activated(slot_index)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_slot_tag_type(self, slot_index: int, tag_type: TagSpecificType):
|
||||
ret = super(PositiveChameleonCMD, self).set_slot_tag_type(slot_index, tag_type)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_slot_data_default(self, slot_index: int, tag_type: TagSpecificType):
|
||||
ret = super(PositiveChameleonCMD, self).set_slot_data_default(slot_index, tag_type)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_slot_enable(self, slot_index: int, enable: bool):
|
||||
ret = super(PositiveChameleonCMD, self).set_slot_enable(slot_index, enable)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_em140x_sim_id(self, id_bytes: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).set_em140x_sim_id(id_bytes)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_mf1_detection_enable(self, enable: bool):
|
||||
ret = super(PositiveChameleonCMD, self).set_mf1_detection_enable(enable)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def get_mf1_detection_log(self, index: int):
|
||||
ret = super(PositiveChameleonCMD, self).get_mf1_detection_log(index)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_mf1_block_data(self, block_start: int, data: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).set_mf1_block_data(block_start, data)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_mf1_anti_collision_res(self, sak: int, atqa: bytearray, uid: bytearray):
|
||||
ret = super(PositiveChameleonCMD, self).set_mf1_anti_collision_res(sak, atqa, uid)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def set_slot_tag_nick_name(self, slot: int, sense_type: int, name: str):
|
||||
ret = super(PositiveChameleonCMD, self).set_slot_tag_nick_name(slot, sense_type, name)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
def get_slot_tag_nick_name(self, slot: int, sense_type: int):
|
||||
ret = super(PositiveChameleonCMD, self).get_slot_tag_nick_name(slot, sense_type)
|
||||
self.check_status(ret.status, chameleon_status.Device.STATUS_DEVICE_SUCCESS)
|
||||
return ret
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
# connect to chameleon
|
||||
dev = chameleon_com.ChameleonCom()
|
||||
dev.open("com19")
|
||||
cml = BaseChameleonCMD(dev)
|
||||
cml = ChameleonCMD(dev)
|
||||
ver = cml.get_firmware_version()
|
||||
print(f"Firmware number of application: {ver}")
|
||||
id = cml.get_device_chip_id()
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
from functools import wraps
|
||||
from typing import Union
|
||||
|
||||
import chameleon_status
|
||||
|
||||
|
||||
class NegativeResponseError(Exception):
|
||||
"""
|
||||
Not positive response
|
||||
"""
|
||||
|
||||
def expect_response(accepted_responses):
|
||||
if isinstance(accepted_responses, int):
|
||||
accepted_responses = [accepted_responses]
|
||||
|
||||
def decorator(func):
|
||||
@wraps(func)
|
||||
def error_throwing_func(*args, **kwargs):
|
||||
ret = func(*args, **kwargs)
|
||||
|
||||
if ret.status not in accepted_responses:
|
||||
if ret.status in chameleon_status.Device and ret.status in chameleon_status.message:
|
||||
raise NegativeResponseError(chameleon_status.message[ret.status])
|
||||
else:
|
||||
raise NegativeResponseError(f"Not positive response and unknown status {ret.status}")
|
||||
|
||||
return ret
|
||||
|
||||
return error_throwing_func
|
||||
|
||||
return decorator
|
||||
Reference in New Issue
Block a user