mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
Merge branch 'main' into bugfix/cli-offset
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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):
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user