Merge branch 'main' into bugfix/cli-offset

This commit is contained in:
Philippe Teuwen
2023-08-18 16:02:55 +02:00
committed by GitHub
24 changed files with 561 additions and 81 deletions
+16 -4
View File
@@ -73,6 +73,7 @@ class ChameleonCLI:
'help': "Device mode get/set"
},
'slot': {
'info': new_uint(chameleon_cli_unit.HWSlotInfo, "Get information about slots"),
'change': new_uint(chameleon_cli_unit.HWSlotSet, "Set emulation tag slot activated."),
'type': new_uint(chameleon_cli_unit.HWSlotTagType, "Set emulation tag type"),
'init': new_uint(chameleon_cli_unit.HWSlotDataDefault, "Set emulation tag data to default"),
@@ -86,7 +87,18 @@ class ChameleonCLI:
'openall': new_uint(chameleon_cli_unit.HWSlotOpenAll, "Open all slot and set to default data"),
'help': "Emulation tag slot.",
},
'version': new_uint(chameleon_cli_unit.HWVersion, "Get current device firmware version"),
'dfu': new_uint(chameleon_cli_unit.HWDFU, "Restart application to bootloader mode(Not yet implement dfu)."),
'settings': {
'animation': {
'get': new_uint(chameleon_cli_unit.HWSettingsAnimationGet, "Get current animation mode value"),
'set': new_uint(chameleon_cli_unit.HWSettingsAnimationSet, "Change chameleon animation mode"),
'help': 'Manage wake-up and sleep animation mode'
},
'store': new_uint(chameleon_cli_unit.HWSettingsStore, "Store current settings to flash"),
'reset': new_uint(chameleon_cli_unit.HWSettingsReset, "Reset settings to default values"),
'help': "Chameleon settings management"
},
'help': "hardware controller",
},
'hf': {
@@ -143,14 +155,15 @@ class ChameleonCLI:
cmds = cmd_str.split(" ")
cmd_maps: dict or types.FunctionType = self.cmd_maps
cmd_end = ""
cmd_end_position = 0
for cmd in cmds:
if cmd in cmd_maps: # CMD found in map, we can continue find next
cmd_maps = cmd_maps[cmd]
cmd_end = cmd
cmd_end_position += len(cmd) + 1
else: # CMD not found
break
cmd_end_position = cmd_str.index(cmd_end) + len(cmd_end) + 1
return cmd_maps, (cmd_str[:cmd_end_position], cmd_str[cmd_end_position:])
return cmd_maps, (cmd_str[:cmd_end_position - 1], cmd_str[cmd_end_position:])
def startCLI(self):
"""
@@ -162,9 +175,8 @@ class ChameleonCLI:
while True:
# wait user input
status = f"{colorama.Fore.GREEN}USB" if self.device_com.isOpen() else f"{colorama.Fore.RED}Offline"
print(f"[{status}{colorama.Style.RESET_ALL}] chameleon --> ", end="")
try:
cmd_str = input().strip()
cmd_str = input(f"[{status}{colorama.Style.RESET_ALL}] chameleon --> ").strip()
except EOFError:
print("")
closing = True
+72
View File
@@ -253,6 +253,16 @@ class HWAddressGet(DeviceRequiredUnit):
def on_exec(self, args: argparse.Namespace):
print(f' - Device address: ' + self.cmd_positive.get_device_address())
class HWVersion(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
return None
def on_exec(self, args: argparse.Namespace):
fw_version_int = self.cmd_positive.get_firmware_version()
fw_version = f'v{fw_version_int // 256}.{fw_version_int % 256}'
git_version = self.cmd_positive.get_git_version()
print(f' - Version: {fw_version} ({git_version})')
class HF14AScan(ReaderRequiredUint):
def args_parser(self) -> ArgumentParserNoExit or None:
@@ -813,6 +823,18 @@ class SenseTypeRequireUint(DeviceRequiredUnit):
help=help_str, metavar="number", choices=slot_choices)
return parser
class HWSlotInfo(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
return
# hw slot info
def on_exec(self, args: argparse.Namespace):
data = self.cmd_positive.get_slot_info().data
selected = self.cmd_positive.get_active_slot().data[0]
for slot in range(8):
print(f' - Slot {slot + 1} data{" (active)" if slot == selected else ""}:')
print(f' HF: {chameleon_cmd.TagSpecificType(data[slot * 2])}')
print(f' LF: {chameleon_cmd.TagSpecificType(data[slot * 2 + 1])}')
class HWSlotSet(SlotIndexRequireUint):
@@ -1000,3 +1022,53 @@ class HWDFU(DeviceRequiredUnit):
print(" - Enter success @.@~")
# let time for comm thread to send dfu cmd and close port
time.sleep(0.1)
class HWSettingsAnimationGet(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
return None
def on_exec(self, args: argparse.Namespace):
resp: chameleon_com.Response = self.cmd_standard.get_settings_animation()
if resp.data[0] == 0:
print("Full animation")
elif resp.data[0] == 1:
print("Minimal animation")
elif resp.data[0] == 2:
print("No animation")
else:
print("Unknown setting value, something failed.")
class HWSettingsAnimationSet(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
parser = ArgumentParserNoExit()
parser.add_argument('-m', '--mode', type=int, required=True, help="0 is full (default), 1 is minimal (only single pass on button wakeup), 2 is none", choices=[0, 1, 2])
return parser
def on_exec(self, args: argparse.Namespace):
mode = args.mode
self.cmd_standard.set_settings_animation(mode)
print("Animation mode change success. Do not forget to store your settings in flash!")
class HWSettingsStore(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
return None
def on_exec(self, args: argparse.Namespace):
print("Storing settings...")
resp: chameleon_com.Response = self.cmd_standard.store_settings()
if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS:
print(" - Store success @.@~")
else:
print(" - Store failed")
class HWSettingsReset(DeviceRequiredUnit):
def args_parser(self) -> ArgumentParserNoExit or None:
return None
def on_exec(self, args: argparse.Namespace):
print("Initializing settings...")
resp: chameleon_com.Response = self.cmd_standard.reset_settings()
if resp.status == chameleon_status.Device.STATUS_DEVICE_SUCCESS:
print(" - Reset success @.@~")
else:
print(" - Reset failed")
+72 -1
View File
@@ -20,6 +20,16 @@ DATA_CMD_ENTER_BOOTLOADER = 1010
DATA_CMD_GET_DEVICE_CHIP_ID = 1011
DATA_CMD_GET_DEVICE_ADDRESS = 1012
DATA_CMD_SAVE_SETTINGS = 1013
DATA_CMD_RESET_SETTINGS = 1014
DATA_CMD_SET_ANIMATION_MODE = 1015
DATA_CMD_GET_ANIMATION_MODE = 1016
DATA_CMD_GET_GIT_VERSION = 1017
DATA_CMD_GET_ACTIVE_SLOT = 1018
DATA_CMD_GET_SLOT_INFO = 1019
DATA_CMD_SCAN_14A_TAG = 2000
DATA_CMD_MF1_SUPPORT_DETECT = 2001
DATA_CMD_MF1_NT_LEVEL_DETECT = 2002
@@ -127,6 +137,26 @@ class TagSpecificType(enum.IntEnum):
enum_list.remove(TagSpecificType.TAG_TYPE_UNKNOWN)
return enum_list
def __str__(self):
if self.value == TagSpecificType.TAG_TYPE_EM410X:
return "EM410X"
elif self.value == TagSpecificType.TAG_TYPE_MIFARE_Mini:
return "Mifare Mini"
elif self.value == TagSpecificType.TAG_TYPE_MIFARE_1024:
return "Mifare Classic 1k"
elif self.value == TagSpecificType.TAG_TYPE_MIFARE_2048:
return "Mifare Classic 2k"
elif self.value == TagSpecificType.TAG_TYPE_MIFARE_4096:
return "Mifare Classic 4k"
elif self.value == TagSpecificType.TAG_TYPE_NTAG_213:
return "NTAG 213"
elif self.value == TagSpecificType.TAG_TYPE_NTAG_215:
return "NTAG 215"
elif self.value == TagSpecificType.TAG_TYPE_NTAG_216:
return "NTAG 216"
return "Unknown"
class BaseChameleonCMD:
"""
@@ -159,7 +189,10 @@ class BaseChameleonCMD:
"""
resp = self.device.send_cmd_sync(DATA_CMD_GET_DEVICE_ADDRESS, 0x00, None)
return resp.data[::-1].hex()
def get_git_version(self) -> str:
resp = self.device.send_cmd_sync(DATA_CMD_GET_GIT_VERSION, 0x00, None)
return resp.data.decode('utf-8')
def is_reader_device_mode(self) -> bool:
"""
@@ -318,6 +351,20 @@ class BaseChameleonCMD:
data.extend(key)
return self.device.send_cmd_sync(DATA_CMD_WRITE_EM410X_TO_T5577, 0x00, data)
def get_slot_info(self):
"""
Get slots info
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_SLOT_INFO, 0x00, None)
def get_active_slot(self):
"""
Get selected slot
:return:
"""
return self.device.send_cmd_sync(DATA_CMD_GET_ACTIVE_SLOT, 0x00, None)
def set_slot_activated(self, slot_index: SlotNumber):
"""
设置当前激活使用的卡槽
@@ -475,6 +522,30 @@ class BaseChameleonCMD:
:return:
"""
return self.device.send_cmd_auto(DATA_CMD_ENTER_BOOTLOADER, 0x00, close=True)
def get_settings_animation(self):
"""
Get animation mode value
"""
return self.device.send_cmd_sync(DATA_CMD_GET_ANIMATION_MODE, 0x00, None)
def set_settings_animation(self, value: int):
"""
Set animation mode value
"""
return self.device.send_cmd_sync(DATA_CMD_SET_ANIMATION_MODE, 0x00, bytearray([value]))
def reset_settings(self):
"""
Reset settings stored in flash memory
"""
return self.device.send_cmd_sync(DATA_CMD_RESET_SETTINGS, 0x00)
def store_settings(self):
"""
Store settings to flash memory
"""
return self.device.send_cmd_sync(DATA_CMD_SAVE_SETTINGS, 0x00)
class NegativeResponseError(Exception):
+4
View File
@@ -41,6 +41,8 @@ class Device(metaclass=MetaDevice):
STATUS_INVALID_CMD = 0x67 # 无效的指令
STATUS_DEVICE_SUCCESS = 0x68 # 设备相关操作成功执行
STATUS_NOT_IMPLEMENTED = 0x69 # 调用了某些未实现的操作,属于开发者遗漏的错误
STATUS_FLASH_WRITE_FAIL = 0x70 # flash写入失败
STATUS_FLASH_READ_FAIL = 0x71 # flash读取失败
message = {
@@ -68,4 +70,6 @@ message = {
Device.STATUS_INVALID_CMD : "API request fail, cmd invalid",
Device.STATUS_DEVICE_SUCCESS : "Device operation succeeded",
Device.STATUS_NOT_IMPLEMENTED : "Some api not implemented",
Device.STATUS_FLASH_WRITE_FAIL : "Flash write failed",
Device.STATUS_FLASH_READ_FAIL : "Flash read failed"
}