4df3eb3f |
1 | local cmds = require('commands') |
b61f426c |
2 | local getopt = require('getopt') |
3 | local lib14a = require('read14a') |
4 | |
450d2e3a |
5 | example = "script run 14araw -x 6000F57b" |
b61f426c |
6 | author = "Martin Holst Swende" |
7 | |
8 | |
9 | desc = |
4df3eb3f |
10 | [[ |
b61f426c |
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 |
5d8f664d |
20 | -t Topaz mode |
21 | -3 Skip ISO14443-4 select |
b61f426c |
22 | |
23 | Examples : |
4df3eb3f |
24 | |
b61f426c |
25 | # 1. Connect and don't disconnect |
450d2e3a |
26 | script run 14araw -p |
b61f426c |
27 | # 2. Send mf auth, read response (nonce) |
450d2e3a |
28 | script run 14araw -o -x 6000F57b -p |
b61f426c |
29 | # 3. disconnect |
450d2e3a |
30 | script run 14araw -o |
4df3eb3f |
31 | |
b61f426c |
32 | # All three steps in one go: |
450d2e3a |
33 | script run 14araw -x 6000F57b |
4df3eb3f |
34 | ]] |
35 | |
b61f426c |
36 | --[[ |
4df3eb3f |
37 | |
b61f426c |
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 |
4df3eb3f |
46 | local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds |
b61f426c |
47 | local DEBUG = false -- the debug flag |
4df3eb3f |
48 | |
b61f426c |
49 | ------------------------------- |
50 | -- Some utilities |
51 | ------------------------------- |
52 | |
53 | --- |
54 | -- A debug printout-function |
55 | function dbg(args) |
56 | if DEBUG then |
450d2e3a |
57 | print("###", args) |
4df3eb3f |
58 | end |
b61f426c |
59 | end |
60 | --- |
61 | -- This is only meant to be used when errors occur |
62 | function oops(err) |
63 | print("ERROR: ",err) |
4df3eb3f |
64 | end |
65 | |
24d48e60 |
66 | |
b61f426c |
67 | --- |
68 | -- Usage help |
69 | function help() |
70 | print(desc) |
71 | print("Example usage") |
72 | print(example) |
73 | end |
74 | |
5d8f664d |
75 | |
b61f426c |
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 |
5d8f664d |
89 | local topaz_mode = false |
90 | local no_rats = false |
b61f426c |
91 | |
92 | -- Read the parameters |
7085af05 |
93 | for o, a in getopt.getopt(args, 'orcpx:dt3') do |
b61f426c |
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 |
5d8f664d |
100 | if o == "t" then topaz_mode = true end |
101 | if o == "3" then no_rats = true end |
b61f426c |
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 |
5d8f664d |
109 | info, err = lib14a.read1443a(true, no_rats) |
b61f426c |
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 |
7085af05 |
117 | res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode}) |
b61f426c |
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 | |
b61f426c |
147 | function sendRaw(rawdata, options) |
148 | print(">> ", rawdata) |
149 | |
150 | local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW |
7085af05 |
151 | if options.topaz_mode == true then flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE end |
b61f426c |
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 |
24d48e60 |
157 | arg2 = string.len(rawdata)/2, |
4df3eb3f |
158 | data = rawdata} |
b61f426c |
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, |
3e69b211 |
166 | arg1 = 0, -- Nothing |
167 | } |
b61f426c |
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() |
450d2e3a |
178 | DEBUG = true |
179 | dbg("Performing test") |
180 | main() |
b61f426c |
181 | main("-p") |
182 | main(" -o -x 6000F57b -p") |
183 | main("-o") |
184 | main("-x 6000F57b") |
450d2e3a |
185 | dbg("Tests done") |
b61f426c |
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 |
450d2e3a |
189 | if "--test"==args then |
b61f426c |
190 | selftest() |
191 | else |
192 | -- Call the main |
193 | main(args) |
4df3eb3f |
194 | end |