mirror of
https://github.com/RfidResearchGroup/ChameleonUltra.git
synced 2026-05-12 11:22:59 -07:00
hw 14a raw: closer to pm3 syntax, removed bit_frame,...
Now data length is always in bits Option -o => -a and only needed to turn field on without select or data Reorganize pcd_14a_reader_raw_cmd Some more checks
This commit is contained in:
@@ -1589,26 +1589,34 @@ class HF14ARaw(ReaderRequiredUnit):
|
||||
|
||||
def args_parser(self) -> ArgumentParserNoExit or None:
|
||||
parser = ArgumentParserNoExit()
|
||||
parser.add_argument('-r', '--response', help="do not read response", action='store_true', default=False,)
|
||||
parser.add_argument('-c', '--crc', help="calculate and append CRC", action='store_true', default=False,)
|
||||
parser.add_argument('-cc', '--crc-clear', help="Verify and clear CRC of received data", action='store_true', default=False,)
|
||||
parser.add_argument('-k', '--keep-rf', help="keep signal field ON after receive", action='store_true', default=False,)
|
||||
parser.add_argument('-o', '--open-rf', help="active signal field ON", action='store_true', default=False,)
|
||||
parser.add_argument('-s', '--select-tag', help="Select the tag before executing the command", action='store_true', default=False,)
|
||||
parser.add_argument('-b', '--bits', type=int, help="number of bits to send. Useful for send partial byte")
|
||||
parser.add_argument('-t', '--timeout', type=int, help="timeout in ms", default=100)
|
||||
parser.add_argument('-a', '--activate-rf', help="Active signal field ON without select", action='store_true', default=False,)
|
||||
parser.add_argument('-s', '--select-tag', help="Active signal field ON with select", action='store_true', default=False,)
|
||||
# TODO: parser.add_argument('-3', '--type3-select-tag', help="Active signal field ON with ISO14443-3 select (no RATS)", action='store_true', default=False,)
|
||||
parser.add_argument('-d', '--data', type=str, help="Data to be sent")
|
||||
parser.add_argument('-b', '--bits', type=int, help="Number of bits to send. Useful for send partial byte")
|
||||
parser.add_argument('-c', '--crc', help="Calculate and append CRC", action='store_true', default=False,)
|
||||
parser.add_argument('-r', '--response', help="Do not read response", action='store_true', default=False,)
|
||||
parser.add_argument('-cc', '--crc-clear', help="Verify and clear CRC of received data", action='store_true', default=False,)
|
||||
parser.add_argument('-k', '--keep-rf', help="Keep signal field ON after receive", action='store_true', default=False,)
|
||||
parser.add_argument('-t', '--timeout', type=int, help="Timeout in ms", default=100)
|
||||
# TODO: need support for carriage returns in parser, why are they mangled?
|
||||
# parser.description = 'Examples:\n' \
|
||||
# ' hf 14a raw -b 7 -d 40 -k\n' \
|
||||
# ' hf 14a raw -d 43 -k\n' \
|
||||
# ' hf 14a raw -d 3000 -c\n' \
|
||||
# ' hf 14a raw -sc -d 6000\n'
|
||||
return parser
|
||||
|
||||
|
||||
def on_exec(self, args: argparse.Namespace):
|
||||
options = {
|
||||
'open_rf_field': self.bool_to_bit(args.open_rf),
|
||||
'wait_response': self.bool_to_bit(args.response == False),
|
||||
'activate_rf_field': self.bool_to_bit(args.activate_rf),
|
||||
'wait_response': self.bool_to_bit(not args.response),
|
||||
'append_crc': self.bool_to_bit(args.crc),
|
||||
'bit_frame': self.bool_to_bit(args.bits is not None),
|
||||
'auto_select': self.bool_to_bit(args.select_tag),
|
||||
'keep_rf_field': self.bool_to_bit(args.keep_rf),
|
||||
'check_response_crc': self.bool_to_bit(args.crc_clear),
|
||||
#'auto_type3_select': self.bool_to_bit(args.type3-select-tag),
|
||||
}
|
||||
data: str = args.data
|
||||
if data is not None:
|
||||
@@ -1624,6 +1632,10 @@ class HF14ARaw(ReaderRequiredUnit):
|
||||
return
|
||||
else:
|
||||
data_bytes = []
|
||||
if args.bits is not None and args.crc:
|
||||
print(f" [!] {CR}--bits and --crc are mutually exclusive{C0}")
|
||||
return
|
||||
|
||||
# Exec 14a raw cmd.
|
||||
resp = self.cmd.hf14a_raw(options, args.timeout, data_bytes, args.bits)
|
||||
if resp.status == chameleon_status.Device.HF_TAG_OK:
|
||||
@@ -1632,9 +1644,9 @@ class HF14ARaw(ReaderRequiredUnit):
|
||||
# print head
|
||||
" - " +
|
||||
# print data
|
||||
' '.join([ hex(byte).replace('0x', '').rjust(2, '0') for byte in resp.data ])
|
||||
' '.join([hex(byte).replace('0x', '').rjust(2, '0') for byte in resp.data])
|
||||
)
|
||||
else:
|
||||
print(F" [*] {CY}No data response{C0}")
|
||||
print(F" [*] {CY}No response{C0}")
|
||||
else:
|
||||
print(f" [!] {CR}{chameleon_status.message[resp.status]}{C0} ")
|
||||
|
||||
@@ -617,7 +617,7 @@ class ChameleonCMD:
|
||||
resp.data = resp.status == chameleon_status.Device.HF_TAG_OK
|
||||
return resp
|
||||
|
||||
def hf14a_raw(self, options, resp_timeout_ms=100, data=[], bit_owned_by_the_last_byte=None):
|
||||
def hf14a_raw(self, options, resp_timeout_ms=100, data=[], bitlen=None):
|
||||
"""
|
||||
Send raw cmd to 14a tag
|
||||
:param options:
|
||||
@@ -629,40 +629,35 @@ class ChameleonCMD:
|
||||
|
||||
class CStruct(ctypes.BigEndianStructure):
|
||||
_fields_ = [
|
||||
("open_rf_field", ctypes.c_uint8, 1),
|
||||
("activate_rf_field", ctypes.c_uint8, 1),
|
||||
("wait_response", ctypes.c_uint8, 1),
|
||||
("append_crc", ctypes.c_uint8, 1),
|
||||
("bit_frame", ctypes.c_uint8, 1),
|
||||
("auto_select", ctypes.c_uint8, 1),
|
||||
("keep_rf_field", ctypes.c_uint8, 1),
|
||||
("check_response_crc", ctypes.c_uint8, 1),
|
||||
("reserved", ctypes.c_uint8, 1),
|
||||
("reserved", ctypes.c_uint8, 2),
|
||||
]
|
||||
|
||||
cs = CStruct()
|
||||
cs.open_rf_field = options['open_rf_field']
|
||||
cs.activate_rf_field = options['activate_rf_field']
|
||||
cs.wait_response = options['wait_response']
|
||||
cs.append_crc = options['append_crc']
|
||||
cs.bit_frame = options['bit_frame']
|
||||
cs.auto_select = options['auto_select']
|
||||
cs.keep_rf_field = options['keep_rf_field']
|
||||
cs.check_response_crc = options['check_response_crc']
|
||||
|
||||
if options['bit_frame'] == 1:
|
||||
bits_or_bytes = len(data) * 8 # bits = bytes * 8(bit)
|
||||
if bit_owned_by_the_last_byte is not None and bit_owned_by_the_last_byte != 8:
|
||||
bits_or_bytes = bits_or_bytes - (8 - bit_owned_by_the_last_byte)
|
||||
if bitlen is None:
|
||||
bitlen = len(data) * 8 # bits = bytes * 8(bit)
|
||||
else:
|
||||
bits_or_bytes = len(data) # bytes length
|
||||
|
||||
if len(data) > 0:
|
||||
data = struct.pack(f'!BHH{len(data)}s', bytes(cs)[0], resp_timeout_ms, bits_or_bytes, bytearray(data))
|
||||
else:
|
||||
data = struct.pack(f'!BHH', bytes(cs)[0], resp_timeout_ms, 0)
|
||||
if len(data) == 0:
|
||||
raise ValueError(f'bitlen={bitlen} but missing data')
|
||||
if not ((len(data) - 1) * 8 < bitlen <= len(data) * 8):
|
||||
raise ValueError(f'bitlen={bitlen} incompatible with provided data ({len(data)} bytes), '
|
||||
f'must be between {((len(data) - 1) * 8 )+1} and {len(data) * 8} included')
|
||||
|
||||
data = bytes(cs)+struct.pack(f'!HH{len(data)}s', resp_timeout_ms, bitlen, bytearray(data))
|
||||
return self.device.send_cmd_sync(DATA_CMD_HF14A_RAW, data, timeout=(resp_timeout_ms / 1000) + 1)
|
||||
|
||||
|
||||
@expect_response(chameleon_status.Device.HF_TAG_OK)
|
||||
def mf1_static_nested_acquire(self, block_known, type_known, key_known, block_target, type_target):
|
||||
"""
|
||||
@@ -1228,26 +1223,24 @@ def test_fn():
|
||||
cml.set_device_reader_mode()
|
||||
|
||||
options = {
|
||||
'open_rf_field': 1,
|
||||
'activate_rf_field': 1,
|
||||
'wait_response': 1,
|
||||
'append_crc': 0,
|
||||
'bit_frame': 1,
|
||||
'auto_select': 0,
|
||||
'keep_rf_field': 1,
|
||||
'check_response_crc': 0,
|
||||
}
|
||||
|
||||
# unlock 1
|
||||
resp = cml.hf14a_raw(options=options, resp_timeout_ms=1000, data=[0x40], bit_owned_by_the_last_byte=7)
|
||||
resp = cml.hf14a_raw(options=options, resp_timeout_ms=1000, data=[0x40], bitlen=7)
|
||||
|
||||
if resp.status == 0x00 and resp.data[0] == 0x0a:
|
||||
print("Gen1A unlock 1 success")
|
||||
# unlock 2
|
||||
options['bit_frame'] = 0
|
||||
resp = cml.hf14a_raw(options=options, resp_timeout_ms=1000, data=[0x43])
|
||||
if resp.status == 0x00 and resp.data[0] == 0x0a:
|
||||
print("Gen1A unlock 2 success")
|
||||
print("Start dump gen1a memeory...")
|
||||
print("Start dump gen1a memory...")
|
||||
block = 0
|
||||
while block < 64:
|
||||
# Tag read block cmd
|
||||
|
||||
Reference in New Issue
Block a user