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:
Collin Kidder
2026-05-13 20:46:53 -04:00
parent ad65cf78a8
commit 035b65243b
10 changed files with 771 additions and 435 deletions
+4 -4
View File
@@ -56,7 +56,6 @@ SOURCES += main.cpp\
framesenderwindow.cpp \
framefileio.cpp \
mainsettingsdialog.cpp \
firmwareuploaderwindow.cpp \
scriptingwindow.cpp \
scriptcontainer.cpp \
canfilter.cpp \
@@ -104,6 +103,7 @@ SOURCES += main.cpp\
re/sniffer/SnifferDelegate.cpp \
connections/newconnectiondialog.cpp \
re/temporalgraphwindow.cpp \
re/udsfirmwareuploaderwindow.cpp \
filterutility.cpp \
pcaplite.cpp
@@ -151,7 +151,6 @@ HEADERS += mainwindow.h \
framefileio.h \
config.h \
mainsettingsdialog.h \
firmwareuploaderwindow.h \
scriptingwindow.h \
scriptcontainer.h \
canfilter.h \
@@ -199,6 +198,7 @@ HEADERS += mainwindow.h \
re/sniffer/SnifferDelegate.h \
connections/newconnectiondialog.h \
re/temporalgraphwindow.h \
re/udsfirmwareuploaderwindow.h \
filterutility.h \
pcaplite.h
@@ -216,7 +216,6 @@ FORMS += ui/candatagrid.ui \
ui/dbcnodeeditor.ui \
ui/discretestatewindow.ui \
ui/filecomparatorwindow.ui \
ui/firmwareuploaderwindow.ui \
ui/flowviewwindow.ui \
ui/frameinfowindow.ui \
ui/frameplaybackwindow.ui \
@@ -236,7 +235,8 @@ FORMS += ui/candatagrid.ui \
ui/signalviewerwindow.ui \
ui/helpwindow.ui \
ui/newconnectiondialog.ui \
ui/temporalgraphwindow.ui
ui/temporalgraphwindow.ui \
ui/udsfirmwareuploaderwindow.ui
RESOURCES += \
icons.qrc \
-250
View File
@@ -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();
}
-50
View File
@@ -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
View File
@@ -80,7 +80,7 @@ MainWindow::MainWindow(QWidget *parent) :
dbcMainEditor = nullptr;
comparatorWindow = nullptr;
settingsDialog = nullptr;
firmwareUploaderWindow = nullptr;
udsFirmwareUploaderWindow = nullptr;
discreteStateWindow = nullptr;
connectionWindow = nullptr;
scriptingWindow = nullptr;
@@ -126,7 +126,7 @@ MainWindow::MainWindow(QWidget *parent) :
connect(ui->actionDBC_Comparison, &QAction::triggered, this, &MainWindow::showDBCComparisonWindow);
connect(ui->actionScripting_INterface, &QAction::triggered, this, &MainWindow::showScriptingWindow);
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->actionFuzzing, &QAction::triggered, this, &MainWindow::showFuzzingWindow);
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
//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->actionSingle_Multi_State_2->setVisible(false);
@@ -288,7 +288,7 @@ void MainWindow::killEmAll()
killWindow(isoWindow);
killWindow(snifferWindow);
killWindow(bisectWindow);
killWindow(firmwareUploaderWindow);
killWindow(udsFirmwareUploaderWindow);
killWindow(motorctrlConfigWindow);
killWindow(signalViewerWindow);
killWindow(temporalGraphWindow);
@@ -1720,13 +1720,13 @@ void MainWindow::showPlaybackWindow()
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()
+3 -3
View File
@@ -20,7 +20,6 @@
#include "re/filecomparatorwindow.h"
#include "dbc/dbcmaineditor.h"
#include "mainsettingsdialog.h"
#include "firmwareuploaderwindow.h"
#include "re/discretestatewindow.h"
#include "scriptingwindow.h"
#include "re/rangestatewindow.h"
@@ -33,6 +32,7 @@
#include "signalviewerwindow.h"
#include "re/temporalgraphwindow.h"
#include "re/dbccomparatorwindow.h"
#include "re/udsfirmwareuploaderwindow.h"
#include "canbridgewindow.h"
class CANConnection;
@@ -89,7 +89,7 @@ private slots:
void showFuzzyScopeWindow();
void showComparisonWindow();
void showSettingsDialog();
void showFirmwareUploaderWindow();
void showUDSFirmwareUploaderWindow();
void showConnectionSettingsWindow();
void showScriptingWindow();
void showDBCFileWindow();
@@ -184,7 +184,7 @@ private:
FileComparatorWindow *comparatorWindow;
MainSettingsDialog *settingsDialog;
DiscreteStateWindow *discreteStateWindow;
FirmwareUploaderWindow *firmwareUploaderWindow;
UDSFirmwareUploaderWindow *udsFirmwareUploaderWindow;
ConnectionWindow *connectionWindow;
ScriptingWindow *scriptingWindow;
RangeStateWindow *rangeWindow;
+467
View File
@@ -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()
{
}
+89
View File
@@ -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
-106
View File
@@ -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
View File
@@ -43,7 +43,7 @@
<bool>true</bool>
</property>
<property name="verticalScrollMode">
<enum>QAbstractItemView::ScrollPerPixel</enum>
<enum>QAbstractItemView::ScrollMode::ScrollPerPixel</enum>
</property>
<property name="wordWrap">
<bool>false</bool>
@@ -69,7 +69,7 @@
<string>Remote Connection Active:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
@@ -99,7 +99,7 @@
<number>8</number>
</property>
<property name="alignment">
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
<set>Qt::AlignmentFlag::AlignLeading|Qt::AlignmentFlag::AlignLeft|Qt::AlignmentFlag::AlignVCenter</set>
</property>
<property name="readOnly">
<bool>true</bool>
@@ -156,11 +156,11 @@
<string/>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<item alignment="Qt::AlignmentFlag::AlignHCenter">
<widget class="QLabel" name="label">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -173,7 +173,7 @@
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<item alignment="Qt::AlignmentFlag::AlignHCenter">
<widget class="QLabel" name="lbNumFrames">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -186,7 +186,7 @@
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<item alignment="Qt::AlignmentFlag::AlignHCenter">
<widget class="QLabel" name="label_6">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -199,7 +199,7 @@
</property>
</widget>
</item>
<item alignment="Qt::AlignHCenter">
<item alignment="Qt::AlignmentFlag::AlignHCenter">
<widget class="QLabel" name="lbFPS">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
@@ -263,7 +263,7 @@
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
<enum>Qt::Orientation::Horizontal</enum>
</property>
</widget>
</item>
@@ -294,7 +294,7 @@
<string>Bus Filtering:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
@@ -313,7 +313,7 @@
</size>
</property>
<property name="flow">
<enum>QListView::LeftToRight</enum>
<enum>QListView::Flow::LeftToRight</enum>
</property>
</widget>
</item>
@@ -323,7 +323,7 @@
<string>Frame Filtering:</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
<set>Qt::AlignmentFlag::AlignCenter</set>
</property>
</widget>
</item>
@@ -382,7 +382,7 @@
<x>0</x>
<y>0</y>
<width>1177</width>
<height>26</height>
<height>20</height>
</rect>
</property>
<widget class="QMenu" name="menu_RE_Tools">
@@ -411,7 +411,7 @@
<addaction name="actionScripting_INterface"/>
<addaction name="actionFuzzing"/>
<addaction name="actionUDS_Scanner"/>
<addaction name="actionFirmware_Update"/>
<addaction name="actionUDS_Firmware_Update"/>
<addaction name="actionMotorControlConfig"/>
<addaction name="actionCAN_Bridge"/>
</widget>
@@ -641,6 +641,11 @@
<string>CAN Bridge</string>
</property>
</action>
<action name="actionUDS_Firmware_Update">
<property name="text">
<string>UDS Firmware Update</string>
</property>
</action>
</widget>
<layoutdefault spacing="6" margin="11"/>
<resources/>
+181
View File
@@ -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>