style
[RRG-proxmark3.git] / client / lualibs / trace_parse.lua
blob5e132936ac0bb4a5e74ee825d3769dbc9a204d0e
1 --[[
2 Simple Trace Parser library
4 -- fair warning, this is best to just get trace data values, I didn't see any better implementation for this, so I just made one myself
6 -- Example Usage
7 -- Load the traceParser library
8 local traceParser = require("trace_parse")
10 -- Parse the trace file
11 local trace_data = traceParser.parse_trace_file(filename)
13 -- Print the parsed data
14 for _, record in ipairs(trace_data) do
15 -- Format the data bytes
16 local data_bytes = {}
17 for i = 1, #record.data do
18 table.insert(data_bytes, string.format("%02X", record.data:byte(i)))
19 end
20 local data_str = table.concat(data_bytes, "")
21 print("Data: " .. data_str)
22 end
26 local bit = require("bit") -- Requires Lua bitwise library (bit)
27 local traceParser = {}
29 -- Function to read a 4-byte unsigned integer (little-endian)
30 local function read_u32_le(data, pos)
31 if pos + 3 > #data then return nil, pos end
32 local b1, b2, b3, b4 = data:byte(pos, pos + 3)
33 return (b4 * 2^24) + (b3 * 2^16) + (b2 * 2^8) + b1, pos + 4
34 end
36 -- Function to read a 2-byte unsigned integer (little-endian)
37 local function read_u16_le(data, pos)
38 if pos + 1 > #data then return nil, pos end
39 local b1, b2 = data:byte(pos, pos + 1)
40 return (b2 * 2^8) + b1, pos + 2
41 end
43 -- Function to parse a single record from the trace file
44 local function parse_record(trace, pos)
45 local record = {}
47 -- Read the 32-bit timestamp (4 bytes, little-endian)
48 record.timestamp_start, pos = read_u32_le(trace, pos)
50 -- Read the 16-bit duration (2 bytes, little-endian)
51 record.duration, pos = read_u16_le(trace, pos)
53 -- Read the 15-bit data length and 1-bit isResponse flag
54 local data_len_and_flag, pos = read_u16_le(trace, pos)
55 record.data_len = bit.band(data_len_and_flag, 0x7FFF) -- 15 bits for data length
56 record.is_response = bit.rshift(data_len_and_flag, 15) == 1 -- 1 bit for isResponse
58 -- Read the data bytes
59 record.data, pos = trace:sub(pos, pos + record.data_len - 1), pos + record.data_len
61 -- Read the parity bytes (parity length is ceil(data_len / 8))
62 local parity_len = math.ceil(record.data_len / 8)
63 record.parity, pos = trace:sub(pos, pos + parity_len - 1), pos + parity_len
65 return record, pos
66 end
68 -- Function to parse the entire trace file
69 function traceParser.parse_trace_file(file_path)
70 local trace_data = {}
71 local trace_file = io.open(file_path, "rb")
73 if not trace_file then
74 error("Could not open file: " .. file_path)
75 end
77 -- Read the entire content of the file
78 local content = trace_file:read("*all")
79 trace_file:close()
81 -- Parse records in the file
82 local pos = 1
83 while pos <= #content do
84 local record
85 record, pos = parse_record(content, pos)
86 if record then
87 table.insert(trace_data, record)
88 else
89 break -- Stop if the record is invalid or incomplete
90 end
91 end
93 return trace_data
94 end
97 return traceParser