From 5470dd9c98eed8ffc636632c761fd75c28b3dd97 Mon Sep 17 00:00:00 2001 From: Peter Lakatos Date: Fri, 2 Jul 2021 21:50:28 +0200 Subject: [PATCH 1/5] started working on automatic interpretation of descriptors --- DefinedStructs/ConstDataHolder.hpp | 5 ++ DefinedStructs/DescriptorStruct.hpp | 59 +++++++++++++++++++++ Descriptors/Decs03.txt | 4 ++ Interpreters/ControlTransferInterpreter.cpp | 15 ++++++ Interpreters/ControlTransferInterpreter.hpp | 16 ++++++ Interpreters/InterpreterFactory.cpp | 17 ++++++ Models/AdditionalDataModel.cpp | 21 ++++++-- 7 files changed, 133 insertions(+), 4 deletions(-) create mode 100644 DefinedStructs/DescriptorStruct.hpp create mode 100644 Descriptors/Decs03.txt create mode 100644 Interpreters/ControlTransferInterpreter.cpp create mode 100644 Interpreters/ControlTransferInterpreter.hpp diff --git a/DefinedStructs/ConstDataHolder.hpp b/DefinedStructs/ConstDataHolder.hpp index d133aa9..f6bf2c0 100644 --- a/DefinedStructs/ConstDataHolder.hpp +++ b/DefinedStructs/ConstDataHolder.hpp @@ -4,6 +4,7 @@ #include "PacketExternStructs.hpp" #include #include +#include "DescriptorStruct.hpp" /// /// Class used for holding global variables and for converting data constants to string. @@ -54,6 +55,10 @@ class DataHolder /// Map that associate HeaderDataType to its color highlightion /// std::map DataColors; + /// + /// Vector holding all yet known descriptor structs + /// + std::vector> descriptors; private: DataHolder(); void FillDataColorsMap(); diff --git a/DefinedStructs/DescriptorStruct.hpp b/DefinedStructs/DescriptorStruct.hpp new file mode 100644 index 0000000..c9c25a4 --- /dev/null +++ b/DefinedStructs/DescriptorStruct.hpp @@ -0,0 +1,59 @@ +#ifndef DESCRIPTOR_STRUCT_HPP +#define DESCRIPTOR_STRUCT_HPP + +#include + +/// +/// FORWARD REFERENCES +/// Used in ControlTRansferInterpreter class, where we include AdditionalDataModel +/// along with TreeItem before using any of DescriptorStruct +/// +class AdditionalDataModel; +class TreeItem; + +/// +/// Abstract class representing 1 field in descriptor +/// +class AbstractDescriptorField +{ +public: + AbstractDescriptorField() {} + virtual ~AbstractDescriptorField() noexcept {} + virtual void FillUpField() = 0; +protected: +}; + +/// +/// Conrete class representing 1 field in descriptor +/// +/// type of concrete field (e.g. INT32, INT64, ...) +template +class DescriptorField : public AbstractDescriptorField +{ +public: + DescriptorField(T val) : value(val) {} + void FillUpField() override {} +private: + T value; +}; + +/// +/// Class representing concrete descriptor. +/// +class DescriptorStruct +{ +public: + DescriptorStruct(std::string fName, AdditionalDataModel* additionalDataModel) : filename(fName) {} + /// + /// Fill up concrete tree representing this descriptor + /// + /// + /// + void InterpretData(TreeItem* rootItem, const unsigned char* data) {} +private: + std::string filename; + std::vector> fields; +}; + +#endif // !DESCRIPTOR_STRUCT_HPP + diff --git a/Descriptors/Decs03.txt b/Descriptors/Decs03.txt new file mode 100644 index 0000000..d9a58b5 --- /dev/null +++ b/Descriptors/Decs03.txt @@ -0,0 +1,4 @@ +03 STRING DESCRIPTOR +1 bLength +1 bDescriptorType +.. wstring bString \ No newline at end of file diff --git a/Interpreters/ControlTransferInterpreter.cpp b/Interpreters/ControlTransferInterpreter.cpp new file mode 100644 index 0000000..67873f8 --- /dev/null +++ b/Interpreters/ControlTransferInterpreter.cpp @@ -0,0 +1,15 @@ +#include "ControlTransferInterpreter.hpp" + +ControlTransferInterpreter::ControlTransferInterpreter(TreeItem* rootItem, QTableWidgetItem* item, AdditionalDataModel* additionalDataModel) : + BaseInterpreter(rootItem, item, additionalDataModel) +{ + this->holder = DataHolder::GetDataHolder(); +} + +/// +/// Iterate through data and interpret known descriptors +/// +void ControlTransferInterpreter::Interpret() +{ + QByteArray data = item->data(holder->TRANSFER_LEFTOVER_DATA).toByteArray(); +} \ No newline at end of file diff --git a/Interpreters/ControlTransferInterpreter.hpp b/Interpreters/ControlTransferInterpreter.hpp new file mode 100644 index 0000000..48ca755 --- /dev/null +++ b/Interpreters/ControlTransferInterpreter.hpp @@ -0,0 +1,16 @@ +#ifndef CONTROLTRANSFERINTERPRETER_HPP +#define CONTROLTRANSFERINTERPRETER_HPP + +#include "BaseInterpreter.hpp" + +class ControlTransferInterpreter : public BaseInterpreter +{ +public: + ControlTransferInterpreter(TreeItem* rootItem, QTableWidgetItem* item, AdditionalDataModel* additionalDataModel); + + void Interpret() override; +private: + DataHolder* holder; +}; + +#endif // !CONTROLTRANSFERINTERPRETER_HPP diff --git a/Interpreters/InterpreterFactory.cpp b/Interpreters/InterpreterFactory.cpp index cb1578c..adcf001 100644 --- a/Interpreters/InterpreterFactory.cpp +++ b/Interpreters/InterpreterFactory.cpp @@ -22,6 +22,23 @@ InterpreterFactory::InterpreterFactory(TreeItem* rootItem, QTableWidgetItem* ite /// Pointer to appropriate interpreter BaseInterpreter* InterpreterFactory::GetInterpreter() { + PUSBPCAP_BUFFER_PACKET_HEADER usbh = (PUSBPCAP_BUFFER_PACKET_HEADER)item-> + data(DataHolder::GetDataHolder()->USBPCAP_HEADER_DATA).toByteArray().constData(); + UCHAR transferType = usbh->transfer; + switch (transferType) + { + case 1: //interrupt + { + return new InterruptTransferInterpreter(rootItem, item, additionalDataModel); + } + case 2: // control + { + + } + default: + break; + } + switch (dataType) { case INTERR_TRANSFER: diff --git a/Models/AdditionalDataModel.cpp b/Models/AdditionalDataModel.cpp index 8773202..37493c9 100644 --- a/Models/AdditionalDataModel.cpp +++ b/Models/AdditionalDataModel.cpp @@ -1,6 +1,7 @@ #include "AdditionalDataModel.hpp" -#include "../Interpreters/InterpreterFactory.hpp" +#include "../Interpreters/InterruptTransferInterpreter.hpp" +#include "../Interpreters/ControlTransferInterpreter.hpp" /// /// Constructor of AdditionaldataModel. @@ -56,10 +57,22 @@ QVariant AdditionalDataModel::headerData(int section, Qt::Orientation orientatio /// void AdditionalDataModel::SetupSpecifiedModelData() { - InterpreterFactory factory(rootItem.get(), item, this,dataType); - std::unique_ptr interpreter(factory.GetInterpreter()); - if (interpreter != nullptr) + PUSBPCAP_BUFFER_PACKET_HEADER usbh = (PUSBPCAP_BUFFER_PACKET_HEADER)item-> + data(DataHolder::GetDataHolder()->USBPCAP_HEADER_DATA).toByteArray().constData(); + UCHAR transferType = usbh->transfer; + switch (transferType) { + case 1: //interrupt + { + std::unique_ptr interpreter = std::make_unique(rootItem.get(), item, this); interpreter->Interpret(); } + case 2: // control + { + std::unique_ptr interpreter = std::make_unique(rootItem.get(), item, this); + interpreter->Interpret(); + } + default: + break; + } } \ No newline at end of file From 321b2eab83a69bcda91de5095099b1e3cdac7877 Mon Sep 17 00:00:00 2001 From: Peter Lakatos Date: Sun, 4 Jul 2021 18:38:08 +0200 Subject: [PATCH 2/5] started working on input processing and filling up concrete descriptors --- DefinedStructs/ConstDataHolder.cpp | 22 ++++++ DefinedStructs/ConstDataHolder.hpp | 9 ++- DefinedStructs/DescriptorStruct.cpp | 77 +++++++++++++++++++++ DefinedStructs/DescriptorStruct.hpp | 38 ++++++++-- Interpreters/ControlTransferInterpreter.cpp | 19 +++++ Interpreters/ControlTransferInterpreter.hpp | 4 ++ 6 files changed, 163 insertions(+), 6 deletions(-) create mode 100644 DefinedStructs/DescriptorStruct.cpp diff --git a/DefinedStructs/ConstDataHolder.cpp b/DefinedStructs/ConstDataHolder.cpp index 638e3ac..ecc0cee 100644 --- a/DefinedStructs/ConstDataHolder.cpp +++ b/DefinedStructs/ConstDataHolder.cpp @@ -26,6 +26,7 @@ DataHolder::DataHolder() TRANSFER_LEFTOVER_DATA = Qt::UserRole + 1; TRANSFER_OPTIONAL_HEADER = Qt::UserRole + 2; USBPCAP_HEADER_DATA = Qt::UserRole + 3; + DescriptorPath = "./Descriptors/"; } /// @@ -53,6 +54,27 @@ void DataHolder::FillDataColorsMap() DataColors.insert(std::pair(UNKNOWN_TRANSFER, { 0,0,255,255 })); } +/// +/// Tries to load new descriptor from file if description for given descriptor exists +/// +/// Type of descriptor we want to get +/// Pointer to loaded descriptor if exists, else nullptr +DescriptorStruct* DataHolder::TryLoadNewDescriptor(BYTE descType) +{ + std::stringstream stream(DescriptorPath); + stream << "Desc"; + stream << std::setw(2) << std::setfill('0') << descType; + stream << ".txt"; + + if (std::filesystem::exists(stream.str().c_str())) + { + descriptors.emplace_back(std::make_unique(stream.str().c_str(), descType)); + return descriptors[descriptors.size() - 1].get(); + } + + return nullptr; +} + /// /// Get string representation for USBPcap transfer. /// diff --git a/DefinedStructs/ConstDataHolder.hpp b/DefinedStructs/ConstDataHolder.hpp index f6bf2c0..59eebec 100644 --- a/DefinedStructs/ConstDataHolder.hpp +++ b/DefinedStructs/ConstDataHolder.hpp @@ -1,9 +1,12 @@ #ifndef CONSTDATAHOLDER_HPP #define CONSTDATAHOLDER_HPP -#include "PacketExternStructs.hpp" #include #include +#include +#include +#include +#include "PacketExternStructs.hpp" #include "DescriptorStruct.hpp" /// @@ -25,6 +28,8 @@ class DataHolder std::string GetUsage(const BYTE globalUsage, const BYTE value); std::string GetGenericDesktopUsage(const BYTE value); + DescriptorStruct* TryLoadNewDescriptor(BYTE descType); + /// /// Delete copy constructor due to Singleton pattern /// @@ -67,6 +72,8 @@ class DataHolder /// Instance of this class. /// static DataHolder* holder; + + std::string DescriptorPath; }; #endif // !CONSTDATAHOLDER_HPP \ No newline at end of file diff --git a/DefinedStructs/DescriptorStruct.cpp b/DefinedStructs/DescriptorStruct.cpp new file mode 100644 index 0000000..ac5566d --- /dev/null +++ b/DefinedStructs/DescriptorStruct.cpp @@ -0,0 +1,77 @@ +#include "DescriptorStruct.hpp" +#include + +/// +/// Fills up fields for this concrete descriptor struct +/// +void DescriptorStruct::FillUpFields() +{ + std::ifstream input; + input.open(filename); + std::string line; + //read first line to get descriptor type and name + if (input.good()) + { + if (std::getline(input, line)) + { + std::istringstream ss(line); + std::string bDescType; + ss >> bDescType; + if (std::stoi(bDescType) != descriptorType) + { + return; + } + std::string descName = ss.str(); + fields.emplace_back(std::make_unique>(descName)); + } + } + while (input.good()) + { + if (std::getline(input, line)) + { + //last added field has more detailed structure (on bit level of detail) + //with given range and values (representing more fields) so fill them up + if (line == "<") + { + fields[fields.size() - 1]->FillUpField(input); + } + else + { + std::istringstream ss(line); + std::string firstWord; + ss >> firstWord; + if (!std::isdigit(firstWord[0])) + { + //means input will be read by the end and has no fixed length (e.g. wstring in String Descriptor) + if (firstWord == "..") + { + std::string type; + ss >> type; + if (type == "wstring") + { + fields.emplace_back(std::make_unique>(ss.str())); + } + } + } + else + { + //according to length determine exact type + //currently supporting 2 most common - BYTE and USHORT + switch (std::stoi(firstWord)) + { + case 1: + { + fields.emplace_back(std::make_unique>(ss.str())); + } + case 2: + { + fields.emplace_back(std::make_unique>(ss.str())); + } + default: + break; + } + } + } + } + } +} \ No newline at end of file diff --git a/DefinedStructs/DescriptorStruct.hpp b/DefinedStructs/DescriptorStruct.hpp index c9c25a4..13f821c 100644 --- a/DefinedStructs/DescriptorStruct.hpp +++ b/DefinedStructs/DescriptorStruct.hpp @@ -2,10 +2,14 @@ #define DESCRIPTOR_STRUCT_HPP #include +#include +#include + +#include "PacketExternStructs.hpp" /// /// FORWARD REFERENCES -/// Used in ControlTRansferInterpreter class, where we include AdditionalDataModel +/// Used in ControlTransferInterpreter class, where we include AdditionalDataModel /// along with TreeItem before using any of DescriptorStruct /// class AdditionalDataModel; @@ -19,10 +23,29 @@ class AbstractDescriptorField public: AbstractDescriptorField() {} virtual ~AbstractDescriptorField() noexcept {} - virtual void FillUpField() = 0; + virtual void FillUpField(std::ifstream& input) = 0; protected: }; +/// +/// Structure representing one segment of field which has bit level details +/// +struct BitField +{ + /// + /// starting position of analyzing bits + /// + int start; + /// + /// size of analyzing bits + /// + int size; + /// + /// map holding descriptions to given values + /// + std::map descriptions; +}; + /// /// Conrete class representing 1 field in descriptor /// @@ -31,9 +54,11 @@ template class DescriptorField : public AbstractDescriptorField { public: - DescriptorField(T val) : value(val) {} - void FillUpField() override {} + DescriptorField(std::string descr) : description(descr) {} + void FillUpField(std::ifstream& input) override {} private: + std::string description; + std::vector bitFields; T value; }; @@ -43,14 +68,17 @@ class DescriptorField : public AbstractDescriptorField class DescriptorStruct { public: - DescriptorStruct(std::string fName, AdditionalDataModel* additionalDataModel) : filename(fName) {} + DescriptorStruct(std::string fName, BYTE dType) : filename(fName), descriptorType(dType) { FillUpFields(); } /// /// Fill up concrete tree representing this descriptor /// /// /// void InterpretData(TreeItem* rootItem, const unsigned char* data) {} + BYTE descriptorType; private: + void FillUpFields(); + std::string filename; std::vector> fields; }; diff --git a/Interpreters/ControlTransferInterpreter.cpp b/Interpreters/ControlTransferInterpreter.cpp index 67873f8..9e2e65e 100644 --- a/Interpreters/ControlTransferInterpreter.cpp +++ b/Interpreters/ControlTransferInterpreter.cpp @@ -12,4 +12,23 @@ ControlTransferInterpreter::ControlTransferInterpreter(TreeItem* rootItem, QTabl void ControlTransferInterpreter::Interpret() { QByteArray data = item->data(holder->TRANSFER_LEFTOVER_DATA).toByteArray(); + const char* packet = data.constData(); + BYTE descriptorSize = (BYTE)*packet; + BYTE descriptorType = (BYTE) * (packet++); + DescriptorStruct* descStruct = GetDescriptorStruct(descriptorType); +} + +DescriptorStruct* ControlTransferInterpreter::GetDescriptorStruct(BYTE descriptorType) +{ + auto predicate = [descriptorType](std::unique_ptr& desc) {return desc->descriptorType == descriptorType; }; + auto descStructIterator = std::find_if(holder->descriptors.begin(), holder->descriptors.end(), predicate); + if (descStructIterator == holder->descriptors.end()) + { + DescriptorStruct* descStruct = holder->TryLoadNewDescriptor(descriptorType); + return descStruct; + } + else + { + return descStructIterator->get(); + } } \ No newline at end of file diff --git a/Interpreters/ControlTransferInterpreter.hpp b/Interpreters/ControlTransferInterpreter.hpp index 48ca755..3c74a8c 100644 --- a/Interpreters/ControlTransferInterpreter.hpp +++ b/Interpreters/ControlTransferInterpreter.hpp @@ -3,6 +3,8 @@ #include "BaseInterpreter.hpp" +#include + class ControlTransferInterpreter : public BaseInterpreter { public: @@ -10,6 +12,8 @@ class ControlTransferInterpreter : public BaseInterpreter void Interpret() override; private: + DescriptorStruct* GetDescriptorStruct(BYTE descriptorType); + DataHolder* holder; }; From 048d76088bbec70bd5ea2361f0971ecca66f821c Mon Sep 17 00:00:00 2001 From: Peter Lakatos Date: Mon, 12 Jul 2021 11:26:25 +0200 Subject: [PATCH 3/5] finished filling up concrete descriptors, started working on interpreting its data --- DefinedStructs/DescriptorStruct.cpp | 12 +++++ DefinedStructs/DescriptorStruct.hpp | 51 ++++++++++++++++++++- Interpreters/ControlTransferInterpreter.cpp | 36 +++++++++++++++ Interpreters/ControlTransferInterpreter.hpp | 1 + Models/AdditionalDataModel.cpp | 2 + 5 files changed, 100 insertions(+), 2 deletions(-) diff --git a/DefinedStructs/DescriptorStruct.cpp b/DefinedStructs/DescriptorStruct.cpp index ac5566d..827e9d2 100644 --- a/DefinedStructs/DescriptorStruct.cpp +++ b/DefinedStructs/DescriptorStruct.cpp @@ -62,10 +62,12 @@ void DescriptorStruct::FillUpFields() case 1: { fields.emplace_back(std::make_unique>(ss.str())); + break; } case 2: { fields.emplace_back(std::make_unique>(ss.str())); + break; } default: break; @@ -74,4 +76,14 @@ void DescriptorStruct::FillUpFields() } } } +} + +/// +/// Interpret data according to concrete descriptor +/// +/// Root tree item of tree view. +/// Data to be interpreted +void DescriptorStruct::InterpretData(TreeItem* rootItem, const unsigned char* data) +{ + } \ No newline at end of file diff --git a/DefinedStructs/DescriptorStruct.hpp b/DefinedStructs/DescriptorStruct.hpp index 13f821c..504b8d5 100644 --- a/DefinedStructs/DescriptorStruct.hpp +++ b/DefinedStructs/DescriptorStruct.hpp @@ -4,6 +4,7 @@ #include #include #include +#include #include "PacketExternStructs.hpp" @@ -55,13 +56,59 @@ class DescriptorField : public AbstractDescriptorField { public: DescriptorField(std::string descr) : description(descr) {} - void FillUpField(std::ifstream& input) override {} + void FillUpField(std::ifstream& input) override; private: std::string description; std::vector bitFields; T value; }; +/// +/// fill up one concrete fields along with its bit defined fields +/// +/// Type of descriptor field +/// input stream +template +void DescriptorField::FillUpField(std::ifstream& input) +{ + while (input.good()) + { + std::string line; + if (std::getline(input, line)) + { + //end of the whole field + if (line == ">") + { + return; + } + std::istringstream ss(line); + BitField b; + ss >> b.start; + ss.get(); //separator + ss >> b.size; + char separator = input.get(); + if (input.good() && separator == '{') + { + while (input.good()) + { + if (std::getline(input, line)) + { + //end of bit field + if (line == "}") + { + return; + } + //else fill up one bit field with value - description pairs + ss = std::istringstream(line); + int value = ss.get(); + b.descriptions[value] = ss.str(); + } + } + } + } + } +} + /// /// Class representing concrete descriptor. /// @@ -74,7 +121,7 @@ class DescriptorStruct /// /// /// - void InterpretData(TreeItem* rootItem, const unsigned char* data) {} + void InterpretData(TreeItem* rootItem, const unsigned char* data); BYTE descriptorType; private: void FillUpFields(); diff --git a/Interpreters/ControlTransferInterpreter.cpp b/Interpreters/ControlTransferInterpreter.cpp index 9e2e65e..d055cfa 100644 --- a/Interpreters/ControlTransferInterpreter.cpp +++ b/Interpreters/ControlTransferInterpreter.cpp @@ -1,5 +1,6 @@ #include "ControlTransferInterpreter.hpp" + ControlTransferInterpreter::ControlTransferInterpreter(TreeItem* rootItem, QTableWidgetItem* item, AdditionalDataModel* additionalDataModel) : BaseInterpreter(rootItem, item, additionalDataModel) { @@ -16,8 +17,21 @@ void ControlTransferInterpreter::Interpret() BYTE descriptorSize = (BYTE)*packet; BYTE descriptorType = (BYTE) * (packet++); DescriptorStruct* descStruct = GetDescriptorStruct(descriptorType); + if (descStruct == nullptr) + { + InterpretUnknownDescriptor((const unsigned char*)packet); + } + else + { + descStruct->InterpretData(rootItem, (const unsigned char*)packet); + } } +/// +/// Gets struct that represents given descriptor. If it doesnt exists yet, try to load it +/// +/// Type of descriptor we want to get struct of +/// DescriptorStruct* ControlTransferInterpreter::GetDescriptorStruct(BYTE descriptorType) { auto predicate = [descriptorType](std::unique_ptr& desc) {return desc->descriptorType == descriptorType; }; @@ -31,4 +45,26 @@ DescriptorStruct* ControlTransferInterpreter::GetDescriptorStruct(BYTE descripto { return descStructIterator->get(); } +} + +/// +/// Inteprets unknown descriptor +/// +/// Pointer to descriptor data +void ControlTransferInterpreter::InterpretUnknownDescriptor(const unsigned char* packet) +{ + rootItem->AppendChild(new TreeItem(QVector{"UNKNOWN_DESCRIPTOR", "", ""}, rootItem)); + TreeItem* unknownDescriptorChild = rootItem->Child(rootItem->ChildCount() - 1); + BYTE descriptorSize = (*packet); + + QString hexData; + additionalDataModel->CharToHexConvert(&packet, 1, hexData); + unknownDescriptorChild->AppendChild(new TreeItem(QVector{hexData, "bLength", descriptorSize}, unknownDescriptorChild)); + + BYTE descriptorType = (*packet); + additionalDataModel->CharToHexConvert(&packet, 1, hexData); + unknownDescriptorChild->AppendChild(new TreeItem(QVector{hexData, "bDescriptorType", descriptorType}, unknownDescriptorChild)); + + additionalDataModel->CharToHexConvert(&packet, descriptorSize - 1, hexData); // -1 for descriptorType + unknownDescriptorChild->AppendChild(new TreeItem(QVector{hexData, "unspecified"}, unknownDescriptorChild)); } \ No newline at end of file diff --git a/Interpreters/ControlTransferInterpreter.hpp b/Interpreters/ControlTransferInterpreter.hpp index 3c74a8c..b0cd112 100644 --- a/Interpreters/ControlTransferInterpreter.hpp +++ b/Interpreters/ControlTransferInterpreter.hpp @@ -13,6 +13,7 @@ class ControlTransferInterpreter : public BaseInterpreter void Interpret() override; private: DescriptorStruct* GetDescriptorStruct(BYTE descriptorType); + void InterpretUnknownDescriptor(const unsigned char* packet); DataHolder* holder; }; diff --git a/Models/AdditionalDataModel.cpp b/Models/AdditionalDataModel.cpp index 37493c9..2107734 100644 --- a/Models/AdditionalDataModel.cpp +++ b/Models/AdditionalDataModel.cpp @@ -66,11 +66,13 @@ void AdditionalDataModel::SetupSpecifiedModelData() { std::unique_ptr interpreter = std::make_unique(rootItem.get(), item, this); interpreter->Interpret(); + break; } case 2: // control { std::unique_ptr interpreter = std::make_unique(rootItem.get(), item, this); interpreter->Interpret(); + break; } default: break; From 0a08aedfd3b363ca98735b8b97461f4897ab538b Mon Sep 17 00:00:00 2001 From: Peter Lakatos Date: Tue, 20 Jul 2021 19:35:04 +0200 Subject: [PATCH 4/5] continue works on automated descriptor interpretation --- DefinedStructs/ConstDataHolder.cpp | 2 + DefinedStructs/ConstDataHolder.hpp | 3 +- DefinedStructs/DescriptorStruct.cpp | 15 +++- DefinedStructs/DescriptorStruct.hpp | 96 ++++++++++++++++++--- Interpreters/ControlTransferInterpreter.cpp | 4 +- 5 files changed, 103 insertions(+), 17 deletions(-) diff --git a/DefinedStructs/ConstDataHolder.cpp b/DefinedStructs/ConstDataHolder.cpp index ecc0cee..3eb0934 100644 --- a/DefinedStructs/ConstDataHolder.cpp +++ b/DefinedStructs/ConstDataHolder.cpp @@ -1,4 +1,6 @@ #include "ConstDataHolder.hpp" +#include "DescriptorStruct.hpp" + DataHolder* DataHolder::holder = nullptr; diff --git a/DefinedStructs/ConstDataHolder.hpp b/DefinedStructs/ConstDataHolder.hpp index 59eebec..ba445d9 100644 --- a/DefinedStructs/ConstDataHolder.hpp +++ b/DefinedStructs/ConstDataHolder.hpp @@ -7,7 +7,8 @@ #include #include #include "PacketExternStructs.hpp" -#include "DescriptorStruct.hpp" + +class DescriptorStruct; /// /// Class used for holding global variables and for converting data constants to string. diff --git a/DefinedStructs/DescriptorStruct.cpp b/DefinedStructs/DescriptorStruct.cpp index 827e9d2..36ae2a6 100644 --- a/DefinedStructs/DescriptorStruct.cpp +++ b/DefinedStructs/DescriptorStruct.cpp @@ -1,6 +1,7 @@ #include "DescriptorStruct.hpp" #include + /// /// Fills up fields for this concrete descriptor struct /// @@ -81,9 +82,17 @@ void DescriptorStruct::FillUpFields() /// /// Interpret data according to concrete descriptor /// -/// Root tree item of tree view. +/// Root tree item of tree view /// Data to be interpreted -void DescriptorStruct::InterpretData(TreeItem* rootItem, const unsigned char* data) +/// Pointer to AdditionalDataModel +void DescriptorStruct::InterpretData(TreeItem* rootItem, const QByteArray& data, AdditionalDataModel* additionalDataModel) { - + const char* packet = data.constData(); + std::size_t dataLeft = data.size(); + for (int i = 0; i < fields.size(); i++) + { + std::size_t value = fields[i]->InterpretField(rootItem, (const unsigned char*)packet, dataLeft, additionalDataModel); + packet += value; + dataLeft -= value; + } } \ No newline at end of file diff --git a/DefinedStructs/DescriptorStruct.hpp b/DefinedStructs/DescriptorStruct.hpp index 504b8d5..7b6d89d 100644 --- a/DefinedStructs/DescriptorStruct.hpp +++ b/DefinedStructs/DescriptorStruct.hpp @@ -5,16 +5,12 @@ #include #include #include +#include +#include +#include #include "PacketExternStructs.hpp" - -/// -/// FORWARD REFERENCES -/// Used in ControlTransferInterpreter class, where we include AdditionalDataModel -/// along with TreeItem before using any of DescriptorStruct -/// -class AdditionalDataModel; -class TreeItem; +#include "../Models/AdditionalDataModel.hpp" /// /// Abstract class representing 1 field in descriptor @@ -25,7 +21,8 @@ class AbstractDescriptorField AbstractDescriptorField() {} virtual ~AbstractDescriptorField() noexcept {} virtual void FillUpField(std::ifstream& input) = 0; -protected: + virtual std::size_t InterpretField(TreeItem* rootItem, const unsigned char* data, std::size_t size, + AdditionalDataModel* additionalDataModel) = 0; }; /// @@ -55,9 +52,22 @@ template class DescriptorField : public AbstractDescriptorField { public: - DescriptorField(std::string descr) : description(descr) {} + DescriptorField(std::string descr) : description(descr), value() {} void FillUpField(std::ifstream& input) override; + std::size_t InterpretField(TreeItem* rootItem, const unsigned char* data, std::size_t sizeLeft, + AdditionalDataModel* additionalDataModel) override; private: + void CharToNumberConvert(const unsigned char* addr) + { + value = 0; + for (int i = sizeof(T); i > 0; i--) + { + value = (value << 8) | addr[i - 1]; + } + } + + T GetBitFieldValue(BitField& field); + std::string description; std::vector bitFields; T value; @@ -109,6 +119,70 @@ void DescriptorField::FillUpField(std::ifstream& input) } } +/// +/// Interpret concrete field (and its possible bit fields) +/// +/// Type of descriptor field +/// Root tree item of tree view +/// Starting point of data to be interpreted +/// Size of data that are still valid and has not been proccessed yet +/// Pointer to AdditionalDataModel instance +/// Size of data that were interpreted +template +std::size_t DescriptorField::InterpretField(TreeItem* rootItem, const unsigned char* data, std::size_t sizeLeft, + AdditionalDataModel* additionalDataModel) +{ + QString hexData; + //wstring ... proccess all left data + if (std::is_same_v) + { + additionalDataModel->CharToHexConvert(&data, sizeLeft, hexData); + std::wstring wString(data, data + sizeLeft); + std::string bString(wString.begin(), wString.end()); + rootItem->AppendChild(new TreeItem(QVector{hexData, description.c_str(), bString.c_str()}, rootItem)); + return sizeLeft; + } + + //some other data type + //convert char* to number and fill value data field + CharToNumberConvert(data); + additionalDataModel->CharToHexConvert(&data, sizeof(T), hexData); + rootItem->AppendChild(new TreeItem(QVector{hexData, description.c_str(), value}, rootItem)); + + //check if it carries some bit defined information + //if not, return proccessed size + if (bitFields.empty()) + { + return sizeof(T); + } + //else go through bitFields and interpret them + TreeItem* bitFieldParent = rootItem->Child(rootItem->ChildCount() - 1); + for (std::size_t i = 0; i < bitFields.size(); i++) + { + T bitValue = GetBitFieldValue(bitFields[i]); + auto fieldDesc = bitFields[i].descriptions[bitValue]; + bitFieldParent->AppendChild(new TreeItem(QVector{ + additionalDataModel->ShowBits(bitFields[i].start, bitFields[i].size, value), + fieldDesc.c_str(), bitValue}, bitFieldParent)); + } +} + +/// +/// Get value of given bit-field +/// +/// Type of descriptor field +/// Concrete field +/// Value of given bit-field +template +T DescriptorField::GetBitFieldValue(BitField& field) +{ + T bitmask = (1 << field.size) - 1; + bitmask = bitmask << field.start; + T bitValue = (value & bitmask) >> field.start; + + return bitValue; +} + /// /// Class representing concrete descriptor. /// @@ -121,7 +195,7 @@ class DescriptorStruct /// /// /// - void InterpretData(TreeItem* rootItem, const unsigned char* data); + void InterpretData(TreeItem* rootItem, const QByteArray& data, AdditionalDataModel* additionalDataModel); BYTE descriptorType; private: void FillUpFields(); diff --git a/Interpreters/ControlTransferInterpreter.cpp b/Interpreters/ControlTransferInterpreter.cpp index d055cfa..b80551f 100644 --- a/Interpreters/ControlTransferInterpreter.cpp +++ b/Interpreters/ControlTransferInterpreter.cpp @@ -1,4 +1,5 @@ #include "ControlTransferInterpreter.hpp" +#include "../DefinedStructs/DescriptorStruct.hpp" ControlTransferInterpreter::ControlTransferInterpreter(TreeItem* rootItem, QTableWidgetItem* item, AdditionalDataModel* additionalDataModel) : @@ -14,7 +15,6 @@ void ControlTransferInterpreter::Interpret() { QByteArray data = item->data(holder->TRANSFER_LEFTOVER_DATA).toByteArray(); const char* packet = data.constData(); - BYTE descriptorSize = (BYTE)*packet; BYTE descriptorType = (BYTE) * (packet++); DescriptorStruct* descStruct = GetDescriptorStruct(descriptorType); if (descStruct == nullptr) @@ -23,7 +23,7 @@ void ControlTransferInterpreter::Interpret() } else { - descStruct->InterpretData(rootItem, (const unsigned char*)packet); + descStruct->InterpretData(rootItem, data, additionalDataModel); } } From 08532354109d0b162f278104188401f3040d0c55 Mon Sep 17 00:00:00 2001 From: Peter Lakatos Date: Thu, 9 Sep 2021 20:14:16 +0200 Subject: [PATCH 5/5] Continued work on automatic interpretation. Fixed compilation errors. Need to fix interpretation bugs. --- DefinedStructs/ConstDataHolder.cpp | 7 +- DefinedStructs/DescriptorStruct.hpp | 87 ++++++++++++++------- Descriptors/{Decs03.txt => Desc03.txt} | 0 Interpreters/ControlTransferInterpreter.cpp | 2 +- Models/TreeItemBaseModel.h | 37 +++++---- 5 files changed, 82 insertions(+), 51 deletions(-) rename Descriptors/{Decs03.txt => Desc03.txt} (100%) diff --git a/DefinedStructs/ConstDataHolder.cpp b/DefinedStructs/ConstDataHolder.cpp index 3eb0934..ba55a03 100644 --- a/DefinedStructs/ConstDataHolder.cpp +++ b/DefinedStructs/ConstDataHolder.cpp @@ -28,7 +28,7 @@ DataHolder::DataHolder() TRANSFER_LEFTOVER_DATA = Qt::UserRole + 1; TRANSFER_OPTIONAL_HEADER = Qt::UserRole + 2; USBPCAP_HEADER_DATA = Qt::UserRole + 3; - DescriptorPath = "./Descriptors/"; + DescriptorPath = std::filesystem::current_path().string() + "\\Descriptors\\"; } /// @@ -63,9 +63,10 @@ void DataHolder::FillDataColorsMap() /// Pointer to loaded descriptor if exists, else nullptr DescriptorStruct* DataHolder::TryLoadNewDescriptor(BYTE descType) { - std::stringstream stream(DescriptorPath); + std::stringstream stream(DescriptorPath, std::ios_base::app | std::ios_base::out); + stream << "Desc"; - stream << std::setw(2) << std::setfill('0') << descType; + stream << std::setw(2) << std::setfill('0') << (int)descType; stream << ".txt"; if (std::filesystem::exists(stream.str().c_str())) diff --git a/DefinedStructs/DescriptorStruct.hpp b/DefinedStructs/DescriptorStruct.hpp index 7b6d89d..cf1e08d 100644 --- a/DefinedStructs/DescriptorStruct.hpp +++ b/DefinedStructs/DescriptorStruct.hpp @@ -28,6 +28,7 @@ class AbstractDescriptorField /// /// Structure representing one segment of field which has bit level details /// +template struct BitField { /// @@ -41,7 +42,7 @@ struct BitField /// /// map holding descriptions to given values /// - std::map descriptions; + std::map descriptions; }; /// @@ -57,19 +58,34 @@ class DescriptorField : public AbstractDescriptorField std::size_t InterpretField(TreeItem* rootItem, const unsigned char* data, std::size_t sizeLeft, AdditionalDataModel* additionalDataModel) override; private: - void CharToNumberConvert(const unsigned char* addr) + void CharToNumberConvert(const unsigned char* addr) { - value = 0; - for (int i = sizeof(T); i > 0; i--) + if constexpr (!std::is_same_v && !std::is_same_v) { - value = (value << 8) | addr[i - 1]; + value = T(); + for (int i = sizeof(T); i > 0; i--) + { + value = (value << 8) | addr[i - 1]; + } } } - T GetBitFieldValue(BitField& field); + void CharToConcreteNumberConvert(const unsigned char* addr, T& value) + { + if constexpr (!std::is_same_v && !std::is_same_v) + { + value = T(); + for (int i = sizeof(T); i > 0; i--) + { + value = (value << 8) | addr[i - 1]; + } + } + } + + T GetBitFieldValue(BitField& field); std::string description; - std::vector bitFields; + std::vector> bitFields; T value; }; @@ -92,7 +108,7 @@ void DescriptorField::FillUpField(std::ifstream& input) return; } std::istringstream ss(line); - BitField b; + BitField b; ss >> b.start; ss.get(); //separator ss >> b.size; @@ -110,7 +126,8 @@ void DescriptorField::FillUpField(std::ifstream& input) } //else fill up one bit field with value - description pairs ss = std::istringstream(line); - int value = ss.get(); + T value; + CharToConcreteNumberConvert((const unsigned char*)(ss.str().c_str()), value); b.descriptions[value] = ss.str(); } } @@ -143,27 +160,37 @@ std::size_t DescriptorField::InterpretField(TreeItem* rootItem, const unsigne return sizeLeft; } - //some other data type - //convert char* to number and fill value data field - CharToNumberConvert(data); - additionalDataModel->CharToHexConvert(&data, sizeof(T), hexData); - rootItem->AppendChild(new TreeItem(QVector{hexData, description.c_str(), value}, rootItem)); - - //check if it carries some bit defined information - //if not, return proccessed size - if (bitFields.empty()) - { - return sizeof(T); - } - //else go through bitFields and interpret them - TreeItem* bitFieldParent = rootItem->Child(rootItem->ChildCount() - 1); - for (std::size_t i = 0; i < bitFields.size(); i++) + //used so we can work with std::stringstream and its operator << (it wouldnt work with wstring) + if constexpr (!std::is_same_v && !std::is_same_v) { - T bitValue = GetBitFieldValue(bitFields[i]); - auto fieldDesc = bitFields[i].descriptions[bitValue]; - bitFieldParent->AppendChild(new TreeItem(QVector{ - additionalDataModel->ShowBits(bitFields[i].start, bitFields[i].size, value), - fieldDesc.c_str(), bitValue}, bitFieldParent)); + //some other data type + //convert char* to number and fill value data field + CharToNumberConvert(data); + additionalDataModel->CharToHexConvert(&data, sizeof(T), hexData); + std::stringstream ss; + ss << value; + rootItem->AppendChild(new TreeItem(QVector{hexData, description.c_str(), ss.str().c_str()}, rootItem)); + + //check if it carries some bit defined information + //if not, return proccessed size + if (bitFields.empty()) + { + return sizeof(T); + } + //else go through bitFields and interpret them + TreeItem* bitFieldParent = rootItem->Child(rootItem->ChildCount() - 1); + for (std::size_t i = 0; i < bitFields.size(); i++) + { + T bitValue = GetBitFieldValue(bitFields[i]); + auto fieldDesc = bitFields[i].descriptions[bitValue]; + ss.clear(); + ss << value; + std::stringstream ss2; + ss2 << bitValue; + bitFieldParent->AppendChild(new TreeItem(QVector{ + additionalDataModel->ShowBits(bitFields[i].start, bitFields[i].size, ss.str().c_str()), + fieldDesc.c_str(), ss2.str().c_str()}, bitFieldParent)); + } } } @@ -174,7 +201,7 @@ std::size_t DescriptorField::InterpretField(TreeItem* rootItem, const unsigne /// Concrete field /// Value of given bit-field template -T DescriptorField::GetBitFieldValue(BitField& field) +T DescriptorField::GetBitFieldValue(BitField& field) { T bitmask = (1 << field.size) - 1; bitmask = bitmask << field.start; diff --git a/Descriptors/Decs03.txt b/Descriptors/Desc03.txt similarity index 100% rename from Descriptors/Decs03.txt rename to Descriptors/Desc03.txt diff --git a/Interpreters/ControlTransferInterpreter.cpp b/Interpreters/ControlTransferInterpreter.cpp index b80551f..994e168 100644 --- a/Interpreters/ControlTransferInterpreter.cpp +++ b/Interpreters/ControlTransferInterpreter.cpp @@ -15,7 +15,7 @@ void ControlTransferInterpreter::Interpret() { QByteArray data = item->data(holder->TRANSFER_LEFTOVER_DATA).toByteArray(); const char* packet = data.constData(); - BYTE descriptorType = (BYTE) * (packet++); + BYTE descriptorType = (BYTE) * (++packet); DescriptorStruct* descStruct = GetDescriptorStruct(descriptorType); if (descStruct == nullptr) { diff --git a/Models/TreeItemBaseModel.h b/Models/TreeItemBaseModel.h index c8391bf..747e4da 100644 --- a/Models/TreeItemBaseModel.h +++ b/Models/TreeItemBaseModel.h @@ -55,27 +55,30 @@ template QString TreeItemBaseModel::ShowBits(const uint32_t start, const size_t size, T number) const { std::stringstream stream; - for (int i = 0; i < sizeof(T) * 8; i++) + if constexpr (!std::is_same_v && !std::is_same_v && !std::is_same_v) { - if (i != 0 && i % 4 == 0) + for (int i = 0; i < sizeof(T) * 8; i++) { - stream << ' '; - } - if (i < start || i >= start + size) - { - stream << std::setw(2) << std::setfill(' ') << '.'; + if (i != 0 && i % 4 == 0) + { + stream << ' '; + } + if (i < start || i >= start + size) + { + stream << std::setw(2) << std::setfill(' ') << '.'; + number = number << 1; + continue; + } + if (number & (0x1 << ((sizeof(T) * 8) - 1))) + { + stream << '1'; + } + else + { + stream << '0'; + } number = number << 1; - continue; - } - if (number & (0x1 << ((sizeof(T) * 8) - 1))) - { - stream << '1'; - } - else - { - stream << '0'; } - number = number << 1; } return QString(stream.str().c_str());