Added an ISO-TP decoder. At the moment it tries to decode all frames
and that leads to odd results.
This commit is contained in:
+8
-3
@@ -46,7 +46,9 @@ SOURCES += main.cpp\
|
||||
dbcloadsavewindow.cpp \
|
||||
fuzzingwindow.cpp \
|
||||
udsscanwindow.cpp \
|
||||
can_structs.cpp
|
||||
can_structs.cpp \
|
||||
isotp_interpreterwindow.cpp \
|
||||
isotp_decoder.cpp
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
can_structs.h \
|
||||
@@ -79,7 +81,9 @@ HEADERS += mainwindow.h \
|
||||
rangestatewindow.h \
|
||||
dbcloadsavewindow.h \
|
||||
fuzzingwindow.h \
|
||||
udsscanwindow.h
|
||||
udsscanwindow.h \
|
||||
isotp_interpreterwindow.h \
|
||||
isotp_decoder.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
graphingwindow.ui \
|
||||
@@ -100,7 +104,8 @@ FORMS += mainwindow.ui \
|
||||
rangestatewindow.ui \
|
||||
dbcloadsavewindow.ui \
|
||||
fuzzingwindow.ui \
|
||||
udsscanwindow.ui
|
||||
udsscanwindow.ui \
|
||||
isotp_interpreterwindow.ui
|
||||
|
||||
DISTFILES +=
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ public:
|
||||
};
|
||||
|
||||
//the same as the CANFrame struct but with arbitrary data size.
|
||||
struct ISOTP_FRAME
|
||||
struct ISOTP_MESSAGE
|
||||
{
|
||||
public:
|
||||
int ID;
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#include "isotp_decoder.h"
|
||||
|
||||
ISOTP_DECODER::ISOTP_DECODER(const QVector<CANFrame> *frames, QObject *parent)
|
||||
: QObject(parent)
|
||||
{
|
||||
modelFrames = frames;
|
||||
useExtendedAddressing = false;
|
||||
}
|
||||
|
||||
void ISOTP_DECODER::setExtendedAddressing(bool mode)
|
||||
{
|
||||
useExtendedAddressing = mode;
|
||||
}
|
||||
|
||||
//remember, negative numbers are special -1 = all frames deleted, -2 = totally new set of frames.
|
||||
void ISOTP_DECODER::updatedFrames(int numFrames)
|
||||
{
|
||||
if (numFrames == -1) //all frames deleted. Kill the display
|
||||
{
|
||||
}
|
||||
else if (numFrames == -2) //all new set of frames. Reset
|
||||
{
|
||||
for (int i = 0; i < modelFrames->length(); i++) processFrame(modelFrames->at(i));
|
||||
}
|
||||
else //just got some new frames. See if they are relevant.
|
||||
{
|
||||
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
||||
{
|
||||
processFrame(modelFrames->at(i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ISOTP_DECODER::processFrame(const CANFrame &frame)
|
||||
{
|
||||
uint64_t ID = frame.ID;
|
||||
int frameType;
|
||||
int frameLen;
|
||||
int ln;
|
||||
int offset;
|
||||
ISOTP_MESSAGE msg;
|
||||
ISOTP_MESSAGE *pMsg;
|
||||
|
||||
frameType = 0;
|
||||
frameLen = 0;
|
||||
|
||||
if (useExtendedAddressing)
|
||||
{
|
||||
ID = ID << 8;
|
||||
ID += frame.data[0];
|
||||
frameType = frame.data[1] >> 4;
|
||||
frameLen = frame.data[1] & 0xF;
|
||||
}
|
||||
else
|
||||
{
|
||||
frameType = frame.data[0] >> 4;
|
||||
frameLen = frame.data[0] & 0xF;
|
||||
}
|
||||
|
||||
switch(frameType)
|
||||
{
|
||||
case 0: //single frame message
|
||||
checkNeedFlush(ID);
|
||||
|
||||
if (frameLen == 0) return; //length of zero isn't valid.
|
||||
if (frameLen > 6 && useExtendedAddressing) return; //impossible
|
||||
if (frameLen > 7) return;
|
||||
|
||||
msg.bus = frame.bus;
|
||||
msg.extended = frame.extended;
|
||||
msg.ID = ID;
|
||||
msg.isReceived = frame.isReceived;
|
||||
msg.len = frameLen;
|
||||
msg.data.reserve(frameLen);
|
||||
msg.timestamp = frame.timestamp;
|
||||
if (useExtendedAddressing) for (int j = 0; j < frameLen; j++) msg.data.append(frame.data[j+2]);
|
||||
else for (int j = 0; j < frameLen; j++) msg.data.append(frame.data[j+1]);
|
||||
qDebug() << "Emitting single frame ISOTP message";
|
||||
emit newISOMessage(msg);
|
||||
break;
|
||||
case 1: //first frame of a multi-frame message
|
||||
checkNeedFlush(ID);
|
||||
msg.bus = frame.bus;
|
||||
msg.extended = frame.extended;
|
||||
msg.ID = ID;
|
||||
msg.timestamp = frame.timestamp;
|
||||
msg.isReceived = frame.isReceived;
|
||||
frameLen = frameLen << 8;
|
||||
if (useExtendedAddressing)
|
||||
{
|
||||
frameLen += frame.data[2];
|
||||
frameLen = frameLen & 0xFFF;
|
||||
msg.len = frameLen;
|
||||
msg.data.reserve(frameLen);
|
||||
for (int j = 0; j < 5; j++) msg.data.append(frame.data[3 + j]);
|
||||
}
|
||||
else
|
||||
{
|
||||
frameLen += frame.data[1];
|
||||
frameLen = frameLen & 0xFFF;
|
||||
msg.len = frameLen;
|
||||
msg.data.reserve(frameLen);
|
||||
for (int j = 0; j < 6; j++) msg.data.append(frame.data[2 + j]);
|
||||
}
|
||||
messageBuffer.append(msg);
|
||||
break;
|
||||
case 2: //subsequent frames for multi-frame messages
|
||||
pMsg = NULL;
|
||||
for (int i = 0; i < messageBuffer.length(); i++)
|
||||
{
|
||||
if (messageBuffer[i].ID == ID)
|
||||
{
|
||||
pMsg = &messageBuffer[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!pMsg) return;
|
||||
ln = pMsg->len - pMsg->data.count();
|
||||
offset = pMsg->data.count();
|
||||
if (useExtendedAddressing)
|
||||
{
|
||||
if (ln > 6) ln = 6;
|
||||
for (int j = 0; j < ln; j++) pMsg->data.append(frame.data[j+2]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (ln > 7) ln = 7;
|
||||
for (int j = 0; j < ln; j++) pMsg->data.append(frame.data[j+1]);
|
||||
}
|
||||
if (pMsg->len <= pMsg->data.count())
|
||||
{
|
||||
qDebug() << "Emitting multiframe ISOTP message";
|
||||
emit newISOMessage(*pMsg);
|
||||
}
|
||||
break;
|
||||
case 3: //flow control messages -ignored for now
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ISOTP_DECODER::checkNeedFlush(uint64_t ID)
|
||||
{
|
||||
for (int i = 0; i < messageBuffer.length(); i++)
|
||||
{
|
||||
if (messageBuffer[i].ID == ID)
|
||||
{
|
||||
//warning... this code will work for direct signals as emit turns into a function call
|
||||
//and thus the other side will have time to do its processing before control returns
|
||||
//and we delete the message on our side. But, if this code were used cross thread the
|
||||
//emit would be a queued message instead and control would immediately return
|
||||
//here and then the message would be deleted before being delivered.
|
||||
//To fix that the message would have to be passed by value instead which I'd like to avoid.
|
||||
//Thus, don't use this across threads unless you like to debug strange issues.
|
||||
qDebug() << "Flushing a partial frame";
|
||||
emit newISOMessage(messageBuffer[i]);
|
||||
messageBuffer.removeAt(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#ifndef ISOTP_DECODER_H
|
||||
#define ISOTP_DECODER_H
|
||||
|
||||
#include <QObject>
|
||||
#include <QDebug>
|
||||
#include "can_structs.h"
|
||||
|
||||
class ISOTP_DECODER : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ISOTP_DECODER(const QVector<CANFrame> *frames, QObject *parent = 0);
|
||||
void setExtendedAddressing(bool mode);
|
||||
|
||||
public slots:
|
||||
void updatedFrames(int);
|
||||
|
||||
signals:
|
||||
void newISOMessage(ISOTP_MESSAGE &msg);
|
||||
|
||||
private:
|
||||
QList<ISOTP_MESSAGE> messageBuffer;
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
bool useExtendedAddressing;
|
||||
|
||||
void processFrame(const CANFrame &frame);
|
||||
void checkNeedFlush(uint64_t ID);
|
||||
};
|
||||
|
||||
#endif // ISOTP_DECODER_H
|
||||
@@ -0,0 +1,97 @@
|
||||
#include "isotp_interpreterwindow.h"
|
||||
#include "ui_isotp_interpreterwindow.h"
|
||||
#include "mainwindow.h"
|
||||
|
||||
ISOTP_InterpreterWindow::ISOTP_InterpreterWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::ISOTP_InterpreterWindow)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
modelFrames = frames;
|
||||
|
||||
decoder = new ISOTP_DECODER(modelFrames);
|
||||
|
||||
connect(MainWindow::getReference(), &MainWindow::framesUpdated, decoder, &ISOTP_DECODER::updatedFrames);
|
||||
connect(decoder, &ISOTP_DECODER::newISOMessage, this, &ISOTP_InterpreterWindow::newISOMessage);
|
||||
|
||||
QStringList headers;
|
||||
headers << "Timestamp" << "ID" << "Bus" << "Dir" << "Length" << "Data";
|
||||
ui->tableIsoFrames->setColumnCount(6);
|
||||
ui->tableIsoFrames->setColumnWidth(0, 100);
|
||||
ui->tableIsoFrames->setColumnWidth(1, 50);
|
||||
ui->tableIsoFrames->setColumnWidth(2, 50);
|
||||
ui->tableIsoFrames->setColumnWidth(3, 50);
|
||||
ui->tableIsoFrames->setColumnWidth(4, 75);
|
||||
ui->tableIsoFrames->setColumnWidth(5, 200);
|
||||
ui->tableIsoFrames->setHorizontalHeaderLabels(headers);
|
||||
QHeaderView *HorzHdr = ui->tableIsoFrames->horizontalHeader();
|
||||
HorzHdr->setStretchLastSection(true);
|
||||
}
|
||||
|
||||
ISOTP_InterpreterWindow::~ISOTP_InterpreterWindow()
|
||||
{
|
||||
delete decoder;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void ISOTP_InterpreterWindow::showEvent(QShowEvent* event)
|
||||
{
|
||||
QDialog::showEvent(event);
|
||||
readSettings();
|
||||
decoder->updatedFrames(-2);
|
||||
}
|
||||
|
||||
void ISOTP_InterpreterWindow::closeEvent(QCloseEvent *event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
writeSettings();
|
||||
}
|
||||
|
||||
void ISOTP_InterpreterWindow::readSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
resize(settings.value("ISODecodeWindow/WindowSize", this->size()).toSize());
|
||||
move(settings.value("ISODecodeWindow/WindowPos", QPoint(50, 50)).toPoint());
|
||||
}
|
||||
}
|
||||
|
||||
void ISOTP_InterpreterWindow::writeSettings()
|
||||
{
|
||||
QSettings settings;
|
||||
|
||||
if (settings.value("Main/SaveRestorePositions", false).toBool())
|
||||
{
|
||||
settings.setValue("ISODecodeWindow/WindowSize", size());
|
||||
settings.setValue("ISODecodeWindow/WindowPos", pos());
|
||||
}
|
||||
}
|
||||
|
||||
void ISOTP_InterpreterWindow::newISOMessage(ISOTP_MESSAGE &msg)
|
||||
{
|
||||
int rowNum;
|
||||
QString tempString;
|
||||
|
||||
messages.append(msg);
|
||||
|
||||
rowNum = ui->tableIsoFrames->rowCount();
|
||||
ui->tableIsoFrames->insertRow(rowNum);
|
||||
|
||||
ui->tableIsoFrames->setItem(rowNum, 0, new QTableWidgetItem(QString::number(msg.timestamp)));
|
||||
ui->tableIsoFrames->setItem(rowNum, 1, new QTableWidgetItem(QString::number(msg.ID, 16)));
|
||||
ui->tableIsoFrames->setItem(rowNum, 2, new QTableWidgetItem(QString::number(msg.bus)));
|
||||
if (msg.isReceived) ui->tableIsoFrames->setItem(rowNum, 3, new QTableWidgetItem("Rx"));
|
||||
else ui->tableIsoFrames->setItem(rowNum, 3, new QTableWidgetItem("Tx"));
|
||||
ui->tableIsoFrames->setItem(rowNum, 4, new QTableWidgetItem(QString::number(msg.len)));
|
||||
|
||||
for (int i = 0; i < msg.data.length(); i++)
|
||||
{
|
||||
tempString.append(Utility::formatNumber(msg.data[i]));
|
||||
tempString.append(" ");
|
||||
}
|
||||
ui->tableIsoFrames->setItem(rowNum, 5, new QTableWidgetItem(tempString));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#ifndef ISOTP_INTERPRETERWINDOW_H
|
||||
#define ISOTP_INTERPRETERWINDOW_H
|
||||
|
||||
#include <QDialog>
|
||||
#include "can_structs.h"
|
||||
#include "isotp_decoder.h"
|
||||
|
||||
namespace Ui {
|
||||
class ISOTP_InterpreterWindow;
|
||||
}
|
||||
|
||||
class ISOTP_InterpreterWindow : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ISOTP_InterpreterWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||
~ISOTP_InterpreterWindow();
|
||||
void showEvent(QShowEvent*);
|
||||
|
||||
private slots:
|
||||
void newISOMessage(ISOTP_MESSAGE &msg);
|
||||
|
||||
private:
|
||||
Ui::ISOTP_InterpreterWindow *ui;
|
||||
ISOTP_DECODER *decoder;
|
||||
|
||||
const QVector<CANFrame> *modelFrames;
|
||||
QVector<ISOTP_MESSAGE> messages;
|
||||
|
||||
void closeEvent(QCloseEvent *event);
|
||||
void readSettings();
|
||||
void writeSettings();
|
||||
};
|
||||
|
||||
#endif // ISOTP_INTERPRETERWINDOW_H
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ISOTP_InterpreterWindow</class>
|
||||
<widget class="QDialog" name="ISOTP_InterpreterWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>792</width>
|
||||
<height>571</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>ISO-TP Decoder</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>Interpreted Messages Overview</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTableWidget" name="tableIsoFrames"/>
|
||||
</item>
|
||||
<item alignment="Qt::AlignHCenter">
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Data Details of Selected Message</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QTextBrowser" name="txtFrameDetails"/>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QCheckBox" name="cbInterpretUDS">
|
||||
<property name="text">
|
||||
<string>Interpret Data as UDS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -98,6 +98,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
dbcFileWindow = NULL;
|
||||
fuzzingWindow = NULL;
|
||||
udsScanWindow = NULL;
|
||||
isoWindow = NULL;
|
||||
dbcHandler = new DBCHandler;
|
||||
bDirty = false;
|
||||
inhibitFilterUpdate = false;
|
||||
@@ -140,6 +141,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
||||
connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow);
|
||||
connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
|
||||
connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow);
|
||||
connect(ui->actionISO_TP_Decoder, &QAction::triggered, this, &MainWindow::showISOInterpreterWindow);
|
||||
|
||||
lbStatusConnected.setText(tr("Not connected"));
|
||||
updateFileStatus();
|
||||
@@ -274,6 +276,12 @@ MainWindow::~MainWindow()
|
||||
delete udsScanWindow;
|
||||
}
|
||||
|
||||
if (isoWindow)
|
||||
{
|
||||
isoWindow->close();
|
||||
delete isoWindow;
|
||||
}
|
||||
|
||||
delete elapsedTime;
|
||||
|
||||
delete ui;
|
||||
@@ -299,6 +307,7 @@ void MainWindow::exitApp()
|
||||
if (dbcFileWindow) dbcFileWindow->close();
|
||||
if (fuzzingWindow) fuzzingWindow->close();
|
||||
if (udsScanWindow) udsScanWindow->close();
|
||||
if (isoWindow) isoWindow->close();
|
||||
this->close();
|
||||
}
|
||||
|
||||
@@ -884,6 +893,18 @@ void MainWindow::showFrameDataAnalysis()
|
||||
frameInfoWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showISOInterpreterWindow()
|
||||
{
|
||||
if (!isoWindow)
|
||||
{
|
||||
if (!useFiltered)
|
||||
isoWindow = new ISOTP_InterpreterWindow(model->getListReference());
|
||||
else
|
||||
isoWindow = new ISOTP_InterpreterWindow(model->getFilteredListReference());
|
||||
}
|
||||
isoWindow->show();
|
||||
}
|
||||
|
||||
void MainWindow::showFrameSenderWindow()
|
||||
{
|
||||
if (!frameSenderWindow)
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "dbcloadsavewindow.h"
|
||||
#include "fuzzingwindow.h"
|
||||
#include "udsscanwindow.h"
|
||||
#include "isotp_interpreterwindow.h"
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
@@ -65,6 +66,7 @@ private slots:
|
||||
void showDBCFileWindow();
|
||||
void showFuzzingWindow();
|
||||
void showUDSScanWindow();
|
||||
void showISOInterpreterWindow();
|
||||
void exitApp();
|
||||
void handleSaveDecoded();
|
||||
void changeBaudRates();
|
||||
@@ -141,6 +143,7 @@ private:
|
||||
DBCLoadSaveWindow *dbcFileWindow;
|
||||
FuzzingWindow *fuzzingWindow;
|
||||
UDSScanWindow *udsScanWindow;
|
||||
ISOTP_InterpreterWindow *isoWindow;
|
||||
|
||||
//various private storage
|
||||
QLabel lbStatusConnected;
|
||||
|
||||
@@ -210,6 +210,7 @@
|
||||
<addaction name="actionFile_Comparison"/>
|
||||
<addaction name="actionRange_State_2"/>
|
||||
<addaction name="actionSingle_Multi_State_2"/>
|
||||
<addaction name="actionISO_TP_Decoder"/>
|
||||
</widget>
|
||||
<widget class="QMenu" name="menuSend_Frames">
|
||||
<property name="title">
|
||||
@@ -387,6 +388,11 @@
|
||||
<string>UDS Scanner</string>
|
||||
</property>
|
||||
</action>
|
||||
<action name="actionISO_TP_Decoder">
|
||||
<property name="text">
|
||||
<string>ISO-TP Decoder</string>
|
||||
</property>
|
||||
</action>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
|
||||
+1
-1
@@ -11,7 +11,7 @@
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Dialog</string>
|
||||
<string>UDS Scanner</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
|
||||
Reference in New Issue
Block a user