2 Handle Proxmark Communication Commands
5 local _commands
= require('pm3_cmd')
6 local util
= require('utils')
9 local _reverse_lookup
,k
,v
= {}
10 for k
, v
in pairs(_commands
) do
11 _reverse_lookup
[v
] = k
13 _commands
.tostring = function(command
)
14 if(type(command
) == 'number') then
15 return ("%s (%d)"):format(_reverse_lookup
[command
]or "ERROR UNDEFINED!", command
)
17 return ("Error, numeric argument expected, got : %s"):format(tostring(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
28 o
.cmd
= o
.cmd
or _commands
.CMD_UNKNOWN
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
38 --Should be 1024 hex characters to represent 512 bytes of data
39 data
= data
.. string.rep("0",1024 - len
)
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)
48 print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data
)))
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
59 o
.cmd
= o
.cmd
or _commands
.CMD_UNKNOWN
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)
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
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)
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
),
114 function Command
:getBytes()
115 --If a hex-string has been used
116 local data
= self
.data
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
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
144 local response
, msg
= core
.WaitForResponseTimeout(ack
, timeout
)
145 if response
== nil then
146 return nil, 'Error, waiting for response timed out :: '..msg
154 local count
, length
, magic
, status
, crc
, ng
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
)
163 function Command
:sendNG( ignore_response
, timeout
)
164 if timeout
== nil then timeout
= TIMEOUT
end
165 local data
= self
.data
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
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(
195 print('Data ::', data)