Fixed ISOTP Interpreter Window - It functions again.
Also added UDS decoding to the ISOTP window. An attempt is made to see if a frame looks like UDS and then it is decoded. Also, some code clean up to remove some compiler warnings. There's a LONG way to go still.
This commit is contained in:
@@ -339,7 +339,7 @@ void ISOTP_HANDLER::setProcessAll(bool state)
|
|||||||
processAll = state;
|
processAll = state;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISOTP_HANDLER::addFilter(int pBusId, uint32_t ID, uint32_t mask)
|
void ISOTP_HANDLER::addFilter(uint32_t pBusId, uint32_t ID, uint32_t mask)
|
||||||
{
|
{
|
||||||
CANFilter filt;
|
CANFilter filt;
|
||||||
filt.ID = ID;
|
filt.ID = ID;
|
||||||
@@ -349,7 +349,7 @@ void ISOTP_HANDLER::addFilter(int pBusId, uint32_t ID, uint32_t mask)
|
|||||||
filters.append(filt);
|
filters.append(filt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISOTP_HANDLER::removeFilter(int pBusId, uint32_t ID, uint32_t mask)
|
void ISOTP_HANDLER::removeFilter(uint32_t pBusId, uint32_t ID, uint32_t mask)
|
||||||
{
|
{
|
||||||
for (int i = 0; i < filters.count(); i++)
|
for (int i = 0; i < filters.count(); i++)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -23,8 +23,8 @@ public:
|
|||||||
void sendISOTPFrame(int bus, int ID, QVector<unsigned char> data);
|
void sendISOTPFrame(int bus, int ID, QVector<unsigned char> data);
|
||||||
void setProcessAll(bool state);
|
void setProcessAll(bool state);
|
||||||
void setFlowCtrl(bool state);
|
void setFlowCtrl(bool state);
|
||||||
void addFilter(int pBusId, uint32_t ID, uint32_t mask);
|
void addFilter(uint32_t pBusId, uint32_t ID, uint32_t mask);
|
||||||
void removeFilter(int pBusId, uint32_t ID, uint32_t mask);
|
void removeFilter(uint32_t pBusId, uint32_t ID, uint32_t mask);
|
||||||
void clearAllFilters();
|
void clearAllFilters();
|
||||||
|
|
||||||
public slots:
|
public slots:
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ public:
|
|||||||
int bus;
|
int bus;
|
||||||
bool extended;
|
bool extended;
|
||||||
bool isReceived;
|
bool isReceived;
|
||||||
int len; //# of bytes this message should have (as reported)
|
uint32_t len; //# of bytes this message should have (as reported)
|
||||||
int actualSize; //# we actually got
|
uint32_t actualSize; //# we actually got
|
||||||
QVector<unsigned char> data;
|
QVector<unsigned char> data;
|
||||||
uint64_t timestamp;
|
uint64_t timestamp;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -272,12 +272,12 @@ void UDS_HANDLER::setProcessAllIDs(bool state)
|
|||||||
isoHandler->setProcessAll(state);
|
isoHandler->setProcessAll(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDS_HANDLER::addFilter(int pBusId, uint32_t ID, uint32_t mask)
|
void UDS_HANDLER::addFilter(uint32_t pBusId, uint32_t ID, uint32_t mask)
|
||||||
{
|
{
|
||||||
isoHandler->addFilter(pBusId, ID, mask);
|
isoHandler->addFilter(pBusId, ID, mask);
|
||||||
}
|
}
|
||||||
|
|
||||||
void UDS_HANDLER::removeFilter(int pBusId, uint32_t ID, uint32_t mask)
|
void UDS_HANDLER::removeFilter(uint32_t pBusId, uint32_t ID, uint32_t mask)
|
||||||
{
|
{
|
||||||
isoHandler->removeFilter(pBusId, ID, mask);
|
isoHandler->removeFilter(pBusId, ID, mask);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ namespace UDS_SERVICES
|
|||||||
|
|
||||||
struct CODE_STRUCT
|
struct CODE_STRUCT
|
||||||
{
|
{
|
||||||
int code;
|
unsigned int code;
|
||||||
QString shortDesc;
|
QString shortDesc;
|
||||||
QString longDesc;
|
QString longDesc;
|
||||||
};
|
};
|
||||||
@@ -73,9 +73,9 @@ struct CODE_STRUCT
|
|||||||
class UDS_MESSAGE: public ISOTP_MESSAGE
|
class UDS_MESSAGE: public ISOTP_MESSAGE
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
int service;
|
unsigned int service;
|
||||||
int subFunc;
|
unsigned int subFunc;
|
||||||
int subFuncLen;
|
unsigned int subFuncLen;
|
||||||
bool isErrorReply;
|
bool isErrorReply;
|
||||||
|
|
||||||
UDS_MESSAGE();
|
UDS_MESSAGE();
|
||||||
@@ -94,8 +94,8 @@ public:
|
|||||||
void sendUDSFrame(const UDS_MESSAGE &msg);
|
void sendUDSFrame(const UDS_MESSAGE &msg);
|
||||||
void setProcessAllIDs(bool state);
|
void setProcessAllIDs(bool state);
|
||||||
void setFlowCtrl(bool state);
|
void setFlowCtrl(bool state);
|
||||||
void addFilter(int pBusId, uint32_t ID, uint32_t mask);
|
void addFilter(uint32_t pBusId, uint32_t ID, uint32_t mask);
|
||||||
void removeFilter(int pBusId, uint32_t ID, uint32_t mask);
|
void removeFilter(uint32_t pBusId, uint32_t ID, uint32_t mask);
|
||||||
void clearAllFilters();
|
void clearAllFilters();
|
||||||
|
|
||||||
QString getServiceShortDesc(int service);
|
QString getServiceShortDesc(int service);
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@ public:
|
|||||||
public:
|
public:
|
||||||
uint32_t ID;
|
uint32_t ID;
|
||||||
uint32_t mask;
|
uint32_t mask;
|
||||||
int bus;
|
uint32_t bus;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // CANFILTER_H
|
#endif // CANFILTER_H
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#ifndef CONFIG
|
#ifndef CONFIG
|
||||||
#define CONFIG
|
#define CONFIG
|
||||||
|
|
||||||
#define VERSION 177
|
#define VERSION 178
|
||||||
|
|
||||||
//try to keep this in sync.
|
//try to keep this in sync.
|
||||||
//SavvyCAN will complain if you connect a GVRET board with a revision
|
//SavvyCAN will complain if you connect a GVRET board with a revision
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ FramePlaybackWindow::FramePlaybackWindow(const QVector<CANFrame> *frames, QWidge
|
|||||||
for (int n = 0; n < numBuses; n++) ui->comboCANBus->addItem(QString::number(n));
|
for (int n = 0; n < numBuses; n++) ui->comboCANBus->addItem(QString::number(n));
|
||||||
ui->comboCANBus->addItem(tr("All"));
|
ui->comboCANBus->addItem(tr("All"));
|
||||||
ui->comboCANBus->addItem(tr("From File"));
|
ui->comboCANBus->addItem(tr("From File"));
|
||||||
|
ui->comboCANBus->setCurrentIndex(0);
|
||||||
|
|
||||||
readSettings();
|
readSettings();
|
||||||
|
|
||||||
@@ -113,7 +114,7 @@ void FramePlaybackWindow::readSettings()
|
|||||||
ui->cbLoop->setChecked(true);
|
ui->cbLoop->setChecked(true);
|
||||||
}
|
}
|
||||||
ui->spinPlaySpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
|
ui->spinPlaySpeed->setValue(settings.value("Playback/DefSpeed", 5).toInt());
|
||||||
ui->comboCANBus->setCurrentIndex(settings.value("Playback/SendingBus", 4).toInt());
|
ui->comboCANBus->setCurrentIndex(settings.value("Playback/SendingBus", 0).toInt());
|
||||||
whichBusSend = ui->comboCANBus->currentIndex();
|
whichBusSend = ui->comboCANBus->currentIndex();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -523,7 +524,7 @@ void FramePlaybackWindow::timerTriggered()
|
|||||||
|
|
||||||
void FramePlaybackWindow::updatePosition(bool forward)
|
void FramePlaybackWindow::updatePosition(bool forward)
|
||||||
{
|
{
|
||||||
|
//qDebug() << "updatePosition";
|
||||||
if (forward)
|
if (forward)
|
||||||
{
|
{
|
||||||
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
if (currentPosition < (currentSeqItem->data.count() - 1)) currentPosition++; //still in same file so keep going
|
||||||
@@ -586,10 +587,10 @@ void FramePlaybackWindow::updatePosition(bool forward)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
updateFrameLabel();
|
||||||
//only send frame out if its ID is checked in the list. Otherwise discard it.
|
//only send frame out if its ID is checked in the list. Otherwise discard it.
|
||||||
CANFrame *thisFrame = ¤tSeqItem->data[currentPosition];
|
CANFrame *thisFrame = ¤tSeqItem->data[currentPosition];
|
||||||
int originalBus = thisFrame->bus;
|
uint32_t originalBus = thisFrame->bus;
|
||||||
if (currentSeqItem->idFilters.find(thisFrame->ID).value())
|
if (currentSeqItem->idFilters.find(thisFrame->ID).value())
|
||||||
{
|
{
|
||||||
if (whichBusSend < ui->comboCANBus->count() - 2)
|
if (whichBusSend < ui->comboCANBus->count() - 2)
|
||||||
@@ -611,6 +612,5 @@ void FramePlaybackWindow::updatePosition(bool forward)
|
|||||||
}
|
}
|
||||||
|
|
||||||
thisFrame->bus = originalBus;
|
thisFrame->bus = originalBus;
|
||||||
updateFrameLabel();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,15 +10,20 @@ ISOTP_InterpreterWindow::ISOTP_InterpreterWindow(const QVector<CANFrame> *frames
|
|||||||
modelFrames = frames;
|
modelFrames = frames;
|
||||||
|
|
||||||
decoder = new ISOTP_HANDLER;
|
decoder = new ISOTP_HANDLER;
|
||||||
|
udsDecoder = new UDS_HANDLER;
|
||||||
|
|
||||||
decoder->setReception(true);
|
decoder->setReception(true);
|
||||||
decoder->setProcessAll(true);
|
decoder->setProcessAll(true);
|
||||||
|
|
||||||
|
udsDecoder->setReception(false);
|
||||||
|
|
||||||
connect(MainWindow::getReference(), &MainWindow::framesUpdated, this, &ISOTP_InterpreterWindow::updatedFrames);
|
connect(MainWindow::getReference(), &MainWindow::framesUpdated, this, &ISOTP_InterpreterWindow::updatedFrames);
|
||||||
connect(MainWindow::getReference(), &MainWindow::framesUpdated, decoder, &ISOTP_HANDLER::updatedFrames);
|
connect(MainWindow::getReference(), &MainWindow::framesUpdated, decoder, &ISOTP_HANDLER::updatedFrames);
|
||||||
connect(decoder, &ISOTP_HANDLER::newISOMessage, this, &ISOTP_InterpreterWindow::newISOMessage);
|
connect(decoder, &ISOTP_HANDLER::newISOMessage, this, &ISOTP_InterpreterWindow::newISOMessage);
|
||||||
|
connect(udsDecoder, &UDS_HANDLER::newUDSMessage, this, &ISOTP_InterpreterWindow::newUDSMessage);
|
||||||
|
|
||||||
connect(ui->tableIsoFrames, &QTableWidget::itemSelectionChanged, this, &ISOTP_InterpreterWindow::showDetailView);
|
connect(ui->tableIsoFrames, &QTableWidget::itemSelectionChanged, this, &ISOTP_InterpreterWindow::showDetailView);
|
||||||
|
connect(ui->btnClearList, &QAbstractButton::click, this, &ISOTP_InterpreterWindow::clearList);
|
||||||
|
|
||||||
QStringList headers;
|
QStringList headers;
|
||||||
headers << "Timestamp" << "ID" << "Bus" << "Dir" << "Length" << "Data";
|
headers << "Timestamp" << "ID" << "Bus" << "Dir" << "Length" << "Data";
|
||||||
@@ -32,6 +37,10 @@ ISOTP_InterpreterWindow::ISOTP_InterpreterWindow(const QVector<CANFrame> *frames
|
|||||||
ui->tableIsoFrames->setHorizontalHeaderLabels(headers);
|
ui->tableIsoFrames->setHorizontalHeaderLabels(headers);
|
||||||
QHeaderView *HorzHdr = ui->tableIsoFrames->horizontalHeader();
|
QHeaderView *HorzHdr = ui->tableIsoFrames->horizontalHeader();
|
||||||
HorzHdr->setStretchLastSection(true);
|
HorzHdr->setStretchLastSection(true);
|
||||||
|
|
||||||
|
decoder->setReception(true);
|
||||||
|
decoder->setFlowCtrl(false);
|
||||||
|
decoder->setProcessAll(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
ISOTP_InterpreterWindow::~ISOTP_InterpreterWindow()
|
ISOTP_InterpreterWindow::~ISOTP_InterpreterWindow()
|
||||||
@@ -74,6 +83,11 @@ void ISOTP_InterpreterWindow::writeSettings()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ISOTP_InterpreterWindow::clearList()
|
||||||
|
{
|
||||||
|
ui->tableIsoFrames->clear();
|
||||||
|
}
|
||||||
|
|
||||||
void ISOTP_InterpreterWindow::updatedFrames(int numFrames)
|
void ISOTP_InterpreterWindow::updatedFrames(int numFrames)
|
||||||
{
|
{
|
||||||
if (numFrames == -1) //all frames deleted. Kill the display
|
if (numFrames == -1) //all frames deleted. Kill the display
|
||||||
@@ -117,13 +131,34 @@ void ISOTP_InterpreterWindow::showDetailView()
|
|||||||
}
|
}
|
||||||
buildString.append("\r\r");
|
buildString.append("\r\r");
|
||||||
|
|
||||||
//if (ui->cb->isChecked())
|
ui->txtFrameDetails->setPlainText(buildString);
|
||||||
//{
|
|
||||||
|
|
||||||
//}
|
//pass this frame to the UDS decoder to see if it feels it could be a UDS related message
|
||||||
|
udsDecoder->gotISOTPFrame(messages[rowNum]);
|
||||||
|
}
|
||||||
|
|
||||||
ui->txtFrameDetails->setText(buildString);
|
void ISOTP_InterpreterWindow::newUDSMessage(UDS_MESSAGE msg)
|
||||||
|
{
|
||||||
|
//qDebug() << "Got UDS message in ISOTP Interpreter";
|
||||||
|
QString buildText;
|
||||||
|
|
||||||
|
buildText = ui->txtFrameDetails->toPlainText();
|
||||||
|
|
||||||
|
buildText.append("UDS Message:\n");
|
||||||
|
if (msg.isErrorReply)
|
||||||
|
{
|
||||||
|
buildText.append("Error reply for service " + udsDecoder->getServiceShortDesc(msg.service));
|
||||||
|
buildText.append("\nError Desc: " + udsDecoder->getNegativeResponseShort(msg.subFunc));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (msg.service < 0x3F || (msg.service > 0x7F && msg.service < 0xAF))
|
||||||
|
buildText.append("Request for service " + udsDecoder->getServiceShortDesc(msg.service) + " Sub Func: " + QString::number(msg.subFunc));
|
||||||
|
else
|
||||||
|
buildText.append("Response on service " + udsDecoder->getServiceShortDesc(msg.service - 0x40) + " Sub Func: " + QString::number(msg.subFunc));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui->txtFrameDetails->setPlainText(buildText);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ISOTP_InterpreterWindow::newISOMessage(ISOTP_MESSAGE msg)
|
void ISOTP_InterpreterWindow::newISOMessage(ISOTP_MESSAGE msg)
|
||||||
|
|||||||
@@ -22,12 +22,15 @@ public:
|
|||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void newISOMessage(ISOTP_MESSAGE msg);
|
void newISOMessage(ISOTP_MESSAGE msg);
|
||||||
|
void newUDSMessage(UDS_MESSAGE msg);
|
||||||
void showDetailView();
|
void showDetailView();
|
||||||
void updatedFrames(int);
|
void updatedFrames(int);
|
||||||
|
void clearList();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Ui::ISOTP_InterpreterWindow *ui;
|
Ui::ISOTP_InterpreterWindow *ui;
|
||||||
ISOTP_HANDLER *decoder;
|
ISOTP_HANDLER *decoder;
|
||||||
|
UDS_HANDLER *udsDecoder;
|
||||||
|
|
||||||
const QVector<CANFrame> *modelFrames;
|
const QVector<CANFrame> *modelFrames;
|
||||||
QVector<ISOTP_MESSAGE> messages;
|
QVector<ISOTP_MESSAGE> messages;
|
||||||
|
|||||||
+6
-6
@@ -276,12 +276,12 @@ void ISOTPScriptHelper::sendISOTP(QJSValue bus, QJSValue id, QJSValue length, QJ
|
|||||||
|
|
||||||
if (!data.isArray()) qDebug() << "data isn't an array";
|
if (!data.isArray()) qDebug() << "data isn't an array";
|
||||||
|
|
||||||
for (unsigned int i = 0; i < msg.len; i++)
|
for (int i = 0; i < msg.len; i++)
|
||||||
{
|
{
|
||||||
msg.data[i] = (uint8_t)data.property(i).toInt();
|
msg.data[i] = static_cast<uint8_t>(data.property(i).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.bus = (uint32_t)bus.toInt();
|
msg.bus = bus.toInt();
|
||||||
|
|
||||||
if (msg.ID > 0x7FF) msg.extended = true;
|
if (msg.ID > 0x7FF) msg.extended = true;
|
||||||
|
|
||||||
@@ -302,7 +302,7 @@ void ISOTPScriptHelper::newISOMessage(ISOTP_MESSAGE msg)
|
|||||||
|
|
||||||
QJSValueList args;
|
QJSValueList args;
|
||||||
args << msg.bus << msg.ID << msg.len;
|
args << msg.bus << msg.ID << msg.len;
|
||||||
QJSValue dataBytes = scriptEngine->newArray(msg.len);
|
QJSValue dataBytes = scriptEngine->newArray(static_cast<uint>(msg.len));
|
||||||
|
|
||||||
for (unsigned int j = 0; j < msg.len; j++) dataBytes.setProperty(j, QJSValue(msg.data[j]));
|
for (unsigned int j = 0; j < msg.len; j++) dataBytes.setProperty(j, QJSValue(msg.data[j]));
|
||||||
args.append(dataBytes);
|
args.append(dataBytes);
|
||||||
@@ -341,7 +341,7 @@ void UDSScriptHelper::sendUDS(QJSValue bus, QJSValue id, QJSValue service, QJSVa
|
|||||||
{
|
{
|
||||||
UDS_MESSAGE msg;
|
UDS_MESSAGE msg;
|
||||||
msg.extended = false;
|
msg.extended = false;
|
||||||
msg.ID = id.toInt();
|
msg.ID = id.toUInt();
|
||||||
msg.len = length.toUInt();
|
msg.len = length.toUInt();
|
||||||
msg.service = service.toUInt();
|
msg.service = service.toUInt();
|
||||||
msg.subFuncLen = sublen.toUInt();
|
msg.subFuncLen = sublen.toUInt();
|
||||||
@@ -351,7 +351,7 @@ void UDSScriptHelper::sendUDS(QJSValue bus, QJSValue id, QJSValue service, QJSVa
|
|||||||
|
|
||||||
for (unsigned int i = 0; i < msg.len; i++)
|
for (unsigned int i = 0; i < msg.len; i++)
|
||||||
{
|
{
|
||||||
msg.data[i] = (uint8_t)data.property(i).toInt();
|
msg.data[i] = static_cast<uint8_t>(data.property(i).toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
msg.bus = (uint32_t)bus.toInt();
|
msg.bus = (uint32_t)bus.toInt();
|
||||||
|
|||||||
+3
-2
@@ -60,14 +60,15 @@ void ScriptingWindow::newFrames(const CANConnection* pConn, const QVector<CANFra
|
|||||||
{
|
{
|
||||||
/*FIXME: name of the probe and bus should be checked */
|
/*FIXME: name of the probe and bus should be checked */
|
||||||
Q_UNUSED(pConn);
|
Q_UNUSED(pConn);
|
||||||
|
Q_UNUSED(pFrames);
|
||||||
|
|
||||||
for (int j = 0; j < scripts.length(); j++)
|
/*for (int j = 0; j < scripts.length(); j++)
|
||||||
{
|
{
|
||||||
foreach(const CANFrame& frame, pFrames)
|
foreach(const CANFrame& frame, pFrames)
|
||||||
{
|
{
|
||||||
//scripts[j]->gotFrame(frame);
|
//scripts[j]->gotFrame(frame);
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void ScriptingWindow::updatedValue(int row, int col)
|
void ScriptingWindow::updatedValue(int row, int col)
|
||||||
|
|||||||
@@ -24,6 +24,13 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="QTableWidget" name="tableIsoFrames"/>
|
<widget class="QTableWidget" name="tableIsoFrames"/>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnClearList">
|
||||||
|
<property name="text">
|
||||||
|
<string>Clear Messages List</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignHCenter">
|
||||||
<widget class="QCheckBox" name="cbShowIncomplete">
|
<widget class="QCheckBox" name="cbShowIncomplete">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
@@ -43,43 +50,15 @@
|
|||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
<layout class="QHBoxLayout" name="horizontalLayout_3"/>
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Interpret As:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
<widget class="QRadioButton" name="rbRaw">
|
<widget class="QPlainTextEdit" name="txtFrameDetails">
|
||||||
<property name="text">
|
<property name="readOnly">
|
||||||
<string>Raw</string>
|
|
||||||
</property>
|
|
||||||
<property name="checked">
|
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbUDS">
|
|
||||||
<property name="text">
|
|
||||||
<string>UDS</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QRadioButton" name="rbOBDII">
|
|
||||||
<property name="text">
|
|
||||||
<string>OBDII</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QTextBrowser" name="txtFrameDetails"/>
|
|
||||||
</item>
|
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item>
|
<item>
|
||||||
|
|||||||
Reference in New Issue
Block a user