style
[RRG-proxmark3.git] / client / lualibs / commands.lua
blobd10a32cfe5110e3cc9420ad7198e15945cbfb190
1 --[[
2 Handle Proxmark Communication Commands
3 --]]
5 local _commands = require('pm3_cmd')
6 local util = require('utils')
7 local TIMEOUT = 2000
9 local _reverse_lookup,k,v = {}
10 for k, v in pairs(_commands) do
11 _reverse_lookup[v] = k
12 end
13 _commands.tostring = function(command)
14 if(type(command) == 'number') then
15 return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command)
16 end
17 return ("Error, numeric argument expected, got : %s"):format(tostring(command))
18 end
20 Command = {
22 new = function(self, o)
24 local o = o or {} -- create object if user does not provide one
25 setmetatable(o, self) -- DIY inheritance a'la javascript
26 self.__index = self
28 o.cmd = o.cmd or _commands.CMD_UNKNOWN
29 o.arg1 = o.arg1 or 0
30 o.arg2 = o.arg2 or 0
31 o.arg3 = o.arg3 or 0
32 local data = o.data or "0"
34 if (type(data) == 'string') then
35 -- We need to check if it is correct length, otherwise pad it
36 local len = #data
37 if (len < 1024) then
38 --Should be 1024 hex characters to represent 512 bytes of data
39 data = data .. string.rep("0",1024 - len )
40 end
41 if (len > 1024) then
42 -- OOps, a bit too much data here
43 print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) )
45 data = data:sub(1, 1024)
46 end
47 else
48 print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data)))
49 end
50 o.data = data
51 return o
52 end,
53 newMIX = function(self, o)
55 local o = o or {} -- create object if user does not provide one
56 setmetatable(o, self) -- DIY inheritance a'la javascript
57 self.__index = self
59 o.cmd = o.cmd or _commands.CMD_UNKNOWN
60 o.arg1 = o.arg1 or 0
61 o.arg2 = o.arg2 or 0
62 o.arg3 = o.arg3 or 0
63 local data = o.data or ''
65 if (type(data) == 'string') then
66 if (#data > 1024) then
67 -- OOps, a bit too much data here
68 print( ( "WARNING: data size too large, was %s chars, will be truncated "):format( #data) )
70 data = data:sub(1, 1024)
71 end
72 end
73 o.data = data
74 return o
75 end,
76 newNG = function(self, o)
78 local o = o or {} -- create object if user does not provide one
79 setmetatable(o, self) -- DIY inheritance a'la javascript
80 self.__index = self
82 o.cmd = o.cmd or _commands.CMD_UNKNOWN
83 local data = o.data or ''
85 if (type(data) == 'string') then
86 if (#data > 1024) then
87 -- OOps, a bit too much data here
88 print( ( "WARNING: data size too large, was %s chars, will be truncated "):format( #data) )
90 data = data:sub(1, 1024)
91 end
92 end
93 o.data = data
94 return o
95 end,
96 parse = function(packet)
97 local count, cmd, arg1, arg2, arg3, data = bin.unpack('LLLL', packet)
98 local length = #packet - count + 1
99 count, data = bin.unpack('H'..length, packet, count)
100 return Command:new{cmd = cmd, arg1 = arg1, arg2 = arg2, arg3 = arg3, data = data}
103 -- commented out, not used.
104 function Command:__tostring()
105 local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format(
106 _commands.tostring(self.cmd),
107 tostring(self.arg1),
108 tostring(self.arg2),
109 tostring(self.arg3),
110 tostring(self.data))
111 return output
114 function Command:getBytes()
115 --If a hex-string has been used
116 local data = self.data
117 local cmd = self.cmd
118 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
119 return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data);
122 --- Sends a packet to the device
123 -- @param command - the usb packet to send
124 -- @param ignoreresponse - if set to true, we don't read the device answer packet
125 -- which is usually recipe for fail. If not sent, the host will wait 2s for a
126 -- response of type CMD_ACK or like NG use the CMD as ack..
127 -- @return packet,nil if successful
128 -- nil, errormessage if unsuccessful
129 function Command:sendMIX( ignore_response, timeout, use_cmd_ack)
130 if timeout == nil then timeout = TIMEOUT end
131 local data = self.data
132 local cmd = self.cmd
133 local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3
135 local err, msg = core.SendCommandMIX(cmd, arg1, arg2, arg3, data)
136 if err == nil then return err, msg end
137 if ignore_response then return true, nil end
139 local ack = _commands.CMD_ACK
140 if use_cmd_ack then
141 ack = cmd
144 local response, msg = core.WaitForResponseTimeout(ack, timeout)
145 if response == nil then
146 return nil, 'Error, waiting for response timed out :: '..msg
148 -- lets digest
149 data = nil
150 cmd = nil
151 arg1 = nil
152 arg2 = nil
153 arg3 = nil
154 local count, length, magic, status, crc, ng
156 -- S S I s S L L L
157 count, cmd, length, magic, status, crc, arg1, arg2, arg3 = bin.unpack('SSIsSLLL', response)
158 count, data, ng = bin.unpack('H'..length..'C', response, count)
160 local packed = bin.pack("LLLLH", cmd, arg1, arg2, arg3, data)
161 return packed, nil;
163 function Command:sendNG( ignore_response, timeout )
164 if timeout == nil then timeout = TIMEOUT end
165 local data = self.data
166 local cmd = self.cmd
167 local err, msg = core.SendCommandNG(cmd, data)
168 if err == nil then return nil, msg end
170 if ignore_response then return true, nil end
171 local response, msg = core.WaitForResponseTimeout(cmd, timeout)
172 if response == nil then
173 return nil, 'Error, waiting for response timed out :: '..msg
176 data = nil
177 cmd = nil
178 local count, length, magic, status, crc, arg0, arg1, arg2
180 count, cmd, length, magic, status, crc, arg0, arg1, arg2 = bin.unpack('SSIsSLLL', response)
181 count, data, ng = bin.unpack('H'..length..'C', response, count)
183 --[[ uncomment if you want to debug
184 print('NG package received')
185 print('CMD ::', tostring(cmd))
186 print('Length ::', tostring(length))
187 print('Magic ::', string.format("0x%08X", magic), util.ConvertHexToAscii(string.format("0x%08X", magic)))
188 print('Status ::', tostring(status))
189 print('crc ::', string.format("0x%02X", crc))
190 print('Args ::', ("(%s, %s, %s)\r\n"):format(
191 tostring(arg0),
192 tostring(arg1),
193 tostring(arg2)))
194 print('NG ::', ng)
195 print('Data ::', data)
196 --]]
197 return { Cmd = cmd,
198 Length = length,
199 Magic = magic,
200 Status = status,
201 Crc = crc,
202 Oldarg0 = arg0,
203 Oldarg1 = arg1,
204 Oldarg2 = arg2,
205 Data = data,
206 Ng = ng
210 return _commands