Remove old custom firmware sender and replace it with AI designed UDS firmware sender. Not tested AT ALL.
Committing merely to give a baseline for further changes
This commit is contained in:
+4
-4
@@ -56,7 +56,6 @@ SOURCES += main.cpp\
|
|||||||
framesenderwindow.cpp \
|
framesenderwindow.cpp \
|
||||||
framefileio.cpp \
|
framefileio.cpp \
|
||||||
mainsettingsdialog.cpp \
|
mainsettingsdialog.cpp \
|
||||||
firmwareuploaderwindow.cpp \
|
|
||||||
scriptingwindow.cpp \
|
scriptingwindow.cpp \
|
||||||
scriptcontainer.cpp \
|
scriptcontainer.cpp \
|
||||||
canfilter.cpp \
|
canfilter.cpp \
|
||||||
@@ -104,6 +103,7 @@ SOURCES += main.cpp\
|
|||||||
re/sniffer/SnifferDelegate.cpp \
|
re/sniffer/SnifferDelegate.cpp \
|
||||||
connections/newconnectiondialog.cpp \
|
connections/newconnectiondialog.cpp \
|
||||||
re/temporalgraphwindow.cpp \
|
re/temporalgraphwindow.cpp \
|
||||||
|
re/udsfirmwareuploaderwindow.cpp \
|
||||||
filterutility.cpp \
|
filterutility.cpp \
|
||||||
pcaplite.cpp
|
pcaplite.cpp
|
||||||
|
|
||||||
@@ -151,7 +151,6 @@ HEADERS += mainwindow.h \
|
|||||||
framefileio.h \
|
framefileio.h \
|
||||||
config.h \
|
config.h \
|
||||||
mainsettingsdialog.h \
|
mainsettingsdialog.h \
|
||||||
firmwareuploaderwindow.h \
|
|
||||||
scriptingwindow.h \
|
scriptingwindow.h \
|
||||||
scriptcontainer.h \
|
scriptcontainer.h \
|
||||||
canfilter.h \
|
canfilter.h \
|
||||||
@@ -199,6 +198,7 @@ HEADERS += mainwindow.h \
|
|||||||
re/sniffer/SnifferDelegate.h \
|
re/sniffer/SnifferDelegate.h \
|
||||||
connections/newconnectiondialog.h \
|
connections/newconnectiondialog.h \
|
||||||
re/temporalgraphwindow.h \
|
re/temporalgraphwindow.h \
|
||||||
|
re/udsfirmwareuploaderwindow.h \
|
||||||
filterutility.h \
|
filterutility.h \
|
||||||
pcaplite.h
|
pcaplite.h
|
||||||
|
|
||||||
@@ -216,7 +216,6 @@ FORMS += ui/candatagrid.ui \
|
|||||||
ui/dbcnodeeditor.ui \
|
ui/dbcnodeeditor.ui \
|
||||||
ui/discretestatewindow.ui \
|
ui/discretestatewindow.ui \
|
||||||
ui/filecomparatorwindow.ui \
|
ui/filecomparatorwindow.ui \
|
||||||
ui/firmwareuploaderwindow.ui \
|
|
||||||
ui/flowviewwindow.ui \
|
ui/flowviewwindow.ui \
|
||||||
ui/frameinfowindow.ui \
|
ui/frameinfowindow.ui \
|
||||||
ui/frameplaybackwindow.ui \
|
ui/frameplaybackwindow.ui \
|
||||||
@@ -236,7 +235,8 @@ FORMS += ui/candatagrid.ui \
|
|||||||
ui/signalviewerwindow.ui \
|
ui/signalviewerwindow.ui \
|
||||||
ui/helpwindow.ui \
|
ui/helpwindow.ui \
|
||||||
ui/newconnectiondialog.ui \
|
ui/newconnectiondialog.ui \
|
||||||
ui/temporalgraphwindow.ui
|
ui/temporalgraphwindow.ui \
|
||||||
|
ui/udsfirmwareuploaderwindow.ui
|
||||||
|
|
||||||
RESOURCES += \
|
RESOURCES += \
|
||||||
icons.qrc \
|
icons.qrc \
|
||||||
|
|||||||
@@ -1,250 +0,0 @@
|
|||||||
#include "firmwareuploaderwindow.h"
|
|
||||||
#include "ui_firmwareuploaderwindow.h"
|
|
||||||
#include "mainwindow.h"
|
|
||||||
|
|
||||||
#include <QFile>
|
|
||||||
|
|
||||||
//You might wonder: Collin, what in the hell is this for? Firmware uploader? For what? I'm interested! Well, it's a custom
|
|
||||||
//firmware uploader for a motor controller I built. Why would that be in this project. Cuz. It's not really relevant
|
|
||||||
//to anyone else but might serve as a decent reference for a few things: How to make an uploader interface that runs over CAN,
|
|
||||||
//how to lay out a screen like this, how to make a comm protocol for firmware updating over CAN. But, most things use UDS
|
|
||||||
//for firmware updates and wouldn't need this specific code. But, it might be able to be turned into a UDS firmware uploader or downloader.
|
|
||||||
//Note that this screen is specifically hidden by default because of it's oddball status. You have to re-enable it in mainwindow.cpp to see it.
|
|
||||||
|
|
||||||
FirmwareUploaderWindow::FirmwareUploaderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
|
||||||
QDialog(parent),
|
|
||||||
ui(new Ui::FirmwareUploaderWindow)
|
|
||||||
{
|
|
||||||
ui->setupUi(this);
|
|
||||||
setWindowFlags(Qt::Window);
|
|
||||||
|
|
||||||
transferInProgress = false;
|
|
||||||
startedProcess = false;
|
|
||||||
firmwareSize = 0;
|
|
||||||
currentSendingPosition = 0;
|
|
||||||
baseAddress = 0;
|
|
||||||
bus = 0;
|
|
||||||
modelFrames = frames;
|
|
||||||
|
|
||||||
ui->lblFilename->setText("");
|
|
||||||
ui->spinBus->setValue(0);
|
|
||||||
ui->spinBus->setMaximum(1);
|
|
||||||
ui->txtBaseAddr->setText("0x100");
|
|
||||||
updateProgress();
|
|
||||||
|
|
||||||
timer = new QTimer();
|
|
||||||
timer->setInterval(100); //100ms without a reply will cause us to attempt a resend
|
|
||||||
|
|
||||||
connect(MainWindow::getReference(), SIGNAL(framesUpdated(int)), this, SLOT(updatedFrames(int)));
|
|
||||||
connect(ui->btnLoadFile, SIGNAL(clicked(bool)), this, SLOT(handleLoadFile()));
|
|
||||||
connect(ui->btnStartStop, SIGNAL(clicked(bool)), this, SLOT(handleStartStopTransfer()));
|
|
||||||
connect(timer, SIGNAL(timeout()), this, SLOT(timerElapsed()));
|
|
||||||
}
|
|
||||||
|
|
||||||
FirmwareUploaderWindow::~FirmwareUploaderWindow()
|
|
||||||
{
|
|
||||||
timer->stop();
|
|
||||||
CANConManager::getInstance()->removeAllTargettedFrames(this);
|
|
||||||
delete timer;
|
|
||||||
delete ui;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::updateProgress()
|
|
||||||
{
|
|
||||||
ui->lblProgress->setText(QString::number(currentSendingPosition * 4) + " of " + QString::number(firmwareSize) + " transferred");
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::updatedFrames(int numFrames)
|
|
||||||
{
|
|
||||||
//CANFrame thisFrame;
|
|
||||||
if (numFrames == -1) //all frames deleted.
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else if (numFrames == -2) //all new set of frames.
|
|
||||||
{
|
|
||||||
}
|
|
||||||
else //just got some new frames. See if they are relevant.
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
//run through the supposedly new frames in order
|
|
||||||
for (int i = modelFrames->count() - numFrames; i < modelFrames->count(); i++)
|
|
||||||
{
|
|
||||||
thisFrame = modelFrames->at(i);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::gotTargettedFrame(CANFrame frame)
|
|
||||||
{
|
|
||||||
const unsigned char *data = reinterpret_cast<const unsigned char *>(frame.payload().constData());
|
|
||||||
int dataLen = frame.payload().count();
|
|
||||||
|
|
||||||
qDebug() << "FUW: Got targetted frame with id " << frame.frameId();
|
|
||||||
if (frame.frameId() == (uint32_t)(baseAddress + 0x10) && (dataLen == 8) ) {
|
|
||||||
qDebug() << "Start firmware reply";
|
|
||||||
if ((data[0] == 0xAD) && (data[1] == 0xDE))
|
|
||||||
{
|
|
||||||
if ((data[2] == 0xAF) && (data[3] == 0xDE))
|
|
||||||
{
|
|
||||||
qDebug() << "There's dead beef here";
|
|
||||||
if ( (data[4] == (token & 0xFF)) && (data[5] == ((token >> 8) & 0xFF) ) )
|
|
||||||
{
|
|
||||||
if ((data[6] == ((token >> 16) & 0xFF)) && (data[7] == ((token >> 24) & 0xFF)))
|
|
||||||
{
|
|
||||||
qDebug() << "starting firmware process";
|
|
||||||
//MainWindow::getReference()->setTargettedID(baseAddress + 0x20);
|
|
||||||
transferInProgress = true;
|
|
||||||
sendFirmwareChunk();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (frame.frameId() == (uint32_t)(baseAddress + 0x20)) {
|
|
||||||
qDebug() << "Firmware reception success reply";
|
|
||||||
int seq = data[0] + (256 * data[1]);
|
|
||||||
if (seq == currentSendingPosition)
|
|
||||||
{
|
|
||||||
currentSendingPosition++;
|
|
||||||
if (currentSendingPosition * 4 > firmwareSize || currentSendingPosition > 65535)
|
|
||||||
{
|
|
||||||
transferInProgress = false;
|
|
||||||
timer->stop();
|
|
||||||
handleStartStopTransfer();
|
|
||||||
ui->progressBar->setValue(100);
|
|
||||||
sendFirmwareEnding();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ui->progressBar->setValue((400 * currentSendingPosition) / firmwareSize);
|
|
||||||
updateProgress();
|
|
||||||
sendFirmwareChunk();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::timerElapsed()
|
|
||||||
{
|
|
||||||
sendFirmwareChunk(); //resend
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::sendFirmwareChunk()
|
|
||||||
{
|
|
||||||
CANFrame output;
|
|
||||||
int firmwareLocation = currentSendingPosition * 4;
|
|
||||||
int xorByte = 0;
|
|
||||||
output.setExtendedFrameFormat(false);
|
|
||||||
QByteArray bytes(7,0);
|
|
||||||
output.bus = bus;
|
|
||||||
output.setFrameId(baseAddress + 0x16);
|
|
||||||
bytes[0] = currentSendingPosition & 0xFF;
|
|
||||||
bytes[1] = (currentSendingPosition >> 8) & 0xFF;
|
|
||||||
bytes[2] = firmwareData[firmwareLocation++];
|
|
||||||
bytes[3] = firmwareData[firmwareLocation++];
|
|
||||||
bytes[4] = firmwareData[firmwareLocation++];
|
|
||||||
bytes[5] = firmwareData[firmwareLocation++];
|
|
||||||
for (int i = 0; i < 6; i++) xorByte ^= static_cast<unsigned char>(bytes[i]);
|
|
||||||
bytes[6] = xorByte;
|
|
||||||
output.setPayload(bytes);
|
|
||||||
CANConManager::getInstance()->sendFrame(output);
|
|
||||||
timer->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::sendFirmwareEnding()
|
|
||||||
{
|
|
||||||
CANFrame output;
|
|
||||||
output.setExtendedFrameFormat(false);
|
|
||||||
output.bus = bus;
|
|
||||||
QByteArray bytes(4,0);
|
|
||||||
output.setFrameId(baseAddress + 0x30);
|
|
||||||
bytes[3] = (char)0xC0;
|
|
||||||
bytes[2] = (char)0xDE;
|
|
||||||
bytes[1] = (char)0xFA;
|
|
||||||
bytes[0] = (char)0xDE;
|
|
||||||
output.setPayload(bytes);
|
|
||||||
//sendCANFrame(output, bus);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::handleStartStopTransfer()
|
|
||||||
{
|
|
||||||
startedProcess = !startedProcess;
|
|
||||||
|
|
||||||
if (startedProcess) //start the process
|
|
||||||
{
|
|
||||||
ui->progressBar->setValue(0);
|
|
||||||
ui->btnStartStop->setText("Stop Upload");
|
|
||||||
token = Utility::ParseStringToNum(ui->txtToken->text());
|
|
||||||
bus = ui->spinBus->value();
|
|
||||||
baseAddress = Utility::ParseStringToNum(ui->txtBaseAddr->text());
|
|
||||||
qDebug() << "Base address: " + QString::number(baseAddress);
|
|
||||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x10, 0x7FF, this);
|
|
||||||
CANConManager::getInstance()->addTargettedFrame(bus, baseAddress + 0x20, 0x7FF, this);
|
|
||||||
CANFrame output;
|
|
||||||
output.setExtendedFrameFormat(false);
|
|
||||||
QByteArray bytes(8,0);
|
|
||||||
output.bus = bus;
|
|
||||||
output.setFrameId(baseAddress);
|
|
||||||
output.setFrameType(QCanBusFrame::DataFrame);
|
|
||||||
|
|
||||||
bytes[0] = (char)0xEF;
|
|
||||||
bytes[1] = (char)0xBE;
|
|
||||||
bytes[2] = (char)0xAD;
|
|
||||||
bytes[3] = (char)0xDE;
|
|
||||||
bytes[4] = token & 0xFF;
|
|
||||||
bytes[5] = (token >> 8) & 0xFF;
|
|
||||||
bytes[6] = (token >> 16) & 0xFF;
|
|
||||||
bytes[7] = (token >> 24) & 0xFF;
|
|
||||||
output.setPayload(bytes);
|
|
||||||
CANConManager::getInstance()->sendFrame(output);
|
|
||||||
}
|
|
||||||
else //stop anything in process
|
|
||||||
{
|
|
||||||
ui->btnStartStop->setText("Start Upload");
|
|
||||||
CANConManager::getInstance()->removeAllTargettedFrames(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::handleLoadFile()
|
|
||||||
{
|
|
||||||
QFileDialog dialog;
|
|
||||||
|
|
||||||
QStringList filters;
|
|
||||||
filters.append(QString(tr("Raw firmware binary (*.bin)")));
|
|
||||||
|
|
||||||
dialog.setFileMode(QFileDialog::ExistingFile);
|
|
||||||
dialog.setNameFilters(filters);
|
|
||||||
dialog.setViewMode(QFileDialog::Detail);
|
|
||||||
|
|
||||||
if (dialog.exec() == QDialog::Accepted)
|
|
||||||
{
|
|
||||||
QString filename = dialog.selectedFiles().constFirst();
|
|
||||||
|
|
||||||
loadBinaryFile(filename);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FirmwareUploaderWindow::loadBinaryFile(QString filename)
|
|
||||||
{
|
|
||||||
|
|
||||||
if (transferInProgress) handleStartStopTransfer();
|
|
||||||
|
|
||||||
QFile inFile(filename);
|
|
||||||
|
|
||||||
if (!inFile.open(QIODevice::ReadOnly))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
firmwareData = inFile.readAll();
|
|
||||||
|
|
||||||
currentSendingPosition = 0;
|
|
||||||
firmwareSize = firmwareData.length();
|
|
||||||
|
|
||||||
updateProgress();
|
|
||||||
|
|
||||||
inFile.close();
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
#ifndef FIRMWAREUPLOADERWINDOW_H
|
|
||||||
#define FIRMWAREUPLOADERWINDOW_H
|
|
||||||
|
|
||||||
#include <QDialog>
|
|
||||||
#include <QTimer>
|
|
||||||
#include "can_structs.h"
|
|
||||||
#include "connections/canconmanager.h"
|
|
||||||
#include "utility.h"
|
|
||||||
|
|
||||||
namespace Ui {
|
|
||||||
class FirmwareUploaderWindow;
|
|
||||||
}
|
|
||||||
|
|
||||||
class FirmwareUploaderWindow : public QDialog
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit FirmwareUploaderWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
|
||||||
~FirmwareUploaderWindow();
|
|
||||||
|
|
||||||
public slots:
|
|
||||||
void gotTargettedFrame(CANFrame frame);
|
|
||||||
|
|
||||||
private slots:
|
|
||||||
void handleLoadFile();
|
|
||||||
void handleStartStopTransfer();
|
|
||||||
void updatedFrames(int);
|
|
||||||
void timerElapsed();
|
|
||||||
|
|
||||||
private:
|
|
||||||
void updateProgress();
|
|
||||||
void loadBinaryFile(QString);
|
|
||||||
void sendFirmwareChunk();
|
|
||||||
void sendFirmwareEnding();
|
|
||||||
|
|
||||||
Ui::FirmwareUploaderWindow *ui;
|
|
||||||
bool transferInProgress;
|
|
||||||
bool startedProcess;
|
|
||||||
int firmwareSize;
|
|
||||||
int currentSendingPosition;
|
|
||||||
int baseAddress;
|
|
||||||
int bus;
|
|
||||||
uint32_t token;
|
|
||||||
QByteArray firmwareData;
|
|
||||||
const QVector<CANFrame> *modelFrames;
|
|
||||||
QTimer *timer;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif // FIRMWAREUPLOADERWINDOW_H
|
|
||||||
+8
-8
@@ -80,7 +80,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
dbcMainEditor = nullptr;
|
dbcMainEditor = nullptr;
|
||||||
comparatorWindow = nullptr;
|
comparatorWindow = nullptr;
|
||||||
settingsDialog = nullptr;
|
settingsDialog = nullptr;
|
||||||
firmwareUploaderWindow = nullptr;
|
udsFirmwareUploaderWindow = nullptr;
|
||||||
discreteStateWindow = nullptr;
|
discreteStateWindow = nullptr;
|
||||||
connectionWindow = nullptr;
|
connectionWindow = nullptr;
|
||||||
scriptingWindow = nullptr;
|
scriptingWindow = nullptr;
|
||||||
@@ -126,7 +126,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
connect(ui->actionDBC_Comparison, &QAction::triggered, this, &MainWindow::showDBCComparisonWindow);
|
connect(ui->actionDBC_Comparison, &QAction::triggered, this, &MainWindow::showDBCComparisonWindow);
|
||||||
connect(ui->actionScripting_INterface, &QAction::triggered, this, &MainWindow::showScriptingWindow);
|
connect(ui->actionScripting_INterface, &QAction::triggered, this, &MainWindow::showScriptingWindow);
|
||||||
connect(ui->actionPreferences, &QAction::triggered, this, &MainWindow::showSettingsDialog);
|
connect(ui->actionPreferences, &QAction::triggered, this, &MainWindow::showSettingsDialog);
|
||||||
connect(ui->actionFirmware_Update, &QAction::triggered, this, &MainWindow::showFirmwareUploaderWindow);
|
connect(ui->actionUDS_Firmware_Update, &QAction::triggered, this, &MainWindow::showUDSFirmwareUploaderWindow);
|
||||||
connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow);
|
connect(ui->actionDBC_File_Manager, &QAction::triggered, this, &MainWindow::showDBCFileWindow);
|
||||||
connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
|
connect(ui->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
|
||||||
connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow);
|
connect(ui->actionUDS_Scanner, &QAction::triggered, this, &MainWindow::showUDSScanWindow);
|
||||||
@@ -225,7 +225,7 @@ MainWindow::MainWindow(QWidget *parent) :
|
|||||||
|
|
||||||
//these either are unfinished/not working or are not for general use. But,they exist
|
//these either are unfinished/not working or are not for general use. But,they exist
|
||||||
//so if you want to enable them and play with them then go for it.
|
//so if you want to enable them and play with them then go for it.
|
||||||
ui->actionFirmware_Update->setVisible(false);
|
//ui->actionFirmware_Update->setVisible(false);
|
||||||
ui->actionMotorControlConfig->setVisible(false);
|
ui->actionMotorControlConfig->setVisible(false);
|
||||||
ui->actionSingle_Multi_State_2->setVisible(false);
|
ui->actionSingle_Multi_State_2->setVisible(false);
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ void MainWindow::killEmAll()
|
|||||||
killWindow(isoWindow);
|
killWindow(isoWindow);
|
||||||
killWindow(snifferWindow);
|
killWindow(snifferWindow);
|
||||||
killWindow(bisectWindow);
|
killWindow(bisectWindow);
|
||||||
killWindow(firmwareUploaderWindow);
|
killWindow(udsFirmwareUploaderWindow);
|
||||||
killWindow(motorctrlConfigWindow);
|
killWindow(motorctrlConfigWindow);
|
||||||
killWindow(signalViewerWindow);
|
killWindow(signalViewerWindow);
|
||||||
killWindow(temporalGraphWindow);
|
killWindow(temporalGraphWindow);
|
||||||
@@ -1720,13 +1720,13 @@ void MainWindow::showPlaybackWindow()
|
|||||||
playbackWindow->show();
|
playbackWindow->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showFirmwareUploaderWindow()
|
void MainWindow::showUDSFirmwareUploaderWindow()
|
||||||
{
|
{
|
||||||
if (!firmwareUploaderWindow)
|
if (!udsFirmwareUploaderWindow)
|
||||||
{
|
{
|
||||||
firmwareUploaderWindow = new FirmwareUploaderWindow(model->getListReference());
|
udsFirmwareUploaderWindow = new UDSFirmwareUploaderWindow(model->getListReference());
|
||||||
}
|
}
|
||||||
firmwareUploaderWindow->show();
|
udsFirmwareUploaderWindow->show();
|
||||||
}
|
}
|
||||||
|
|
||||||
void MainWindow::showComparisonWindow()
|
void MainWindow::showComparisonWindow()
|
||||||
|
|||||||
+3
-3
@@ -20,7 +20,6 @@
|
|||||||
#include "re/filecomparatorwindow.h"
|
#include "re/filecomparatorwindow.h"
|
||||||
#include "dbc/dbcmaineditor.h"
|
#include "dbc/dbcmaineditor.h"
|
||||||
#include "mainsettingsdialog.h"
|
#include "mainsettingsdialog.h"
|
||||||
#include "firmwareuploaderwindow.h"
|
|
||||||
#include "re/discretestatewindow.h"
|
#include "re/discretestatewindow.h"
|
||||||
#include "scriptingwindow.h"
|
#include "scriptingwindow.h"
|
||||||
#include "re/rangestatewindow.h"
|
#include "re/rangestatewindow.h"
|
||||||
@@ -33,6 +32,7 @@
|
|||||||
#include "signalviewerwindow.h"
|
#include "signalviewerwindow.h"
|
||||||
#include "re/temporalgraphwindow.h"
|
#include "re/temporalgraphwindow.h"
|
||||||
#include "re/dbccomparatorwindow.h"
|
#include "re/dbccomparatorwindow.h"
|
||||||
|
#include "re/udsfirmwareuploaderwindow.h"
|
||||||
#include "canbridgewindow.h"
|
#include "canbridgewindow.h"
|
||||||
|
|
||||||
class CANConnection;
|
class CANConnection;
|
||||||
@@ -89,7 +89,7 @@ private slots:
|
|||||||
void showFuzzyScopeWindow();
|
void showFuzzyScopeWindow();
|
||||||
void showComparisonWindow();
|
void showComparisonWindow();
|
||||||
void showSettingsDialog();
|
void showSettingsDialog();
|
||||||
void showFirmwareUploaderWindow();
|
void showUDSFirmwareUploaderWindow();
|
||||||
void showConnectionSettingsWindow();
|
void showConnectionSettingsWindow();
|
||||||
void showScriptingWindow();
|
void showScriptingWindow();
|
||||||
void showDBCFileWindow();
|
void showDBCFileWindow();
|
||||||
@@ -184,7 +184,7 @@ private:
|
|||||||
FileComparatorWindow *comparatorWindow;
|
FileComparatorWindow *comparatorWindow;
|
||||||
MainSettingsDialog *settingsDialog;
|
MainSettingsDialog *settingsDialog;
|
||||||
DiscreteStateWindow *discreteStateWindow;
|
DiscreteStateWindow *discreteStateWindow;
|
||||||
FirmwareUploaderWindow *firmwareUploaderWindow;
|
UDSFirmwareUploaderWindow *udsFirmwareUploaderWindow;
|
||||||
ConnectionWindow *connectionWindow;
|
ConnectionWindow *connectionWindow;
|
||||||
ScriptingWindow *scriptingWindow;
|
ScriptingWindow *scriptingWindow;
|
||||||
RangeStateWindow *rangeWindow;
|
RangeStateWindow *rangeWindow;
|
||||||
|
|||||||
@@ -0,0 +1,467 @@
|
|||||||
|
#include "udsfirmwareuploaderwindow.h"
|
||||||
|
#include "ui_udsfirmwareuploaderwindow.h"
|
||||||
|
#include "mainwindow.h"
|
||||||
|
#include "connections/canconmanager.h"
|
||||||
|
#include "utility.h"
|
||||||
|
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
|
#include <QDateTime>
|
||||||
|
|
||||||
|
UDSFirmwareUploaderWindow::UDSFirmwareUploaderWindow(const QVector<CANFrame> *frames, QWidget *parent) :
|
||||||
|
QDialog(parent),
|
||||||
|
ui(new Ui::UDSFirmwareUploaderWindow)
|
||||||
|
{
|
||||||
|
ui->setupUi(this);
|
||||||
|
setWindowFlags(Qt::Window);
|
||||||
|
|
||||||
|
modelFrames = frames;
|
||||||
|
currentState = STATE_IDLE;
|
||||||
|
firmwareSize = 0;
|
||||||
|
blockSequenceCounter = 0;
|
||||||
|
maxBlockLength = 0;
|
||||||
|
currentDataPos = 0;
|
||||||
|
busId = 0;
|
||||||
|
targetId = 0x7E0;
|
||||||
|
responseId = 0x7E8;
|
||||||
|
sessionType = 0x02;
|
||||||
|
securityLevel = 1;
|
||||||
|
flashAddr = 0x08000000;
|
||||||
|
useSecurity = true;
|
||||||
|
|
||||||
|
udsHandler = new UDS_HANDLER();
|
||||||
|
timeoutTimer = new QTimer();
|
||||||
|
timeoutTimer->setInterval(1000);
|
||||||
|
testerTimer = new QTimer();
|
||||||
|
testerTimer->setInterval(2000);
|
||||||
|
progressTimer = new QElapsedTimer();
|
||||||
|
|
||||||
|
int numBuses = CANConManager::getInstance()->getNumBuses();
|
||||||
|
ui->spinBus->setMaximum(numBuses > 0 ? numBuses - 1 : 0);
|
||||||
|
|
||||||
|
connect(ui->btnLoadFile, &QPushButton::clicked, this, &UDSFirmwareUploaderWindow::handleLoadFile);
|
||||||
|
connect(ui->btnStartStop, &QPushButton::clicked, this, &UDSFirmwareUploaderWindow::handleStartStop);
|
||||||
|
connect(ui->btnAbort, &QPushButton::clicked, this, &UDSFirmwareUploaderWindow::handleAbort);
|
||||||
|
connect(udsHandler, &UDS_HANDLER::newUDSMessage, this, &UDSFirmwareUploaderWindow::gotUDSReply);
|
||||||
|
connect(timeoutTimer, &QTimer::timeout, this, &UDSFirmwareUploaderWindow::timeoutTriggered);
|
||||||
|
connect(testerTimer, &QTimer::timeout, this, &UDSFirmwareUploaderWindow::testerPresentTick);
|
||||||
|
}
|
||||||
|
|
||||||
|
UDSFirmwareUploaderWindow::~UDSFirmwareUploaderWindow()
|
||||||
|
{
|
||||||
|
stopUpload();
|
||||||
|
delete testerTimer;
|
||||||
|
delete timeoutTimer;
|
||||||
|
delete udsHandler;
|
||||||
|
delete progressTimer;
|
||||||
|
delete ui;
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::logMessage(const QString &msg)
|
||||||
|
{
|
||||||
|
QString timestamp = QDateTime::currentDateTime().toString("hh:mm:ss.zzz");
|
||||||
|
ui->txtLog->append("[" + timestamp + "] " + msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::setState(UPLOAD_STATE newState)
|
||||||
|
{
|
||||||
|
currentState = newState;
|
||||||
|
if (newState == STATE_ERROR || newState == STATE_COMPLETE || newState == STATE_IDLE)
|
||||||
|
{
|
||||||
|
timeoutTimer->stop();
|
||||||
|
testerTimer->stop();
|
||||||
|
ui->btnStartStop->setEnabled(true);
|
||||||
|
ui->btnAbort->setEnabled(false);
|
||||||
|
ui->btnLoadFile->setEnabled(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::handleLoadFile()
|
||||||
|
{
|
||||||
|
QFileDialog dialog;
|
||||||
|
QStringList filters;
|
||||||
|
filters.append("Binary Firmware (*.bin)");
|
||||||
|
filters.append("All Files (*)");
|
||||||
|
dialog.setFileMode(QFileDialog::ExistingFile);
|
||||||
|
dialog.setNameFilters(filters);
|
||||||
|
|
||||||
|
if (dialog.exec() == QDialog::Accepted)
|
||||||
|
{
|
||||||
|
QString filename = dialog.selectedFiles().constFirst();
|
||||||
|
QFile inFile(filename);
|
||||||
|
if (!inFile.open(QIODevice::ReadOnly))
|
||||||
|
{
|
||||||
|
logMessage("ERROR: Could not open file: " + filename);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
firmwareData = inFile.readAll();
|
||||||
|
firmwareSize = firmwareData.length();
|
||||||
|
inFile.close();
|
||||||
|
ui->lblFilename->setText(filename + QString(" (%1 bytes)").arg(firmwareSize));
|
||||||
|
logMessage("Loaded firmware: " + filename + " (" + QString::number(firmwareSize) + " bytes)");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::handleStartStop()
|
||||||
|
{
|
||||||
|
if (currentState != STATE_IDLE && currentState != STATE_COMPLETE && currentState != STATE_ERROR)
|
||||||
|
{
|
||||||
|
stopUpload();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
startUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::handleAbort()
|
||||||
|
{
|
||||||
|
stopUpload();
|
||||||
|
logMessage("Upload aborted by user");
|
||||||
|
setState(STATE_IDLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::startUpload()
|
||||||
|
{
|
||||||
|
if (firmwareData.isEmpty())
|
||||||
|
{
|
||||||
|
logMessage("ERROR: No firmware file loaded");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
busId = ui->spinBus->value();
|
||||||
|
targetId = Utility::ParseStringToNum(ui->txtTargetID->text());
|
||||||
|
responseId = Utility::ParseStringToNum(ui->txtResponseID->text());
|
||||||
|
flashAddr = Utility::ParseStringToNum(ui->txtFlashAddr->text());
|
||||||
|
securityLevel = ui->spinSecurityLevel->value();
|
||||||
|
useSecurity = ui->ckUseSecurity->isChecked();
|
||||||
|
|
||||||
|
if (ui->cbSessionType->currentIndex() == 0) sessionType = 0x02;
|
||||||
|
else sessionType = 0x03;
|
||||||
|
|
||||||
|
blockSequenceCounter = 0;
|
||||||
|
currentDataPos = 0;
|
||||||
|
|
||||||
|
ui->progressBar->setValue(0);
|
||||||
|
ui->btnStartStop->setEnabled(false);
|
||||||
|
ui->btnAbort->setEnabled(true);
|
||||||
|
ui->btnLoadFile->setEnabled(false);
|
||||||
|
|
||||||
|
udsHandler->setReception(true);
|
||||||
|
udsHandler->addFilter(busId, responseId, 0x7FF);
|
||||||
|
|
||||||
|
logMessage("Starting UDS firmware upload...");
|
||||||
|
logMessage(QString("Target: 0x%1, Response: 0x%2, Bus: %3")
|
||||||
|
.arg(targetId, 0, 16).arg(responseId, 0, 16).arg(busId));
|
||||||
|
logMessage(QString("Flash Address: 0x%1, Size: %2 bytes")
|
||||||
|
.arg(flashAddr, 0, 16).arg(firmwareSize));
|
||||||
|
|
||||||
|
sendDiagSession();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::stopUpload(bool resetState)
|
||||||
|
{
|
||||||
|
timeoutTimer->stop();
|
||||||
|
testerTimer->stop();
|
||||||
|
udsHandler->clearAllFilters();
|
||||||
|
udsHandler->setReception(false);
|
||||||
|
|
||||||
|
ui->btnStartStop->setEnabled(true);
|
||||||
|
ui->btnAbort->setEnabled(false);
|
||||||
|
ui->btnLoadFile->setEnabled(true);
|
||||||
|
|
||||||
|
if (resetState)
|
||||||
|
{
|
||||||
|
currentState = STATE_IDLE;
|
||||||
|
ui->btnStartStop->setText("Start Upload");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendDiagSession()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::DIAG_CONTROL;
|
||||||
|
msg.subFuncLen = 1;
|
||||||
|
msg.subFunc = sessionType;
|
||||||
|
|
||||||
|
logMessage("Sending Diagnostic Session Control (0x10) - Sub: 0x" + QString::number(sessionType, 16));
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_DIAG_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendSecuritySeed()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::SECURITY_ACCESS;
|
||||||
|
msg.subFuncLen = 1;
|
||||||
|
msg.subFunc = (securityLevel * 2) - 1;
|
||||||
|
|
||||||
|
logMessage("Requesting Security Seed (0x27) - Level: " + QString::number(securityLevel));
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_SEED);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendSecurityKey(const QByteArray &seed)
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::SECURITY_ACCESS;
|
||||||
|
msg.subFuncLen = 1;
|
||||||
|
msg.subFunc = securityLevel * 2;
|
||||||
|
msg.payload() = seed;
|
||||||
|
|
||||||
|
logMessage("Sending Security Key (0x27) - " + seed.toHex(' '));
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_KEY_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendRequestDownload()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::REQUEST_DOWNLOAD;
|
||||||
|
msg.subFuncLen = 0;
|
||||||
|
msg.subFunc = 0;
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
data.append(static_cast<char>(0x00));
|
||||||
|
uint32_t addr = flashAddr;
|
||||||
|
uint32_t size = firmwareSize;
|
||||||
|
|
||||||
|
int addrLen = 4;
|
||||||
|
int sizeLen = 4;
|
||||||
|
data[0] = (addrLen << 4) | sizeLen;
|
||||||
|
|
||||||
|
for (int i = addrLen - 1; i >= 0; i--)
|
||||||
|
data.append((addr >> (i * 8)) & 0xFF);
|
||||||
|
for (int i = sizeLen - 1; i >= 0; i--)
|
||||||
|
data.append((size >> (i * 8)) & 0xFF);
|
||||||
|
|
||||||
|
msg.payload() = data;
|
||||||
|
|
||||||
|
logMessage(QString("Sending Request Download (0x34) - Addr: 0x%1, Size: %2")
|
||||||
|
.arg(addr, 0, 16).arg(size));
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_DOWNLOAD_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendDataBlock()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::TRANSFER_DATA;
|
||||||
|
msg.subFuncLen = 0;
|
||||||
|
msg.subFunc = 0;
|
||||||
|
|
||||||
|
QByteArray data;
|
||||||
|
data.append(blockSequenceCounter & 0xFF);
|
||||||
|
|
||||||
|
int bytesToSend = firmwareSize - currentDataPos;
|
||||||
|
if (maxBlockLength > 0 && bytesToSend > maxBlockLength)
|
||||||
|
bytesToSend = maxBlockLength;
|
||||||
|
|
||||||
|
data.append(firmwareData.constData() + currentDataPos, bytesToSend);
|
||||||
|
msg.payload() = data;
|
||||||
|
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_DATA_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendTransferExit()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::REQ_TRANS_EXIT;
|
||||||
|
msg.subFuncLen = 0;
|
||||||
|
msg.subFunc = 0;
|
||||||
|
|
||||||
|
logMessage("Sending Request Transfer Exit (0x37)");
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_EXIT_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendECUReset()
|
||||||
|
{
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::ECU_RESET;
|
||||||
|
msg.subFuncLen = 1;
|
||||||
|
msg.subFunc = 0x01;
|
||||||
|
|
||||||
|
logMessage("Sending ECU Reset (0x11)");
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
setState(STATE_WAIT_RESET_RESP);
|
||||||
|
timeoutTimer->start();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::sendTesterPresent()
|
||||||
|
{
|
||||||
|
if (currentState != STATE_WAIT_DATA_RESP && currentState != STATE_WAIT_DOWNLOAD_RESP)
|
||||||
|
return;
|
||||||
|
|
||||||
|
UDS_MESSAGE msg;
|
||||||
|
msg.bus = busId;
|
||||||
|
msg.setFrameId(targetId);
|
||||||
|
msg.service = UDS_SERVICES::TESTER_PRESENT;
|
||||||
|
msg.subFuncLen = 1;
|
||||||
|
msg.subFunc = 0x80;
|
||||||
|
|
||||||
|
udsHandler->sendUDSFrame(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::handleNRC(int nrc)
|
||||||
|
{
|
||||||
|
QString desc = udsHandler->getNegativeResponseLong(nrc);
|
||||||
|
logMessage(QString("NEGATIVE RESPONSE: 0x%1 - %2").arg(nrc, 0, 16).arg(desc));
|
||||||
|
setState(STATE_ERROR);
|
||||||
|
stopUpload();
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::gotUDSReply(UDS_MESSAGE msg)
|
||||||
|
{
|
||||||
|
if (msg.frameId() != responseId) return;
|
||||||
|
if (msg.bus != busId) return;
|
||||||
|
|
||||||
|
const unsigned char *data = reinterpret_cast<const unsigned char *>(msg.payload().constData());
|
||||||
|
int dataLen = msg.payload().size();
|
||||||
|
|
||||||
|
if (msg.isErrorReply)
|
||||||
|
{
|
||||||
|
qDebug() << "UDS FW Upload: NRC service=" << msg.service << " subfunc=" << msg.subFunc;
|
||||||
|
handleNRC(msg.subFunc);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeoutTimer->stop();
|
||||||
|
|
||||||
|
switch (currentState)
|
||||||
|
{
|
||||||
|
case STATE_WAIT_DIAG_RESP:
|
||||||
|
{
|
||||||
|
logMessage("Diagnostic Session Control response received");
|
||||||
|
if (useSecurity)
|
||||||
|
{
|
||||||
|
sendSecuritySeed();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendRequestDownload();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_SEED:
|
||||||
|
{
|
||||||
|
logMessage("Security seed received (" + QString::number(dataLen) + " bytes)");
|
||||||
|
QByteArray seed;
|
||||||
|
seed.append(reinterpret_cast<const char *>(data), dataLen);
|
||||||
|
QByteArray key = seed;
|
||||||
|
for (int i = 0; i < key.size(); i++)
|
||||||
|
key[i] = ~key[i];
|
||||||
|
sendSecurityKey(key);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_KEY_RESP:
|
||||||
|
{
|
||||||
|
logMessage("Security access granted");
|
||||||
|
sendRequestDownload();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_DOWNLOAD_RESP:
|
||||||
|
{
|
||||||
|
if (dataLen > 1)
|
||||||
|
{
|
||||||
|
int sizeLen = data[0] >> 4;
|
||||||
|
maxBlockLength = 0;
|
||||||
|
for (int i = 0; i < sizeLen && (i + 1) < dataLen; i++)
|
||||||
|
{
|
||||||
|
maxBlockLength = (maxBlockLength << 8) | data[1 + i];
|
||||||
|
}
|
||||||
|
logMessage(QString("Download accepted. Max block size: %1 bytes").arg(maxBlockLength));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
maxBlockLength = 4096;
|
||||||
|
logMessage("Download accepted (no block size limit advertised)");
|
||||||
|
}
|
||||||
|
testerTimer->start();
|
||||||
|
sendDataBlock();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_DATA_RESP:
|
||||||
|
{
|
||||||
|
progressTimer->start();
|
||||||
|
currentDataPos += maxBlockLength > 0 ?
|
||||||
|
qMin(maxBlockLength, firmwareSize - currentDataPos) :
|
||||||
|
(firmwareSize - currentDataPos);
|
||||||
|
blockSequenceCounter++;
|
||||||
|
|
||||||
|
int progress = (currentDataPos * 100) / firmwareSize;
|
||||||
|
ui->progressBar->setValue(progress);
|
||||||
|
|
||||||
|
if (currentDataPos >= firmwareSize)
|
||||||
|
{
|
||||||
|
logMessage("All data blocks transferred");
|
||||||
|
testerTimer->stop();
|
||||||
|
sendTransferExit();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sendDataBlock();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_EXIT_RESP:
|
||||||
|
{
|
||||||
|
logMessage("Transfer exit confirmed");
|
||||||
|
sendECUReset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case STATE_WAIT_RESET_RESP:
|
||||||
|
{
|
||||||
|
logMessage("ECU reset acknowledged");
|
||||||
|
setState(STATE_COMPLETE);
|
||||||
|
stopUpload();
|
||||||
|
logMessage("*** Firmware upload complete! ***");
|
||||||
|
ui->progressBar->setValue(100);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::timeoutTriggered()
|
||||||
|
{
|
||||||
|
logMessage("TIMEOUT - No response received");
|
||||||
|
handleNRC(0x10);
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::testerPresentTick()
|
||||||
|
{
|
||||||
|
sendTesterPresent();
|
||||||
|
logMessage("Tester Present keep-alive sent");
|
||||||
|
}
|
||||||
|
|
||||||
|
void UDSFirmwareUploaderWindow::advanceState()
|
||||||
|
{
|
||||||
|
}
|
||||||
@@ -0,0 +1,89 @@
|
|||||||
|
#ifndef UDSFIRMWAREUPLOADERWINDOW_H
|
||||||
|
#define UDSFIRMWAREUPLOADERWINDOW_H
|
||||||
|
|
||||||
|
#include <QDialog>
|
||||||
|
#include <QTimer>
|
||||||
|
#include <QElapsedTimer>
|
||||||
|
#include "can_structs.h"
|
||||||
|
#include "bus_protocols/uds_handler.h"
|
||||||
|
|
||||||
|
namespace Ui {
|
||||||
|
class UDSFirmwareUploaderWindow;
|
||||||
|
}
|
||||||
|
|
||||||
|
enum UPLOAD_STATE
|
||||||
|
{
|
||||||
|
STATE_IDLE,
|
||||||
|
STATE_SEND_DIAG_SESSION,
|
||||||
|
STATE_WAIT_DIAG_RESP,
|
||||||
|
STATE_SEND_SECURITY_SEED,
|
||||||
|
STATE_WAIT_SEED,
|
||||||
|
STATE_SEND_SECURITY_KEY,
|
||||||
|
STATE_WAIT_KEY_RESP,
|
||||||
|
STATE_SEND_REQUEST_DOWNLOAD,
|
||||||
|
STATE_WAIT_DOWNLOAD_RESP,
|
||||||
|
STATE_SEND_DATA,
|
||||||
|
STATE_WAIT_DATA_RESP,
|
||||||
|
STATE_SEND_TRANSFER_EXIT,
|
||||||
|
STATE_WAIT_EXIT_RESP,
|
||||||
|
STATE_SEND_ECU_RESET,
|
||||||
|
STATE_WAIT_RESET_RESP,
|
||||||
|
STATE_COMPLETE,
|
||||||
|
STATE_ERROR
|
||||||
|
};
|
||||||
|
|
||||||
|
class UDSFirmwareUploaderWindow : public QDialog
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit UDSFirmwareUploaderWindow(const QVector<CANFrame> *frames, QWidget *parent = 0);
|
||||||
|
~UDSFirmwareUploaderWindow();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleLoadFile();
|
||||||
|
void handleStartStop();
|
||||||
|
void handleAbort();
|
||||||
|
void gotUDSReply(UDS_MESSAGE msg);
|
||||||
|
void timeoutTriggered();
|
||||||
|
void testerPresentTick();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void logMessage(const QString &msg);
|
||||||
|
void setState(UPLOAD_STATE newState);
|
||||||
|
void startUpload();
|
||||||
|
void stopUpload(bool resetState = true);
|
||||||
|
void sendDiagSession();
|
||||||
|
void sendSecuritySeed();
|
||||||
|
void sendSecurityKey(const QByteArray &seed);
|
||||||
|
void sendRequestDownload();
|
||||||
|
void sendDataBlock();
|
||||||
|
void sendTransferExit();
|
||||||
|
void sendECUReset();
|
||||||
|
void sendTesterPresent();
|
||||||
|
void handleNRC(int nrc);
|
||||||
|
void advanceState();
|
||||||
|
|
||||||
|
Ui::UDSFirmwareUploaderWindow *ui;
|
||||||
|
const QVector<CANFrame> *modelFrames;
|
||||||
|
UDS_HANDLER *udsHandler;
|
||||||
|
UPLOAD_STATE currentState;
|
||||||
|
QTimer *timeoutTimer;
|
||||||
|
QTimer *testerTimer;
|
||||||
|
QElapsedTimer *progressTimer;
|
||||||
|
|
||||||
|
QByteArray firmwareData;
|
||||||
|
int firmwareSize;
|
||||||
|
int busId;
|
||||||
|
uint32_t targetId;
|
||||||
|
uint32_t responseId;
|
||||||
|
int sessionType;
|
||||||
|
int securityLevel;
|
||||||
|
uint32_t flashAddr;
|
||||||
|
int blockSequenceCounter;
|
||||||
|
int maxBlockLength;
|
||||||
|
int currentDataPos;
|
||||||
|
bool useSecurity;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // UDSFIRMWAREUPLOADERWINDOW_H
|
||||||
@@ -1,106 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<ui version="4.0">
|
|
||||||
<class>FirmwareUploaderWindow</class>
|
|
||||||
<widget class="QDialog" name="FirmwareUploaderWindow">
|
|
||||||
<property name="geometry">
|
|
||||||
<rect>
|
|
||||||
<x>0</x>
|
|
||||||
<y>0</y>
|
|
||||||
<width>327</width>
|
|
||||||
<height>357</height>
|
|
||||||
</rect>
|
|
||||||
</property>
|
|
||||||
<property name="windowTitle">
|
|
||||||
<string>Firmware Updater</string>
|
|
||||||
</property>
|
|
||||||
<layout class="QVBoxLayout" name="verticalLayout">
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_2">
|
|
||||||
<property name="text">
|
|
||||||
<string>Loaded File:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLabel" name="lblFilename">
|
|
||||||
<property name="text">
|
|
||||||
<string/>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnLoadFile">
|
|
||||||
<property name="text">
|
|
||||||
<string>Load File</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label">
|
|
||||||
<property name="text">
|
|
||||||
<string>Device Token:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="txtToken"/>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_4">
|
|
||||||
<property name="text">
|
|
||||||
<string>CAN Bus:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QSpinBox" name="spinBus"/>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="label_3">
|
|
||||||
<property name="text">
|
|
||||||
<string>Base Address:</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QLineEdit" name="txtBaseAddr"/>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<spacer name="verticalSpacer">
|
|
||||||
<property name="orientation">
|
|
||||||
<enum>Qt::Vertical</enum>
|
|
||||||
</property>
|
|
||||||
<property name="sizeHint" stdset="0">
|
|
||||||
<size>
|
|
||||||
<width>20</width>
|
|
||||||
<height>40</height>
|
|
||||||
</size>
|
|
||||||
</property>
|
|
||||||
</spacer>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QProgressBar" name="progressBar">
|
|
||||||
<property name="value">
|
|
||||||
<number>0</number>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item alignment="Qt::AlignHCenter">
|
|
||||||
<widget class="QLabel" name="lblProgress">
|
|
||||||
<property name="text">
|
|
||||||
<string>X of Y bytes</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
<item>
|
|
||||||
<widget class="QPushButton" name="btnStartStop">
|
|
||||||
<property name="text">
|
|
||||||
<string>Start Upload</string>
|
|
||||||
</property>
|
|
||||||
</widget>
|
|
||||||
</item>
|
|
||||||
</layout>
|
|
||||||
</widget>
|
|
||||||
<resources/>
|
|
||||||
<connections/>
|
|
||||||
</ui>
|
|
||||||
+19
-14
@@ -43,7 +43,7 @@
|
|||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
</property>
|
</property>
|
||||||
<property name="verticalScrollMode">
|
<property name="verticalScrollMode">
|
||||||
<enum>QAbstractItemView::ScrollPerPixel</enum>
|
<enum>QAbstractItemView::ScrollMode::ScrollPerPixel</enum>
|
||||||
</property>
|
</property>
|
||||||
<property name="wordWrap">
|
<property name="wordWrap">
|
||||||
<bool>false</bool>
|
<bool>false</bool>
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
<string>Remote Connection Active:</string>
|
<string>Remote Connection Active:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -99,7 +99,7 @@
|
|||||||
<number>8</number>
|
<number>8</number>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
|
||||||
</property>
|
</property>
|
||||||
<property name="readOnly">
|
<property name="readOnly">
|
||||||
<bool>true</bool>
|
<bool>true</bool>
|
||||||
@@ -156,11 +156,11 @@
|
|||||||
<string/>
|
<string/>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||||
<widget class="QLabel" name="label">
|
<widget class="QLabel" name="label">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@@ -173,7 +173,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||||
<widget class="QLabel" name="lbNumFrames">
|
<widget class="QLabel" name="lbNumFrames">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@@ -186,7 +186,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||||
<widget class="QLabel" name="label_6">
|
<widget class="QLabel" name="label_6">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@@ -199,7 +199,7 @@
|
|||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item alignment="Qt::AlignHCenter">
|
<item alignment="Qt::AlignmentFlag::AlignHCenter">
|
||||||
<widget class="QLabel" name="lbFPS">
|
<widget class="QLabel" name="lbFPS">
|
||||||
<property name="sizePolicy">
|
<property name="sizePolicy">
|
||||||
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
|
||||||
@@ -263,7 +263,7 @@
|
|||||||
<item>
|
<item>
|
||||||
<widget class="Line" name="line">
|
<widget class="Line" name="line">
|
||||||
<property name="orientation">
|
<property name="orientation">
|
||||||
<enum>Qt::Horizontal</enum>
|
<enum>Qt::Orientation::Horizontal</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -294,7 +294,7 @@
|
|||||||
<string>Bus Filtering:</string>
|
<string>Bus Filtering:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
</size>
|
</size>
|
||||||
</property>
|
</property>
|
||||||
<property name="flow">
|
<property name="flow">
|
||||||
<enum>QListView::LeftToRight</enum>
|
<enum>QListView::Flow::LeftToRight</enum>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -323,7 +323,7 @@
|
|||||||
<string>Frame Filtering:</string>
|
<string>Frame Filtering:</string>
|
||||||
</property>
|
</property>
|
||||||
<property name="alignment">
|
<property name="alignment">
|
||||||
<set>Qt::AlignCenter</set>
|
<set>Qt::AlignmentFlag::AlignCenter</set>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -382,7 +382,7 @@
|
|||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>1177</width>
|
<width>1177</width>
|
||||||
<height>26</height>
|
<height>20</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
<widget class="QMenu" name="menu_RE_Tools">
|
<widget class="QMenu" name="menu_RE_Tools">
|
||||||
@@ -411,7 +411,7 @@
|
|||||||
<addaction name="actionScripting_INterface"/>
|
<addaction name="actionScripting_INterface"/>
|
||||||
<addaction name="actionFuzzing"/>
|
<addaction name="actionFuzzing"/>
|
||||||
<addaction name="actionUDS_Scanner"/>
|
<addaction name="actionUDS_Scanner"/>
|
||||||
<addaction name="actionFirmware_Update"/>
|
<addaction name="actionUDS_Firmware_Update"/>
|
||||||
<addaction name="actionMotorControlConfig"/>
|
<addaction name="actionMotorControlConfig"/>
|
||||||
<addaction name="actionCAN_Bridge"/>
|
<addaction name="actionCAN_Bridge"/>
|
||||||
</widget>
|
</widget>
|
||||||
@@ -641,6 +641,11 @@
|
|||||||
<string>CAN Bridge</string>
|
<string>CAN Bridge</string>
|
||||||
</property>
|
</property>
|
||||||
</action>
|
</action>
|
||||||
|
<action name="actionUDS_Firmware_Update">
|
||||||
|
<property name="text">
|
||||||
|
<string>UDS Firmware Update</string>
|
||||||
|
</property>
|
||||||
|
</action>
|
||||||
</widget>
|
</widget>
|
||||||
<layoutdefault spacing="6" margin="11"/>
|
<layoutdefault spacing="6" margin="11"/>
|
||||||
<resources/>
|
<resources/>
|
||||||
|
|||||||
@@ -0,0 +1,181 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<ui version="4.0">
|
||||||
|
<class>UDSFirmwareUploaderWindow</class>
|
||||||
|
<widget class="QDialog" name="UDSFirmwareUploaderWindow">
|
||||||
|
<property name="geometry">
|
||||||
|
<rect>
|
||||||
|
<x>0</x>
|
||||||
|
<y>0</y>
|
||||||
|
<width>520</width>
|
||||||
|
<height>520</height>
|
||||||
|
</rect>
|
||||||
|
</property>
|
||||||
|
<property name="windowTitle">
|
||||||
|
<string>UDS Firmware Uploader</string>
|
||||||
|
</property>
|
||||||
|
<layout class="QVBoxLayout" name="verticalLayout">
|
||||||
|
<item>
|
||||||
|
<layout class="QFormLayout" name="formLayout">
|
||||||
|
<item row="0" column="0">
|
||||||
|
<widget class="QLabel" name="labelBus">
|
||||||
|
<property name="text">
|
||||||
|
<string>CAN Bus:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="0" column="1">
|
||||||
|
<widget class="QSpinBox" name="spinBus"/>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="0">
|
||||||
|
<widget class="QLabel" name="labelTargetID">
|
||||||
|
<property name="text">
|
||||||
|
<string>Target Request ID:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="1" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtTargetID">
|
||||||
|
<property name="text">
|
||||||
|
<string>0x7E0</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="0">
|
||||||
|
<widget class="QLabel" name="labelRespID">
|
||||||
|
<property name="text">
|
||||||
|
<string>Target Response ID:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="2" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtResponseID">
|
||||||
|
<property name="text">
|
||||||
|
<string>0x7E8</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="0">
|
||||||
|
<widget class="QLabel" name="labelSession">
|
||||||
|
<property name="text">
|
||||||
|
<string>Session Type:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="3" column="1">
|
||||||
|
<widget class="QComboBox" name="cbSessionType">
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Programming (0x02)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<property name="text">
|
||||||
|
<string>Extended (0x03)</string>
|
||||||
|
</property>
|
||||||
|
</item>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="0">
|
||||||
|
<widget class="QLabel" name="labelSecurity">
|
||||||
|
<property name="text">
|
||||||
|
<string>Security Level:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="4" column="1">
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||||
|
<item>
|
||||||
|
<widget class="QSpinBox" name="spinSecurityLevel">
|
||||||
|
<property name="minimum">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
<property name="maximum">
|
||||||
|
<number>255</number>
|
||||||
|
</property>
|
||||||
|
<property name="value">
|
||||||
|
<number>1</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="ckUseSecurity">
|
||||||
|
<property name="text">
|
||||||
|
<string>Enable Security</string>
|
||||||
|
</property>
|
||||||
|
<property name="checked">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="0">
|
||||||
|
<widget class="QLabel" name="labelAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>Flash Address:</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item row="5" column="1">
|
||||||
|
<widget class="QLineEdit" name="txtFlashAddr">
|
||||||
|
<property name="text">
|
||||||
|
<string>0x08000000</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnLoadFile">
|
||||||
|
<property name="text">
|
||||||
|
<string>Load Firmware File...</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QLabel" name="lblFilename">
|
||||||
|
<property name="text">
|
||||||
|
<string>No file loaded</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QTextEdit" name="txtLog">
|
||||||
|
<property name="readOnly">
|
||||||
|
<bool>true</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QProgressBar" name="progressBar">
|
||||||
|
<property name="value">
|
||||||
|
<number>0</number>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnStartStop">
|
||||||
|
<property name="text">
|
||||||
|
<string>Start Upload</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="QPushButton" name="btnAbort">
|
||||||
|
<property name="text">
|
||||||
|
<string>Abort</string>
|
||||||
|
</property>
|
||||||
|
<property name="enabled">
|
||||||
|
<bool>false</bool>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</widget>
|
||||||
|
<resources/>
|
||||||
|
<connections/>
|
||||||
|
</ui>
|
||||||
Reference in New Issue
Block a user