From a596e98bf738f5327b66ab5d524b16361dce8b49 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 26 Aug 2023 02:07:47 +0200 Subject: [PATCH] python style --- software/script/chameleon_cli_main.py | 13 ++-- software/script/chameleon_cli_unit.py | 58 +++++++++------ software/script/chameleon_cmd.py | 102 +++++++++++++------------- software/script/chameleon_com.py | 6 +- software/script/chameleon_status.py | 54 ++++++++------ 5 files changed, 130 insertions(+), 103 deletions(-) diff --git a/software/script/chameleon_cli_main.py b/software/script/chameleon_cli_main.py index 7bb0178..0190de4 100755 --- a/software/script/chameleon_cli_main.py +++ b/software/script/chameleon_cli_main.py @@ -1,11 +1,8 @@ #!/usr/bin/env python3 import argparse -import platform import sys import traceback -import types import chameleon_com -import chameleon_cmd import colorama import chameleon_cli_unit import chameleon_utils @@ -29,7 +26,7 @@ LITE = r""" """ # create by http://patorjk.com/software/taag/#p=display&f=ANSI%20Shadow&t=Chameleon%20Ultra -BANNER = f""" +BANNER = """ ██████╗██╗ ██╗ █████╗ ██╗ ██╗███████╗██╗ ███████╗ █████╗ ██╗ ██╗ ██╔════╝██║ ██║██╔══██╗███╗ ███║██╔════╝██║ ██╔════╝██╔══██╗███╗ ██║ ██║ ███████║███████║████████║█████╗ ██║ █████╗ ██║ ██║████╗██║ @@ -46,12 +43,14 @@ class ChameleonCLI: def __init__(self): self.completer = chameleon_utils.CustomNestedCompleter.from_nested_dict(chameleon_cli_unit.root_commands) - self.session = prompt_toolkit.PromptSession(completer=self.completer, history=FileHistory(pathlib.Path.home() / ".chameleon_history")) + self.session = prompt_toolkit.PromptSession(completer=self.completer, + history=FileHistory(pathlib.Path.home() / ".chameleon_history")) # new a device communication instance(only communication) self.device_com = chameleon_com.ChameleonCom() - def get_cmd_node(self, node: chameleon_utils.CLITree, cmdline: list[str]) -> tuple[chameleon_utils.CLITree, list[str]]: + def get_cmd_node(self, node: chameleon_utils.CLITree, + cmdline: list[str]) -> tuple[chameleon_utils.CLITree, list[str]]: """ Recursively traverse the command line tree to get to the matching node @@ -92,7 +91,7 @@ class ChameleonCLI: start listen input. :return: """ - if sys.version_info < (3,9): + if sys.version_info < (3, 9): raise Exception("This script requires at least Python 3.9") self.print_banner() diff --git a/software/script/chameleon_cli_unit.py b/software/script/chameleon_cli_unit.py index d2a5f08..1ac759a 100644 --- a/software/script/chameleon_cli_unit.py +++ b/software/script/chameleon_cli_unit.py @@ -14,7 +14,8 @@ import chameleon_com import chameleon_cmd import chameleon_cstruct import chameleon_status -from chameleon_utils import * +from chameleon_utils import ArgumentParserNoExit, ArgsParserError, UnexpectedResponseError +from chameleon_utils import CLITree class BaseCLIUnit: @@ -176,6 +177,7 @@ root_commands: dict[str, CLITree] = { 'lf': lf, } + @hw.command('connect', 'Connect to chameleon by serial port') class HWConnect(BaseCLIUnit): def args_parser(self) -> ArgumentParserNoExit or None: @@ -189,18 +191,25 @@ class HWConnect(BaseCLIUnit): def on_exec(self, args: argparse.Namespace): try: if args.port is None: # Chameleon auto-detect if no port is supplied - platformname = uname().release - if 'Microsoft' in platformname: + platform_name = uname().release + if 'Microsoft' in platform_name: path = os.environ["PATH"].split(os.pathsep) path.append("/mnt/c/Windows/System32/WindowsPowerShell/v1.0/") for prefix in path: fn = os.path.join(prefix, "powershell.exe") if not os.path.isdir(fn) and os.access(fn, os.X_OK): - PSHEXE=fn + PSHEXE = fn break if PSHEXE: - #process = subprocess.Popen([PSHEXE,"Get-CimInstance -ClassName Win32_serialport | Where-Object {$_.PNPDeviceID -like '*VID_6868&PID_8686*'} | Select -expandproperty DeviceID"],stdout=subprocess.PIPE); - process = subprocess.Popen([PSHEXE,"Get-PnPDevice -Class Ports -PresentOnly | where {$_.DeviceID -like '*VID_6868&PID_8686*'} | Select-Object -First 1 FriendlyName | % FriendlyName | select-string COM\d+ |% { $_.matches.value }"],stdout=subprocess.PIPE); + # process = subprocess.Popen([PSHEXE,"Get-CimInstance -ClassName Win32_serialport |" + # " Where-Object {$_.PNPDeviceID -like '*VID_6868&PID_8686*'} |" + # " Select -expandproperty DeviceID"],stdout=subprocess.PIPE); + process = subprocess.Popen([PSHEXE, "Get-PnPDevice -Class Ports -PresentOnly |" + " where {$_.DeviceID -like '*VID_6868&PID_8686*'} |" + " Select-Object -First 1 FriendlyName |" + " % FriendlyName |" + " select-string COM\d+ |" + "% { $_.matches.value }"], stdout=subprocess.PIPE) res = process.communicate()[0] _comport = res.decode('utf-8').strip() if _comport: @@ -253,7 +262,7 @@ class HWChipIdGet(DeviceRequiredUnit): return None def on_exec(self, args: argparse.Namespace): - print(f' - Device chip ID: ' + self.cmd.get_device_chip_id()) + print(' - Device chip ID: ' + self.cmd.get_device_chip_id()) @hw_address.command('get', 'Get device address (used with Bluetooth)') @@ -262,7 +271,7 @@ class HWAddressGet(DeviceRequiredUnit): return None def on_exec(self, args: argparse.Namespace): - print(f' - Device address: ' + self.cmd.get_device_address()) + print(' - Device address: ' + self.cmd.get_device_address()) @hw.command('version', 'Get current device firmware version') @@ -639,7 +648,7 @@ class HFMFDetectionDecrypt(DeviceRequiredUnit): recv_count = int(len(tmp) / HFMFDetectionDecrypt.detection_log_size) index += recv_count buffer.extend(tmp) - print(f".", end="") + print(".", end="") print() print(f" - Download done ({len(buffer)}bytes), start parse and decrypt") @@ -801,7 +810,7 @@ class HFMFSettings(DeviceRequiredUnit): if args.write != -1: self.cmd.set_mf1_write_mode(args.write) print(f' - Set write mode to {chameleon_cmd.MifareClassicWriteMode(args.write)} success') - print(f' - Emulator settings updated') + print(' - Emulator settings updated') @hf_mf.command('sim', 'Simulate a Mifare Classic card') @@ -1028,7 +1037,7 @@ class HWSlotTagType(TagTypeRequiredUnit, SlotIndexRequireUnit): tag_type = args.type slot_index = args.slot self.cmd.set_slot_tag_type(slot_index, tag_type) - print(f' - Set slot tag type success.') + print(' - Set slot tag type success.') @hw_slot.command('delete', 'Delete sense type data for slot') @@ -1061,7 +1070,7 @@ class HWSlotDataDefault(TagTypeRequiredUnit, SlotIndexRequireUnit): tag_type = args.type slot_num = args.slot self.cmd.set_slot_data_default(slot_num, tag_type) - print(f' - Set slot tag data init success.') + print(' - Set slot tag data init success.') @hw_slot.command('enable', 'Set emulation tag slot enable or disable') @@ -1092,7 +1101,7 @@ class LFEMSimSet(LFEMCardRequiredUnit): id_hex = args.id id_bytes = bytearray.fromhex(id_hex) self.cmd.set_em410x_sim_id(id_bytes) - print(f' - Set em410x tag id success.') + print(' - Set em410x tag id success.') @lf_em_sim.command('get', 'Get simulated em410x card id') @@ -1104,7 +1113,7 @@ class LFEMSimGet(DeviceRequiredUnit): # lf em sim get def on_exec(self, args: argparse.Namespace): response = self.cmd.get_em410x_sim_id() - print(f' - Get em410x tag id success.') + print(' - Get em410x tag id success.') print(f'ID: {response.data.hex()}') @@ -1153,7 +1162,7 @@ class HWSlotUpdate(DeviceRequiredUnit): # hw slot update def on_exec(self, args: argparse.Namespace): self.cmd.update_slot_data_config() - print(f' - Update config and data from device memory to flash success.') + print(' - Update config and data from device memory to flash success.') @hw_slot.command('openall', 'Open all slot and set to default data') @@ -1182,7 +1191,7 @@ class HWSlotOpenAll(DeviceRequiredUnit): # update config and save to flash self.cmd.update_slot_data_config() - print(f' - Succeeded opening all slots and setting data to default.') + print(' - Succeeded opening all slots and setting data to default.') @hw.command('dfu', 'Restart application to bootloader mode(Not yet implement dfu).') @@ -1195,8 +1204,10 @@ class HWDFU(DeviceRequiredUnit): print("Application restarting...") self.cmd.enter_dfu_mode() # In theory, after the above command is executed, the dfu mode will enter, and then the USB will restart, - # To judge whether to enter the USB successfully, we only need to judge whether the USB becomes the VID and PID of the DFU device. - # At the same time, we remember to confirm the information of the device, it is the same device when it is consistent. + # To judge whether to enter the USB successfully, we only need to judge whether the USB becomes the VID and PID + # of the DFU device. + # At the same time, we remember to confirm the information of the device, + # it is the same device when it is consistent. print(" - Enter success @.@~") # let time for comm thread to send dfu cmd and close port time.sleep(0.1) @@ -1295,7 +1306,7 @@ class HWBatteryInfo(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): resp = self.cmd.battery_information() - voltage = int.from_bytes(resp.data[:2], 'big') + voltage = int.from_bytes(resp.data[:2], 'big') percentage = resp.data[2] print(" - Battery information:") print(f" voltage -> {voltage}mV") @@ -1322,9 +1333,11 @@ class HWButtonSettingsGet(DeviceRequiredUnit): resp_long = self.cmd.get_long_button_press_fun(button) button_fn = chameleon_cmd.ButtonPressFunction.from_int(resp.data[0]) button_long_fn = chameleon_cmd.ButtonPressFunction.from_int(resp_long.data[0]) - print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}short{colorama.Style.RESET_ALL}: {button_fn}") + print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}short{colorama.Style.RESET_ALL}:" + " {button_fn}") print(f" usage: {button_fn.usage()}") - print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}long {colorama.Style.RESET_ALL}: {button_long_fn}") + print(f" - {colorama.Fore.GREEN}{button} {colorama.Fore.YELLOW}long {colorama.Style.RESET_ALL}:" + " {button_long_fn}") print(f" usage: {button_long_fn.usage()}") print("") print(" - Successfully get button function from settings") @@ -1351,8 +1364,7 @@ class HWButtonSettingsSet(DeviceRequiredUnit): def on_exec(self, args: argparse.Namespace): button = chameleon_cmd.ButtonType.from_str(args.b) function = chameleon_cmd.ButtonPressFunction.from_int(args.f) - long = args.long == True - if long: + if args.long: self.cmd.set_long_button_press_fun(button, function) else: self.cmd.set_button_press_fun(button, function) diff --git a/software/script/chameleon_cmd.py b/software/script/chameleon_cmd.py index 5cb76fc..27b3681 100644 --- a/software/script/chameleon_cmd.py +++ b/software/script/chameleon_cmd.py @@ -3,7 +3,7 @@ import struct import chameleon_com import chameleon_status -from chameleon_utils import UnexpectedResponseError, expect_response +from chameleon_utils import expect_response DATA_CMD_GET_APP_VERSION = 1000 DATA_CMD_CHANGE_MODE = 1001 @@ -263,7 +263,8 @@ class ButtonPressFunction(enum.IntEnum): elif self == ButtonPressFunction.SettingsButtonCycleSlotDec: return "Card slot number sequence decreases after pressing" elif self == ButtonPressFunction.SettingsButtonCloneIcUid: - return "Read the UID card number immediately after pressing, continue searching, and simulate immediately after reading the card" + return "Read the UID card number immediately after pressing, continue searching," + \ + "and simulate immediately after reading the card" return "Unknown" @@ -322,28 +323,28 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def scan_tag_14a(self): """ - ( ) 14a tags in the scanning field + 14a tags in the scanning field :return: """ return self.device.send_cmd_sync(DATA_CMD_SCAN_14A_TAG, 0x00) def detect_mf1_support(self): """ - ( ) Detect whether it is mi (ar) classic label + Detect whether it is mifare classic label :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_SUPPORT_DETECT, 0x00) def detect_mf1_nt_level(self): """ - ( ) detect mi (ar) Class of classic nt vulnerabilities + detect mifare Class of classic nt vulnerabilities :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_NT_LEVEL_DETECT, 0x00) def detect_darkside_support(self): """ - ( ) Check if the card is vulnerable to mifare cla (si) darkside attack + Check if the card is vulnerable to mifare classic darkside attack :return: """ return self.device.send_cmd_sync(DATA_CMD_MF1_DARKSIDE_DETECT, 0x00, None, timeout=20) @@ -351,7 +352,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def detect_nt_distance(self, block_known, type_known, key_known): """ - ( ) Detect the random number distance of the card + Detect the random number distance of the card :return: """ data = bytearray() @@ -363,7 +364,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def acquire_nested(self, block_known, type_known, key_known, block_target, type_target): """ - ( ) Collect the key NT parameters needed for Nested decryption + Collect the key NT parameters needed for Nested decryption :return: """ data = bytearray() @@ -377,7 +378,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def acquire_darkside(self, block_target, type_target, first_recover: int or bool, sync_max): """ - ( ) Collect the key parameters needed for Darkside decryption + Collect the key parameters needed for Darkside decryption :param block_target: :param type_target: :param first_recover: @@ -399,7 +400,7 @@ class ChameleonCMD: ]) def auth_mf1_key(self, block, type_value, key): """ - ( ) Verify the mf1 key, only verify the specified type of key for a single sector + Verify the mf1 key, only verify the specified type of key for a single sector :param block: :param type_value: :param key: @@ -414,7 +415,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def read_mf1_block(self, block, type_value, key): """ - ( ) read mf1 monoblock + read mf1 monoblock :param block: :param type_value: :param key: @@ -429,7 +430,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.HF_TAG_OK) def write_mf1_block(self, block, type_value, key, block_data): """ - ( ) Write mf1 single block + Write mf1 single block :param block: :param type_value: :param key: @@ -446,7 +447,7 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.LF_TAG_OK) def read_em_410x(self): """ - ( ) Read the card number of EM410X + Read the card number of EM410X :return: """ return self.device.send_cmd_sync(DATA_CMD_SCAN_EM410X_TAG, 0x00) @@ -454,8 +455,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.LF_TAG_OK) def write_em_410x_to_t55xx(self, id_bytes: bytearray): """ - ( ) Write EM410X card number into T55XX - :param id_by (es) ID card number + Write EM410X card number into T55XX + :param id_bytes: ID card number :return: """ new_key = [0x20, 0x20, 0x66, 0x66] @@ -498,10 +499,11 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_tag_type(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ - ( ) Set the label type of the simulated card of the current card slot - ( ) Note: This operation will not change the data in the flash, and the change of the data in the flash will only be updated at the next save - :param slot_in (ex) Card slot number - :param tag_t (pe) label type + Set the label type of the simulated card of the current card slot + Note: This operation will not change the data in the flash, + and the change of the data in the flash will only be updated at the next save + :param slot_index: Card slot number + :param tag_type: label type :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -526,10 +528,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_data_default(self, slot_index: SlotNumber, tag_type: TagSpecificType): """ - ( ) Set the data of the simulated card in the specified card slot as the default data - ( ) Note: This API will set the data in the flash together - :param slot_in (ex) Card slot number - :param tag_t (pe) The default label type to set + Set the data of the simulated card in the specified card slot as the default data + Note: This API will set the data in the flash together + :param slot_index: Card slot number + :param tag_type: The default label type to set :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -541,9 +543,9 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_enable(self, slot_index: SlotNumber, enable: bool): """ - ( ) Set whether the specified card slot is enabled - :param slot_in (ex) Card slot number - :param ena (le) Whether to enable + Set whether the specified card slot is enabled + :param slot_index: Card slot number + :param enable: Whether to enable :return: """ # SlotNumber() will raise error for us if slot_index not in slot range @@ -555,8 +557,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_em410x_sim_id(self, id_bytes: bytearray): """ - ( ) Set the card number simulated by EM410x - :param id_by (es) byte of the card number + Set the card number simulated by EM410x + :param id_bytes: byte of the card number :return: """ if len(id_bytes) != 5: @@ -572,8 +574,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_detection_enable(self, enable: bool): """ - ( ) Set whether to enable the detection of the current card slot - :param ena (le) Whether to enable + Set whether to enable the detection of the current card slot + :param enable: Whether to enable :return: """ data = bytearray() @@ -582,7 +584,7 @@ class ChameleonCMD: def get_mf1_detection_count(self): """ - ( ) Get the statistics of the current detection records + Get the statistics of the current detection records :return: """ return self.device.send_cmd_sync(DATA_CMD_GET_MF1_DETECTION_COUNT, 0x00) @@ -590,8 +592,8 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def get_mf1_detection_log(self, index: int): """ - ( ) Get detection logs from the specified index position - :param in (ex) start index + Get detection logs from the specified index position + :param index: start index :return: """ data = bytearray() @@ -601,9 +603,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_block_data(self, block_start: int, block_data: bytearray): """ - ( ) Set the block data of the analog card of MF1 - :param block_st (rt) Start setting the location of block data, including this location - :param block_d (ta) The byte buffer of the block data to be set can contain multiple block data, automatically from block_s (ar) increment + Set the block data of the analog card of MF1 + :param block_start: Start setting the location of block data, including this location + :param block_data: The byte buffer of the block data to be set + can contain multiple block data, automatically from block_start increment :return: """ data = bytearray() @@ -621,10 +624,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_mf1_anti_collision_res(self, sak: bytearray, atqa: bytearray, uid: bytearray): """ - ( ) Set the anti-collision resource information of the MF1 analog card - :param (ak) sak bytes - :param a (qa) atqa array - :param (id) card number array + Set the anti-collision resource information of the MF1 analog card + :param sak: sak bytes + :param atqa: atqa array + :param uid: card number array :return: """ data = bytearray() @@ -636,10 +639,10 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def set_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType, name: bytes): """ - ( ) Set the anti-collision resource information of the MF1 analog card - :param s (ot) Card slot number - :param sense_t (pe) field type - :param n (me) Card slot nickname + Set the anti-collision resource information of the MF1 analog card + :param slot: Card slot number + :param sense_type: field type + :param name: Card slot nickname :return: """ # SlotNumber() will raise error for us if slot not in slot range @@ -651,9 +654,9 @@ class ChameleonCMD: @expect_response(chameleon_status.Device.STATUS_DEVICE_SUCCESS) def get_slot_tag_nick_name(self, slot: SlotNumber, sense_type: TagSenseType): """ - ( ) Set the anti-collision resource information of the MF1 analog card - :param s (ot) Card slot number - :param sense_t (pe) field type + Set the anti-collision resource information of the MF1 analog card + :param slot: Card slot number + :param sense_type: field type :return: """ # SlotNumber() will raise error for us if slot not in slot range @@ -699,14 +702,14 @@ class ChameleonCMD: def update_slot_data_config(self): """ - ( ) Update the configuration and data of the card slot to flash. + Update the configuration and data of the card slot to flash. :return: """ return self.device.send_cmd_sync(DATA_CMD_SLOT_DATA_CONFIG_SAVE, 0x00) def enter_dfu_mode(self): """ - ( ) Reboot into DFU mode (bootloader) + Reboot into DFU mode (bootloader) :return: """ return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True) @@ -792,6 +795,7 @@ class ChameleonCMD: bytearray([button, function]) ) + if __name__ == '__main__': # connect to chameleon dev = chameleon_com.ChameleonCom() diff --git a/software/script/chameleon_com.py b/software/script/chameleon_com.py index 92b5977..3bf76d7 100644 --- a/software/script/chameleon_com.py +++ b/software/script/chameleon_com.py @@ -78,7 +78,7 @@ class ChameleonCom: raise OpenFailException(error) try: self.serial_instance.dtr = 1 # must make dtr enable - except: + except Exception: # not all serial support dtr, e.g. virtual serial over BLE pass self.serial_instance.timeout = 0 # noblock @@ -122,7 +122,7 @@ class ChameleonCom: self.event_closing.set() try: self.serial_instance.close() - except: + except Exception: pass finally: self.serial_instance = None @@ -163,7 +163,7 @@ class ChameleonCom: if data_buffer[data_position] != self.lrc_calc(data_buffer[0:1]): data_position = 0 data_buffer.clear() - print(f"Data frame sof lrc error.") + print("Data frame sof lrc error.") continue elif data_position == 8: # frame head lrc if data_buffer[data_position] != self.lrc_calc(data_buffer[0:8]): diff --git a/software/script/chameleon_status.py b/software/script/chameleon_status.py index 3ae4f0f..afa326e 100644 --- a/software/script/chameleon_status.py +++ b/software/script/chameleon_status.py @@ -14,32 +14,44 @@ class MetaDevice(type): class Device(metaclass=MetaDevice): - HF_TAG_OK = 0x00 # IC card operation is successful - HF_TAG_NO = 0x01 # IC card not found - HF_ERRSTAT = 0x02 # Abnormal IC card communication - HF_ERRCRC = 0x03 # IC card communication verification abnormal + HF_TAG_OK = 0x00 # IC card operation is successful + HF_TAG_NO = 0x01 # IC card not found + HF_ERRSTAT = 0x02 # Abnormal IC card communication + HF_ERRCRC = 0x03 # IC card communication verification abnormal HF_COLLISION = 0x04 # IC card conflict - HF_ERRBCC = 0x05 # IC card BCC error - MF_ERRAUTH = 0x06 # MF card verification failed + HF_ERRBCC = 0x05 # IC card BCC error + MF_ERRAUTH = 0x06 # MF card verification failed HF_ERRPARITY = 0x07 # IC card parity error - DARKSIDE_CANT_FIXED_NT = 0x20 # Darkside, the random number cannot be fixed, this situation may appear on the UID card - DARKSIDE_LUCK_AUTH_OK = 0x21 # Darkside, the direct verification is successful, maybe the key is empty - DARKSIDE_NACK_NO_SEND = 0x22 # Darkside, the card doesn't respond to nack, probably a card that fixes the nack logic bug - DARKSIDE_TAG_CHANGED = 0x23 # Darkside, there is a card switching during the running of darkside, maybe there is a signal problem, or the two cards really switched quickly - NESTED_TAG_IS_STATIC = 0x24 # Nested, it is detected that the random number of the card response is fixed - NESTED_TAG_IS_HARD = 0x25 # Nested, detected nonce for card response is unpredictable + # Darkside, the random number cannot be fixed, this situation may appear on the UID card + DARKSIDE_CANT_FIXED_NT = 0x20 + # Darkside, the direct verification is successful, maybe the key is empty + DARKSIDE_LUCK_AUTH_OK = 0x21 + # Darkside, the card doesn't respond to nack, probably a card that fixes the nack logic bug + DARKSIDE_NACK_NO_SEND = 0x22 + # Darkside, there is a card switching during the running of darkside, + # maybe there is a signal problem, or the two cards really switched quickly + DARKSIDE_TAG_CHANGED = 0x23 + # Nested, it is detected that the random number of the card response is fixed + NESTED_TAG_IS_STATIC = 0x24 + # Nested, detected nonce for card response is unpredictable + NESTED_TAG_IS_HARD = 0x25 - LF_TAG_OK = 0x40 # Some operations with low frequency cards succeeded! - EM410X_TAG_NO_FOUND = 0x41 # Unable to search for a valid EM410X label + # Some operations with low frequency cards succeeded! + LF_TAG_OK = 0x40 + # Unable to search for a valid EM410X label + EM410X_TAG_NO_FOUND = 0x41 - STATUS_PAR_ERR = 0x60 # The parameters passed by the BLE instruction are wrong, or the parameters passed by calling some functions are wrong - STATUS_DEVICE_MODE_ERROR = 0x66 # The mode of the current device is wrong, and the corresponding API cannot be called - STATUS_INVALID_CMD = 0x67 # invalid command - STATUS_DEVICE_SUCCESS = 0x68 # Device-related operations performed successfully - STATUS_NOT_IMPLEMENTED = 0x69 # Some unimplemented operations were called, an error missed by the developer - STATUS_FLASH_WRITE_FAIL = 0x70 # flash write failed - STATUS_FLASH_READ_FAIL = 0x71 # flash read failed + # The parameters passed by the BLE instruction are wrong, or the parameters passed + # by calling some functions are wrong + STATUS_PAR_ERR = 0x60 + # The mode of the current device is wrong, and the corresponding API cannot be called + STATUS_DEVICE_MODE_ERROR = 0x66 + STATUS_INVALID_CMD = 0x67 + STATUS_DEVICE_SUCCESS = 0x68 + STATUS_NOT_IMPLEMENTED = 0x69 + STATUS_FLASH_WRITE_FAIL = 0x70 + STATUS_FLASH_READ_FAIL = 0x71 message = {