2 -- Ability to read what card is there
3 local getopt = require('getopt')
4 local cmds = require('commands')
5 local taglib = require('taglib')
8 [[This script will automatically recognize and dump full content of a NFC NDEF Initialized tag; non-initialized tags will be ignored.
15 local example = "script run xxx"
16 local author = "Martin Holst Swende & Asper"
24 -- TODO; replace this with a call to the proper PrintAndLog
31 prlog("Example usage")
42 -- This is only meant to be used when errors occur
48 local function show(data)
50 local formatString = ("H%d"):format(string.len(data))
51 local _,hexdata = bin.unpack(formatString, data)
52 debug("Hexdata" , hexdata)
55 --- Fire up a connection with a tag, return uid
56 -- @return UID if successfull
57 -- @return nil, errormessage if unsuccessfull
60 debug("Opening connection")
61 core.clearCommandBuffer()
62 local x = string.format("hf 14a raw -r -p -s")
66 data, err = waitCmd(true)
67 if err then return oops(err) end
69 local formatString = ("H%d"):format(string.len(data))
70 local _,uid = bin.unpack(formatString, data)
73 --- Shut down tag communication
74 -- return no return values
75 local function close()
76 debug("Closing connection")
77 core.clearCommandBuffer()
78 local x = string.format("hf 14a raw -r")
82 --data, err = waitCmd(true)
83 --data, err = waitCmd(false)
88 ---_ Gets data from a block
89 -- @return {block, block+1, block+2, block+3} if successfull
90 -- @return nil, errormessage if unsuccessfull
91 local function getBlock(block)
94 core.clearCommandBuffer()
96 local x = string.format("hf 14a raw -r -c -p 30 %02x", block)
100 -- By now, there should be an ACK waiting from the device, since
101 -- we used the -r flag (don't read response).
103 data, err = waitCmd(false)
104 if err then return oops(err) end
107 if string.len(data) < 18 then
108 return nil, ("Error, expected at least 18 bytes, got %d"):format(string.len(data))
110 -- Now, parse out the block data
111 -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
112 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
113 b0 = string.sub(data,1,4)
114 b1 = string.sub(data,5,8)
115 b2 = string.sub(data,9,12)
116 b3 = string.sub(data,13,16)
121 --- This function is a lua-implementation of
122 -- cmdhf14a.c:waitCmd(uint8_t iSelect)
123 function waitCmd(iSelect)
124 local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000)
126 local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response)
129 if iSelect then iLen = arg1 end
130 debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1))
131 if iLen == 0 then return nil, "No response from tag" end
132 local recv = string.sub(response,count, iLen+count-1)
135 return nil, "No response from device"
140 local function main( args)
141 debug("script started")
142 local err, data, data2,k,v,i
143 -- Read the parameters
144 for o, a in getopt.getopt(args, 'hd') do
145 if o == "h" then help() return end
146 if o == "d" then DEBUG = true end
149 -- Info contained within the tag (block 0 example)
150 -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155
151 -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC
152 -- MM?? ???? ???? ???? ???? ???? NNVV SS?? ----
153 -- M = Manufacturer info
154 -- N = NDEF-Structure-Compliant (if value is E1)
155 -- V = NFC Forum Specification version (if 10 = v1.0)
157 -- First, 'connect' (fire up the field) and get the uid
158 local uidHexstr = open()
160 -- First, get blockt 3 byte 2
161 local blocks, err = getBlock(0)
162 if err then return oops(err) end
163 -- Block 3 contains number of blocks
164 local b3chars = {string.byte(blocks[4], 1,4)}
165 local numBlocks = b3chars[3] * 2 + 6
166 prlog("Number of blocks:", numBlocks)
169 if b3chars[1] ~= 0xE1 then
170 return oops("This tag is not NDEF-Complian")
173 local ndefVersion = b3chars[2]
175 -- Block 1, byte 1 contains manufacturer info
176 local bl1_b1 = string.byte(blocks[1], 1)
177 local manufacturer = taglib.lookupManufacturer(bl1_b1)
179 -- Reuse existing info
180 local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]}
183 --[[ Due to the infineon my-d move bug
184 (if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12)
185 the only way to avoid this is to send the read command as many times as block numbers
186 removing bytes from 5 to 18 from each answer.
188 prlog("Dumping data...please wait")
189 for i=4,numBlocks-1,1 do
190 blocks, err = getBlock(i)
191 if err then return oops(err) end
192 table.insert(blockData,blocks[1])
197 prlog(string.format("Tag manufacturer: %s", manufacturer))
198 prlog(string.format("Tag UID: %s", uidHexstr))
199 prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion))
201 for k,v in ipairs(blockData) do
202 prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4)))