You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

740 lines
29 KiB

// License: Apache 2.0. See LICENSE file in root directory.
// Copyright(c) 2015 Intel Corporation. All Rights Reserved.
#include <string>
#include <map>
#include <regex>
#include <fstream>
#include <sstream>
#include <vector>
#include <functional>
#include <cstring>
#include <iomanip>
#ifdef ANDROID
#include "android_helpers.h"
#endif
#include "../third-party/rapidxml/rapidxml.hpp"
#include <rsutils/string/string-utilities.h>
#define MAX_PARAMS 4
struct section;
typedef std::function<void(const uint8_t*, const section&, std::stringstream&)> xml_parser_function;
const uint16_t HW_MONITOR_BUFFER_SIZE = 1024;
#pragma pack(push, 1)
typedef struct
{
uint8_t Version_Revision;
uint8_t Version_Number;
uint8_t Version_Minor;
uint8_t Version_Major;
int Version_spare;
}ChangeSetVersion;
typedef struct
{
uint8_t Version_Minor;
uint8_t Version_Major;
uint8_t Version_spare[2];
}MajorMinorVersion;
typedef struct
{
uint8_t Version1;
uint8_t Version2;
uint8_t Version3;
uint8_t Version4;
}HexByte;
typedef struct
{
uint8_t Version2;
uint8_t Version1;
uint8_t Version_spare[2];
}LiguriaVersion;
typedef struct
{
uint8_t sts;
}Bool;
typedef struct
{
uint8_t num;
}HwTypeNumber;
typedef struct
{
uint8_t Version_Minor;
uint8_t Version_Major;
uint8_t Version_spare[2];
}WideMajorMinorVersion;
typedef struct
{
uint8_t value[32];
}Ascii;
typedef struct
{
uint8_t version;
}DecByte;
typedef struct
{
uint8_t number1;
uint8_t number2;
uint8_t number3;
uint8_t number4;
}HexNumber;
typedef struct
{
uint8_t number1;
uint8_t number2;
uint8_t number3;
uint8_t number4;
}HexNumberReversed;
typedef struct
{
uint8_t number1;
uint8_t number2;
uint8_t number3;
uint8_t number4;
uint8_t number5;
uint8_t number6;
uint8_t number7;
uint8_t number8;
}BarCodeSerial12Char;
typedef struct
{
double number;
}DoubleNumber;
#pragma pack(pop)
struct parameter {
std::string name, data;
bool is_decimal, is_reverse_bytes;
int format_length;
parameter(std::string in_name, std::string in_data,
bool in_is_decimal, bool in_is_reverse_bytes,
int in_format_length)
: name(in_name),
format_length(in_format_length),
is_decimal(in_is_decimal),
is_reverse_bytes(in_is_reverse_bytes),
data(in_data)
{}
parameter()
: name(""),
format_length(2),
is_decimal(false),
is_reverse_bytes(false),
data("")
{}
};
struct section {
std::string name = "";
std::string title = "";
std::string format_type = "";
std::string data = "";
int offset = 0;
int size = 0;
};
struct data {
std::vector<section> sections;
};
struct kvp {
std::string key, value;
};
struct custom_formatter {
std::string name, key_size;
std::vector<kvp> kv;
};
typedef struct command
{
std::string name;
unsigned int op_code;
std::string read_format;
bool is_write_only = false;
bool is_read_command = false;
std::string description;
int time_out = 20000;
int num_of_parameters = 0;
bool is_cmd_write_data = false;
std::string cmd_permission;
std::string cmd_interface;
std::string cmd_pipe;
std::string i2c_reg_offset;
std::string i2c_cmd_type;
data read_data;
std::vector<parameter> parameters;
} command_from_xml;
// units of nibbles
enum FormatSize {
Byte = 2,
Word = 4,
Double = 8
};
struct commands_xml
{
std::map<std::string, command_from_xml> commands;
std::map<std::string, custom_formatter> custom_formatters;
};
// While working from files, convert the file content into recognized raw format
inline void file_argument_to_blob(std::vector<std::string>& params)
{
if (!params.size())
return;
//The last parameter provided by the user can represent a fully-qualified file path
std::ifstream file(params.back(), std::ios::binary | std::ios::in);
if (file.good())
{
auto data = std::vector<uint8_t>((std::istreambuf_iterator<char>(file)),
std::istreambuf_iterator<char>());
size_t unmodified_params = params.size() - 1; // non-negative due to the file parameter
std::vector<std::string> modified_params(unmodified_params + data.size());
if (unmodified_params) // copy leading parameters
std::copy(modified_params.begin(), modified_params.begin() + unmodified_params, params.begin());
std::transform(data.begin(), data.end(), modified_params.begin() + unmodified_params, [](uint8_t c) { return rsutils::string::hexify(c); });
params = modified_params; // substitute original params with modified data
}
}
inline void parse_xml_from_memory(const char * content, commands_xml& cmd_xml)
{
auto doc = std::make_shared<rapidxml::xml_document<>>();
doc->parse<0>(doc->allocate_string(content));
auto node = doc->first_node("Commands");
if (!node)
throw std::logic_error("Invalid XML file - expecting Commands node to be present");
for (auto NodeI = node->first_node(); NodeI; NodeI = NodeI->next_sibling())
{
if (!strcmp(NodeI->name(), "Command"))
{
command_from_xml cmd;
for (auto AttI = NodeI->first_attribute(); AttI; AttI = AttI->next_attribute())
{
std::string value = AttI->value();
std::string att_name = AttI->name();
if (att_name == "Name") { cmd.name = value; }
else if (att_name == "Opcode") { cmd.op_code = rsutils::string::ascii_hex_string_to_uint(value); }
else if (att_name == "IsWriteOnly") { cmd.is_write_only = rsutils::string::string_to_bool(value); }
else if (att_name == "ReadFormat") { cmd.read_format = value; }
else if (att_name == "IsReadCommand") { cmd.is_read_command = rsutils::string::string_to_bool(value); }
else if (att_name == "CmdPermission") { cmd.cmd_permission = value; }
else if (att_name == "TimeOut") { cmd.time_out = stoi(value); }
else if (att_name == "Description") { cmd.description = value; }
else if (att_name == "CmdInterface") { cmd.cmd_interface = value; }
else if (att_name == "CmdPipe") { cmd.cmd_pipe = value; }
else if (att_name == "I2cRegOffset") { cmd.i2c_reg_offset = value; }
else if (att_name == "I2cCmdType") { cmd.i2c_cmd_type = value; }
}
for (auto SubNodeI = NodeI->first_node(); SubNodeI; SubNodeI = SubNodeI->next_sibling()) // Add commands
{
std::string str_name = SubNodeI->name();
if (str_name.find("Parameter") != std::string::npos)
{
parameter param;
++cmd.num_of_parameters;
for (auto paramAtt = SubNodeI->first_attribute(); paramAtt; paramAtt = paramAtt->next_attribute())
{
std::string value = paramAtt->value();
std::string att_name = paramAtt->name();
if (att_name == "Name") { param.name = value; }
else if (att_name == "IsDecimal") { param.is_decimal = rsutils::string::string_to_bool(value); }
}
cmd.parameters.push_back(param);
}
else if (str_name == "Data")
{
parameter param;
param.name = "Data";
cmd.is_cmd_write_data = true;
for (auto dataAtt = SubNodeI->first_attribute(); dataAtt; dataAtt = dataAtt->next_attribute())
{
std::string value = dataAtt->value();
std::string data_att_name = dataAtt->name();
if (data_att_name == "Name") { param.name = value; }
else if (data_att_name == "IsReverseBytes") { param.is_reverse_bytes = rsutils::string::string_to_bool(value); }
else if (data_att_name == "FormatLength") { param.format_length = stoi(value); }
}
cmd.parameters.push_back(param);
}
else if (str_name == "ReadData")
{
for (auto sectionNode = SubNodeI->first_node(); sectionNode; sectionNode = sectionNode->next_sibling()) // Add CMD Parameters
{
section sec;
for (auto sectionAtt = sectionNode->first_attribute(); sectionAtt; sectionAtt = sectionAtt->next_attribute())
{
std::string value = sectionAtt->value();
std::string section_att_name = sectionAtt->name();
if (section_att_name == "Name") { sec.name = value; }
else if (section_att_name == "Title") { sec.title = value; }
else if (section_att_name == "Offset") { sec.offset = stoi(value); }
else if (section_att_name == "Size") { sec.size = stoi(value); }
else if (section_att_name == "FormatType") { sec.format_type = value; }
}
cmd.read_data.sections.push_back(sec);
}
}
}
cmd_xml.commands.insert(std::pair<std::string, command_from_xml>(rsutils::string::to_lower(cmd.name), cmd));
}
else if (!strcmp(NodeI->name(), "CustomFormatter"))
{
custom_formatter customFormatter;
for (auto AttI = NodeI->first_attribute(); AttI; AttI = AttI->next_attribute())
{
std::string value = AttI->value();
std::string atti_name = AttI->name();
if (atti_name == "KeySize") { customFormatter.key_size = value; }
else if (atti_name == "Name") { customFormatter.name = value; }
}
for (auto SubNodeI = NodeI->first_node(); SubNodeI; SubNodeI = SubNodeI->next_sibling()) // Add Kvp
{
std::string sub_nodei_name = SubNodeI->name();
if (sub_nodei_name.find("KVP") != std::string::npos)
{
kvp kvp;
for (auto paramAtt = SubNodeI->first_attribute(); paramAtt; paramAtt = paramAtt->next_attribute())
{
std::string value = paramAtt->value();
std::string param_att_name = paramAtt->name();
if (param_att_name == "Key") { kvp.key = value; }
else if (param_att_name == "Value") { kvp.value = value; }
}
customFormatter.kv.push_back(kvp);
}
}
cmd_xml.custom_formatters.insert(std::pair<std::string, custom_formatter>(rsutils::string::to_lower(customFormatter.name), customFormatter));
}
}
}
inline bool parse_xml_from_file(const std::string& xml_full_file_path, commands_xml& cmd_xml)
{
std::ifstream fin(xml_full_file_path);
if (!fin.good())
return false;
std::stringstream ss;
ss << fin.rdbuf();
auto xml = ss.str();
parse_xml_from_memory(xml.c_str(), cmd_xml);
return true;
}
inline void check_section_size(unsigned section_size, unsigned struct_size, const std::string& section_name, const std::string& struct_name)
{
std::string exception_str("Size of section %s is bigger than %s struct.");
if (section_size > struct_size)
{
auto msg = "Size of section " + section_name + " is bigger than " + struct_name + " struct!";
throw std::runtime_error(msg);
}
}
inline void update_format_type_to_lambda(std::map<std::string, xml_parser_function>& format_type_to_lambda)
{
format_type_to_lambda.insert(std::make_pair("ChangeSetVersion", [](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(ChangeSetVersion), sec.name.c_str(), "ChangeSetVersion");
auto changeSetVersion = reinterpret_cast<const ChangeSetVersion*>(data_offset + sec.offset);
tempStr << static_cast<int>(changeSetVersion->Version_Major) <<
((sec.size >= 2) ? ("." + std::to_string(static_cast<int>(changeSetVersion->Version_Minor))) : "") <<
((sec.size >= 3) ? ("." + std::to_string(static_cast<int>(changeSetVersion->Version_Number))) : "") <<
((sec.size >= 4) ? ("." + std::to_string(static_cast<int>(changeSetVersion->Version_Revision))) : "") <<
((sec.size >= 5) ? (" (" + std::to_string(changeSetVersion->Version_spare)) + ")" : "");
}));
format_type_to_lambda.insert(std::make_pair("MajorMinorVersion", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(MajorMinorVersion), sec.name.c_str(), "MajorMinorVersion");
auto majorMinorVersion = reinterpret_cast<const MajorMinorVersion*>(data_offset + sec.offset);;
tempStr << static_cast<int>(majorMinorVersion->Version_Major) <<
((sec.size >= 2) ? ("." + std::to_string(static_cast<int>(majorMinorVersion->Version_Minor))) : "");
}));
format_type_to_lambda.insert(std::make_pair("HexByte", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(HexByte), sec.name.c_str(), "HexByte");
auto hexByte = reinterpret_cast<const HexByte*>(data_offset + sec.offset);
tempStr << rsutils::string::hexify(hexByte->Version4);
}));
format_type_to_lambda.insert(std::make_pair("LiguriaVersion", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(LiguriaVersion), sec.name.c_str(), "LiguriaVersion");
auto liguriaVersion = reinterpret_cast<const LiguriaVersion*>(data_offset + sec.offset);
tempStr << static_cast<int>(liguriaVersion->Version1) <<
((sec.size >= 2) ? ("." + std::to_string(static_cast<int>(liguriaVersion->Version2))) : "");
}));
format_type_to_lambda.insert(std::make_pair("Bool", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(Bool), sec.name.c_str(), "Bool");
auto BooL = reinterpret_cast<const Bool*>(data_offset + sec.offset);
tempStr << ((static_cast<int>(BooL->sts)) ? "TRUE" : "FALSE");
}));
format_type_to_lambda.insert(std::make_pair("HwTypeNumber", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(HwTypeNumber), sec.name.c_str(), "HwTypeNumber");
auto hwTypeNumber = reinterpret_cast<const HwTypeNumber*>(data_offset + sec.offset);
tempStr << static_cast<int>(hwTypeNumber->num);
}));
format_type_to_lambda.insert(std::make_pair("Ascii", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(Ascii), sec.name.c_str(), "Ascii");
auto ascii = reinterpret_cast<const Ascii*>(data_offset + sec.offset);
auto temp = new char[sec.size + 1];
memcpy(temp, ascii->value, sec.size);
temp[sec.size] = '\0';
tempStr << temp;
delete[] temp;
}));
format_type_to_lambda.insert(std::make_pair("DecByte", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(DecByte), sec.name.c_str(), "DecByte");
auto decByte = reinterpret_cast<const DecByte*>(data_offset + sec.offset);
tempStr << static_cast<int>(decByte->version);
}));
format_type_to_lambda.insert(std::make_pair("HexNumber", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(HexNumber), sec.name.c_str(), "HexNumber");
auto hexNumber = reinterpret_cast<const HexNumber*>(data_offset + sec.offset);
tempStr << rsutils::string::hexify(hexNumber->number1) <<
((sec.size >= 2) ? rsutils::string::hexify(hexNumber->number2) : "") <<
((sec.size >= 3) ? rsutils::string::hexify(hexNumber->number3) : "") <<
((sec.size >= 4) ? rsutils::string::hexify(hexNumber->number4) : "");
}));
format_type_to_lambda.insert(std::make_pair("HexNumberTwoBytes", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(HexNumber), sec.name.c_str(), "HexNumber");
auto hexNumber = reinterpret_cast<const HexNumber*>(data_offset + sec.offset);
tempStr << rsutils::string::hexify(hexNumber->number2) <<
((sec.size >= 2) ? rsutils::string::hexify(hexNumber->number1) : "");
}));
format_type_to_lambda.insert(std::make_pair("HexNumberReversed", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(HexNumberReversed), sec.name.c_str(), "HexNumberReversed");
auto hexNumberReversed = reinterpret_cast<const HexNumberReversed*>(data_offset + sec.offset);
tempStr << rsutils::string::hexify(hexNumberReversed->number4) <<
((sec.size >= 2) ? rsutils::string::hexify(hexNumberReversed->number3) : "") <<
((sec.size >= 3) ? rsutils::string::hexify(hexNumberReversed->number2) : "") <<
((sec.size >= 4) ? rsutils::string::hexify(hexNumberReversed->number1) : "");
}));
format_type_to_lambda.insert(std::make_pair("BarCodeSerial12Char", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(BarCodeSerial12Char), sec.name.c_str(), "BarCodeSerial12Char");
auto barCodeSerial12Char = reinterpret_cast<const BarCodeSerial12Char*>(data_offset + sec.offset);
tempStr << rsutils::string::hexify(barCodeSerial12Char->number1) <<
((sec.size >= 2) ? rsutils::string::hexify(barCodeSerial12Char->number2) : "") <<
((sec.size >= 3) ? rsutils::string::hexify(barCodeSerial12Char->number3) : "") <<
((sec.size >= 4) ? rsutils::string::hexify(barCodeSerial12Char->number4) : "") <<
((sec.size >= 5) ? rsutils::string::hexify(barCodeSerial12Char->number5) : "") <<
((sec.size >= 6) ? rsutils::string::hexify(barCodeSerial12Char->number6) : "") <<
((sec.size >= 7) ? rsutils::string::hexify(barCodeSerial12Char->number7) : "") <<
((sec.size >= 8) ? rsutils::string::hexify(barCodeSerial12Char->number8) : "");
}));
format_type_to_lambda.insert(std::make_pair("WideMajorMinorVersion", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(WideMajorMinorVersion), sec.name.c_str(), "WideMajorMinorVersion");
auto wideMajorMinorVersion = reinterpret_cast<const WideMajorMinorVersion*>(data_offset + sec.offset);
tempStr << static_cast<int>(wideMajorMinorVersion->Version_Minor) <<
((sec.size >= 2) ? ("." + std::to_string(static_cast<int>(wideMajorMinorVersion->Version_Major))) : "");
}));
format_type_to_lambda.insert(std::make_pair("Double", [&](const uint8_t* data_offset, const section& sec, std::stringstream& tempStr) {
check_section_size(sec.size, sizeof(DoubleNumber), sec.name.c_str(), "DoubleNumber");
auto number = reinterpret_cast<const DoubleNumber*>(data_offset + sec.offset);
tempStr << std::setprecision(10) << number->number;
}));
}
inline void update_sections_data(const uint8_t* data_offset, std::vector<section>& sections, const std::map<std::string, custom_formatter>& custom_formatters, const std::map<std::string, xml_parser_function>& format_type_to_lambda)
{
for (auto& sec : sections)
{
std::stringstream tempStr;
auto pair = format_type_to_lambda.find(sec.format_type);
if (pair != format_type_to_lambda.end())
{
pair->second(data_offset, sec, tempStr);
}
else
{
// FormatType not found. searching in the custom format list
auto it = custom_formatters.find(rsutils::string::to_lower(sec.format_type));
if (it != custom_formatters.end())
{
if (it->second.key_size == "Byte")
{
auto key = uint8_t(*(data_offset + sec.offset));
for (auto& elem : it->second.kv)
{
auto keyStr = std::to_string(int(key));
if (elem.key == keyStr)
{
tempStr << elem.value;
break;
}
}
}
}
}
std::vector<uint8_t> raw_data;
if (sec.size == 0)
throw std::runtime_error(std::string("Size of section " + sec.name + " is 0!").c_str());
raw_data.resize(sec.size);
memcpy(raw_data.data(), data_offset + sec.offset, sec.size);
sec.data = tempStr.str();
}
}
inline void decode_string_from_raw_data(const command_from_xml& command, const std::map<std::string, custom_formatter>& custom_formatters, const uint8_t* raw_data_offset, size_t data_size, std::string& output, const std::map<std::string, xml_parser_function>& format_type_to_lambda)
{
auto data_offset = raw_data_offset + 4;
data_size -= 4;
if (data_size == 0)
throw std::runtime_error("Raw data is empty!");
std::stringstream ss_output;
ss_output.str("");
auto num_of_bytes_for_space = 1;
auto num_of_bytes_for_new_line = 16;
auto read_format = command.read_format;
if (read_format == "Bytes")
num_of_bytes_for_space = 1;
else if (read_format == "Words")
num_of_bytes_for_space = 2;
else if (read_format == "Doubles")
num_of_bytes_for_space = 4;
if (command.read_data.sections.empty())
{
std::vector<std::string> buffer;
auto bytes = 0;
auto bytes_per_line = 0;
auto start_address = "0";
std::string curr_address = start_address;
std::stringstream dec_to_hex;
auto end_address = std::stoi(start_address) + data_size;
auto num_of_zeros = 1;
if (curr_address.size() == 1)
{
auto temp_curr_address = curr_address;
auto temp_end_address = end_address;
auto temp_bytes_per_line = bytes_per_line;
for (size_t offset = 0; offset < data_size; ++offset)
{
++temp_bytes_per_line;
if (temp_bytes_per_line == num_of_bytes_for_new_line)
{
unsigned int next_add = stoi(temp_curr_address) + num_of_bytes_for_new_line;
if (next_add >= temp_end_address)
break;
dec_to_hex.str("");
dec_to_hex << std::hex << next_add;
temp_curr_address = dec_to_hex.str();
if (temp_curr_address.size() == 1)
temp_curr_address.insert(0, "0");
temp_curr_address = std::to_string(next_add);
temp_bytes_per_line = 0;
}
}
num_of_zeros = int(dec_to_hex.str().length());
ss_output << "Offset: 0x";
dec_to_hex.str("");
for (auto i = 1; i < num_of_zeros; ++i)
{
ss_output << "0";
}
}
else
ss_output << "Offset: 0x";
ss_output << std::hex << stoi(curr_address) << " => ";
for (size_t offset = 0; offset < data_size; ++offset)
{
++bytes_per_line;
++bytes;
buffer.push_back(rsutils::string::hexify(static_cast<unsigned char>(*(data_offset + offset))));
if (bytes == num_of_bytes_for_space)
{
bytes = 0;
reverse(buffer.begin(), buffer.end());
for (auto str : buffer)
ss_output << str;
buffer.clear();
if (bytes_per_line == num_of_bytes_for_new_line)
{
unsigned int next_add = stoi(curr_address) + num_of_bytes_for_new_line;
if (next_add >= end_address)
break;
dec_to_hex.str("");
dec_to_hex << std::hex << next_add;
curr_address = dec_to_hex.str();
auto putZeros = num_of_zeros - int(curr_address.size());
ss_output << "\nOffset: 0x";
for (auto i = 0; i < putZeros; ++i)
{
ss_output << "0";
}
ss_output << curr_address << " => ";
curr_address = std::to_string(next_add);
bytes_per_line = 0;
}
else
{
if ((offset + 1) < data_size)
ss_output << " ";
}
}
}
}
else
{
auto sections = command.read_data.sections;
update_sections_data(data_offset, sections, custom_formatters, format_type_to_lambda);
unsigned max_line_len = 0;
for (auto& elem : sections)
max_line_len = ((elem.name.size() > max_line_len) ? unsigned(elem.name.size()) : max_line_len);
const int spaces = 3; // number of spaces between section name to section data
for (auto& elem : sections)
ss_output << elem.name << ":" << std::setw((max_line_len + spaces) - elem.name.size() + elem.data.length()) << std::right << elem.data << std::endl;
}
output = ss_output.str();
}
inline void encode_raw_data_command(const command_from_xml& xml_cmd_info, const std::vector<parameter>& params, std::vector<uint8_t>& raw_data)
{
auto cmd_op_code = xml_cmd_info.op_code;
auto is_cmd_writes_data = xml_cmd_info.is_cmd_write_data;
auto parameters = params;
auto num_of_required_parameters = xml_cmd_info.num_of_parameters + ((xml_cmd_info.is_cmd_write_data) ? 1 : 0);
if (int(params.size()) < num_of_required_parameters)
throw std::runtime_error("Number of given parameters is less than required!"); // TODO: consider to print the command info
auto format_length = Byte;
if (is_cmd_writes_data)
format_length = ((params[xml_cmd_info.num_of_parameters].format_length == -1) ? format_length : static_cast<FormatSize>(params[xml_cmd_info.num_of_parameters].format_length));
const uint16_t pre_header_data = 0xcdab; // magic number
raw_data.resize(HW_MONITOR_BUFFER_SIZE); // TODO: resize std::vector to the right size
auto write_ptr = raw_data.data();
auto header_size = 4;
auto cur_index = 2;
*reinterpret_cast<uint16_t *>(write_ptr + cur_index) = pre_header_data;
cur_index += sizeof(uint16_t);
*reinterpret_cast<unsigned int *>(write_ptr + cur_index) = cmd_op_code;
cur_index += sizeof(unsigned int);
// Parameters
for (auto param_index = 0; param_index < MAX_PARAMS; ++param_index)
{
if (param_index < xml_cmd_info.num_of_parameters)
{
unsigned decimal;
std::stringstream ss;
ss << params[param_index].data;
ss >> std::hex >> decimal;
*reinterpret_cast<unsigned*>(write_ptr + cur_index) = decimal;
cur_index += sizeof(unsigned);
}
else
{
*reinterpret_cast<unsigned *>(write_ptr + cur_index) = 0;
cur_index += sizeof(unsigned);
}
}
// Data
if (is_cmd_writes_data)
{
for (auto j = xml_cmd_info.num_of_parameters; j < int(params.size()); ++j)
{
unsigned decimal;
std::stringstream ss;
ss << params[j].data;
ss >> std::hex >> decimal;
switch (format_length)
{
case Byte:
*reinterpret_cast<uint8_t*>(write_ptr + cur_index) = static_cast<uint8_t>(decimal);
cur_index += sizeof(uint8_t);
break;
case Word:
*reinterpret_cast<short *>(write_ptr + cur_index) = static_cast<short>(decimal);
cur_index += sizeof(short);
break;
case Double:
*reinterpret_cast<unsigned *>(write_ptr + cur_index) = static_cast<unsigned>(decimal);
cur_index += sizeof(unsigned);
break;
default:
*reinterpret_cast<uint8_t*>(write_ptr + cur_index) = static_cast<uint8_t>(decimal);
cur_index += sizeof(uint8_t);
break;
}
}
}
*reinterpret_cast<uint16_t*>(raw_data.data()) = static_cast<uint16_t>(cur_index - header_size);// Length doesn't include hdr.
raw_data.resize(cur_index); // TODO:
}