]>
Commit | Line | Data |
---|---|---|
1 | local cmds = require('commands') | |
2 | local getopt = require('getopt') | |
3 | local lib14a = require('read14a') | |
4 | ||
5 | example = "script run 14araw -x 6000F57b" | |
6 | author = "Martin Holst Swende" | |
7 | ||
8 | ||
9 | desc = | |
10 | [[ | |
11 | This is a script to allow raw 1444a commands to be sent and received. | |
12 | ||
13 | Arguments: | |
14 | -o do not connect - use this only if you previously used -p to stay connected | |
15 | -r do not read response | |
16 | -c calculate and append CRC | |
17 | -p stay connected - dont inactivate the field | |
18 | -x <payload> Data to send (NO SPACES!) | |
19 | -d Debug flag | |
20 | -t Topaz mode | |
21 | -3 Skip ISO14443-4 select | |
22 | ||
23 | Examples : | |
24 | ||
25 | # 1. Connect and don't disconnect | |
26 | script run 14araw -p | |
27 | # 2. Send mf auth, read response (nonce) | |
28 | script run 14araw -o -x 6000F57b -p | |
29 | # 3. disconnect | |
30 | script run 14araw -o | |
31 | ||
32 | # All three steps in one go: | |
33 | script run 14araw -x 6000F57b | |
34 | ]] | |
35 | ||
36 | --[[ | |
37 | ||
38 | This script communicates with | |
39 | /armsrc/iso14443a.c, specifically ReaderIso14443a() at around line 1779 and onwards. | |
40 | ||
41 | Check there for details about data format and how commands are interpreted on the | |
42 | device-side. | |
43 | ]] | |
44 | ||
45 | -- Some globals | |
46 | local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds | |
47 | local DEBUG = false -- the debug flag | |
48 | ||
49 | ------------------------------- | |
50 | -- Some utilities | |
51 | ------------------------------- | |
52 | ||
53 | --- | |
54 | -- A debug printout-function | |
55 | function dbg(args) | |
56 | if DEBUG then | |
57 | print("###", args) | |
58 | end | |
59 | end | |
60 | --- | |
61 | -- This is only meant to be used when errors occur | |
62 | function oops(err) | |
63 | print("ERROR: ",err) | |
64 | end | |
65 | ||
66 | ||
67 | --- | |
68 | -- Usage help | |
69 | function help() | |
70 | print(desc) | |
71 | print("Example usage") | |
72 | print(example) | |
73 | end | |
74 | ||
75 | ||
76 | --- | |
77 | -- The main entry point | |
78 | function main(args) | |
79 | ||
80 | if args == nil or #args == 0 then | |
81 | return help() | |
82 | end | |
83 | ||
84 | local ignore_response = false | |
85 | local appendcrc = false | |
86 | local stayconnected = false | |
87 | local payload = nil | |
88 | local doconnect = true | |
89 | local topaz_mode = false | |
90 | local no_rats = false | |
91 | ||
92 | -- Read the parameters | |
93 | for o, a in getopt.getopt(args, 'orcpx:dt3') do | |
94 | if o == "o" then doconnect = false end | |
95 | if o == "r" then ignore_response = true end | |
96 | if o == "c" then appendcrc = true end | |
97 | if o == "p" then stayconnected = true end | |
98 | if o == "x" then payload = a end | |
99 | if o == "d" then DEBUG = true end | |
100 | if o == "t" then topaz_mode = true end | |
101 | if o == "3" then no_rats = true end | |
102 | end | |
103 | ||
104 | -- First of all, connect | |
105 | if doconnect then | |
106 | dbg("doconnect") | |
107 | -- We reuse the connect functionality from a | |
108 | -- common library | |
109 | info, err = lib14a.read14443a(true, no_rats) | |
110 | ||
111 | if err then return oops(err) end | |
112 | print(("Connected to card, uid = %s"):format(info.uid)) | |
113 | end | |
114 | ||
115 | -- The actual raw payload, if any | |
116 | if payload then | |
117 | res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode}) | |
118 | if err then return oops(err) end | |
119 | ||
120 | if not ignoreresponse then | |
121 | -- Display the returned data | |
122 | showdata(res) | |
123 | end | |
124 | end | |
125 | -- And, perhaps disconnect? | |
126 | if not stayconnected then | |
127 | disconnect() | |
128 | end | |
129 | end | |
130 | ||
131 | --- Picks out and displays the data read from a tag | |
132 | -- Specifically, takes a usb packet, converts to a Command | |
133 | -- (as in commands.lua), takes the data-array and | |
134 | -- reads the number of bytes specified in arg1 (arg0 in c-struct) | |
135 | -- and displays the data | |
136 | -- @param usbpacket the data received from the device | |
137 | function showdata(usbpacket) | |
138 | local cmd_response = Command.parse(usbpacket) | |
139 | local len = tonumber(cmd_response.arg1) *2 | |
140 | --print("data length:",len) | |
141 | local data = string.sub(tostring(cmd_response.data), 0, len); | |
142 | print("<< ",data) | |
143 | --print("----------------") | |
144 | end | |
145 | ||
146 | ||
147 | function sendRaw(rawdata, options) | |
148 | print(">> ", rawdata) | |
149 | ||
150 | local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW | |
151 | if options.topaz_mode == true then flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE end | |
152 | ||
153 | local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, | |
154 | arg1 = flags, -- Send raw | |
155 | -- arg2 contains the length, which is half the length | |
156 | -- of the ASCII-string rawdata | |
157 | arg2 = string.len(rawdata)/2, | |
158 | data = rawdata} | |
159 | return lib14a.sendToDevice(command, options.ignore_response) | |
160 | end | |
161 | ||
162 | -- Sends an instruction to do nothing, only disconnect | |
163 | function disconnect() | |
164 | ||
165 | local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, | |
166 | arg1 = 0, -- Nothing | |
167 | } | |
168 | -- We can ignore the response here, no ACK is returned for this command | |
169 | -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details | |
170 | return lib14a.sendToDevice(command,true) | |
171 | end | |
172 | ||
173 | ||
174 | ------------------------- | |
175 | -- Testing | |
176 | ------------------------- | |
177 | function selftest() | |
178 | DEBUG = true | |
179 | dbg("Performing test") | |
180 | main() | |
181 | main("-p") | |
182 | main(" -o -x 6000F57b -p") | |
183 | main("-o") | |
184 | main("-x 6000F57b") | |
185 | dbg("Tests done") | |
186 | end | |
187 | -- Flip the switch here to perform a sanity check. | |
188 | -- It read a nonce in two different ways, as specified in the usage-section | |
189 | if "--test"==args then | |
190 | selftest() | |
191 | else | |
192 | -- Call the main | |
193 | main(args) | |
194 | end |