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