diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index 4de0681..f276772 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -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即可, # 同时我们记得确认设备的信息,一致时才是同一个设备。 diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 0f793d5..474cd34 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -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() diff --git a/software/script/chameleon_utils.py b/software/script/chameleon_utils.py new file mode 100644 index 0000000..219f205 --- /dev/null +++ b/software/script/chameleon_utils.py @@ -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