local cmds = require('commands') local getopt = require('getopt') local bin = require('bin') local utils = require('utils') local ansicolors = require('ansicolors') local format = string.format local floor = math.floor copyright = '' author = "Iceman" version = 'v1.0.4' desc =[[ This script will program a T55x7 TAG with a configuration and four blocks of data. It will then try to detect and read back those block data and compare if read data matches the expected data. lf t55xx wipe lf t55xx detect lf t55xx write b 1 d 00000000 lf t55xx write b 2 d ffffffff lf t55xx write b 3 d 80000000 lf t55xx write b 4 d 00000001 Loop: try write different configuration blocks, and read block1-4 and comparing the read values with the values used to write. testsuit for T55XX commands demodulation ]] example = [[ 1. script run lf_t55xx_writetest 2. script run lf_t55xx_writetest -t FSK2A 3. script run lf_t55xx_writetest -t PSK1 ]] usage = [[ script run lf_t55xx_writetest [-h] [-t ]] arguments = [[ -h this help -t (optional, defaults to ASK) 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2', 'FSK1A', 'FSK2A', 'ASK', 'BI' ]] local DEBUG = true -- the debug flag local TIMEOUT = 1500 local total_tests = 0 local total_pass = 0 local data_blocks_cmds = { [1] = '00000000', [2] = 'ffffffff', [3] = '80000000', [4] = '00000001', } --- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == 'table' then local i = 1 while args[i] do dbg(args[i]) i = i+1 end else print('###', args) end end --- -- This is only meant to be used when errors occur local function oops(err) print('ERROR:', err) core.clearCommandBuffer() return nil, err end --- -- Usage help local function help() print(copyright) print(author) print(version) print(desc) print(ansicolors.cyan..'Usage'..ansicolors.reset) print(usage) print(ansicolors.cyan..'Arguments'..ansicolors.reset) print(arguments) print(ansicolors.cyan..'Example usage'..ansicolors.reset) print(example) end --- -- Exit message local function exitMsg(msg) print( string.rep('--',20) ) print( string.rep('--',20) ) print(msg) print() end --- -- ask/fsk/psk configuration blocks to test local function GetConfigs( modulation ) local t = {} t['PSK1'] = { -- Rf2 [1] = '00001040', -- 8 [2] = '00041040', -- 16 [3] = '00081040', -- 32 [4] = '000c1040', -- 40 [5] = '00101040', -- 50 [6] = '00141040', -- 64 [7] = '00181040', -- 100 [8] = '001c1040', -- 128 -- Rf4 [9] = '00001440', -- 8 [10] = '00041440', -- 16 [11] = '00081440', -- 32 [12] = '000c1440', -- 40 -- [] = '00101440', -- 50 50/4 == 12.5 invalid [13] = '00141440', -- 64 [14] = '00181440', -- 100 [15] = '001c1440', -- 128 -- Rf8 [16] = '00001840', -- 8 [17] = '00041840', -- 16 [18] = '00081840', -- 32 [19] = '000c1840', -- 40 -- [] = '00101840', -- 50 50/8 = 6.25 invalid [20] = '00141840', -- 64 -- [] = '00181840', -- 100 100/8 == 12.5 invalid [21] = '001c1840', -- 128 } t['PSK2'] = { -- Rf2 [1] = '00002040', -- 8 [2] = '00042040', -- 16 [3] = '00082040', -- 32 [4] = '000c2040', -- 40 [5] = '00102040', -- 50 [6] = '00142040', -- 64 [7] = '00182040', -- 100 [8] = '001c2040', -- 128 -- Rf4 [9] = '00002440', -- 8 [10] = '00042440', -- 16 [11] = '00082440', -- 32 [12] = '000c2440', -- 40 -- [] = '00102440', -- 50 50/4 == 12.5 invalid [13] = '00142440', -- 64 [14] = '00182440', -- 100 [15] = '001c2440', -- 128 -- Rf8 [16] = '00002840', -- 8 [17] = '00042840', -- 16 [18] = '00082840', -- 32 [19] = '000c2840', -- 40 -- [] = '00102840', -- 50 50/8 == 6.25 invalid [20] = '00142840', -- 64 -- [] = '00182840', -- 100 100/8 == 12.5 invalid [21] = '001c2840', -- 128 } t['PSK3'] = { -- Rf2 [1] = '00003040', -- 8 [2] = '00043040', -- 16 [3] = '00083040', -- 32 [4] = '000c3040', -- 40 [5] = '00103040', -- 50 [6] = '00143040', -- 64 [7] = '00183040', -- 100 [8] = '001c3040', -- 128 -- Rf4 [9] = '00003440', -- 8 [10] = '00043440', -- 16 [11] = '00083440', -- 32 [12] = '000c3440', -- 40 -- [] = '00103440', -- 50 50/4 == 12.5 invalid [13] = '00143440', -- 64 [14] = '00183440', -- 100 [15] = '001c3440', -- 128 -- Rf2 [16] = '00003840', -- 8 [17] = '00043840', -- 16 [18] = '00083840', -- 32 [19] = '000c3840', -- 40 -- [] = '00103840', -- 50 50/8 == 6.25 invalid [20] = '00143840', -- 64 -- [] = '00183840', -- 100 100/8 == 12.5 invalid [21] = '001c3840', -- 128 } t['FSK1'] = { [1] = '00004040', [2] = '00004040', [3] = '00044040', [4] = '00084040', [5] = '000c4040', [6] = '00104040', [7] = '00144040', [8] = '00184040', [9] = '001c4040', } t['FSK2'] = { [1] = '00005040', [2] = '00045040', [3] = '00085040', [4] = '000c5040', [5] = '00105040', [6] = '00145040', [7] = '00185040', [8] = '001c5040', } t['FSK1A'] = { [1] = '00006040', [2] = '00046040', [3] = '00086040', [4] = '000c6040', [5] = '00106040', [6] = '00146040', [7] = '00186040', [8] = '001c6040', } t['FSK2A'] = { [1] = '00007040', [2] = '00047040', [3] = '00087040', [4] = '000c7040', [5] = '00107040', [6] = '00147040', [7] = '00187040', [8] = '001c7040', } t['ASK'] = { [1] = '00008040', [2] = '00048040', [3] = '00088040', [4] = '000c8040', [5] = '00108040', [6] = '00148040', [7] = '00188040', [8] = '001c8040', } t['BI'] = { [1] = '00010040', [2] = '00050040', [3] = '00090040', [4] = '000d0040', [5] = '00110040', [6] = '00150040', [7] = '00190040', [8] = '001d0040', } return t[modulation:upper()] end --- -- lf t55xx wipe local function WipeCard() print('Wiping card') core.console('lf t55xx wipe') print('Detecting card') local res, msg = core.t55xx_detect() if not res then oops("Can't detect modulation. Test failed.") core.console('rem [ERR:DETECT:WIPED] Failed to detect after wipe') return false else local wipe_data_cmd = 'lf t55xx write b %s d %s' for _ = 1, #data_blocks_cmds do local val = data_blocks_cmds[_] local c = string.format(wipe_data_cmd, _, val) core.console(c) end return true end end --- -- lf t55xx read local function CheckReadBlock(block) local data, msg -- blockno, page1, override, pwd data, msg = core.t55xx_readblock(block, '0', '0', '') if not data then return '' end return ('%08X'):format(data) end local function test(modulation) local process_block0_cmds = {} local y local password = '00000000' local block = '00' -- configuration block 0 local flags = '00' -- page 0, no pwd, no testmode local s = ('Start test of %s'):format(modulation) print(s) process_block0_cmds = GetConfigs(modulation) if process_block0_cmds == nil then return oops('Cant find modulation '..modulation) end for _ = 1, #process_block0_cmds do local p_config_cmd = process_block0_cmds[_] local errors = 0 core.clearCommandBuffer() -- Write Config block dbg(('lf t55xx write b 0 d %s'):format(p_config_cmd)) local data = ('%s%s%s%s'):format(utils.SwapEndiannessStr(p_config_cmd, 32), password, block, flags) local wc = Command:newNG{cmd = cmds.CMD_LF_T55XX_WRITEBL, data = data} local response, err = wc:sendNG(false, TIMEOUT) if not response then return oops(err) end -- Detect local res, msg = core.t55xx_detect() if not res then print("can't detect modulation, skip to next config") core.console(format('rem [ERR:DETECT:%s] Failed to detect modulation', p_config_cmd)) core.console(format('rem [SUMMARY:%s] FAIL detection', p_config_cmd)) total_tests = total_tests + #data_blocks_cmds else -- Loop block1-2 for _ = 1, #data_blocks_cmds do total_tests = total_tests + 1 local val = data_blocks_cmds[_] local blockdata, msg = CheckReadBlock(_) if blockdata:lower() ~= val:lower() then print( ('Test %s == %s Failed'):format(val, blockdata)) core.console( format('rem [ERR:READ:%s:%d] block %d: read %s instead of %s', p_config_cmd, _, _, blockdata, val)) errors = errors+1 else print( ('Test %s == %s OK'):format(val, blockdata)) total_pass = total_pass + 1 end end if errors >0 then core.console( format('rem [SUMMARY:%s] FAIL %d test%s', p_config_cmd, errors, errors > 1 and "s" or "")) else core.console( format('rem [SUMMARY:%s] PASS all tests', p_config_cmd)) end end end end local function main(args) print( string.rep('--',20) ) print( string.rep('--',20) ) local modulation_type = 'ASK' -- Arguments for the script for o, arg in getopt.getopt(args, 'ht:') do if o == 'h' then return help() end if o == 't' then modulation_type = arg end end core.clearCommandBuffer() local res -- Adjust this table to set which configurations should be tested -- local test_modes = { 'PSK1', 'PSK2', 'PSK3', 'FSK1', 'FSK2', 'FSK1A', 'FSK2A', 'ASK', 'BI' } --local test_modes = { 'PSK1' } local test_modes = { modulation_type } for _ = 1, #test_modes do res = WipeCard() if res then print (test_modes[_]) test(test_modes[_]) else exitMsg('Abort!') return end end exitMsg('Tests finished') core.console( format('rem [SUMMARY] Success rate: %d/%d tests passed%s' , total_pass , total_tests , total_pass < total_tests and ', help me improving that number!' or ' \\o/' ) ) end main(args)