From 2b521c4aaafbc97ca2b3c1fcc29cff2e1eabc58f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jan=20K=C3=A4berich?= Date: Mon, 22 Apr 2024 13:21:41 +0200 Subject: [PATCH] Add firmware update command --- .../Device/LibreVNA/firmwareupdatedialog.cpp | 44 ++++++++++++++++--- .../Device/LibreVNA/firmwareupdatedialog.h | 5 +++ .../Device/LibreVNA/librevnadriver.cpp | 5 +++ .../Device/LibreVNA/librevnadriver.h | 1 + .../LibreVNA-GUI/Device/devicedriver.h | 1 + .../PC_Application/LibreVNA-GUI/appwindow.cpp | 17 +++++++ 6 files changed, 67 insertions(+), 6 deletions(-) diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp index a220e8d..e001b0b 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.cpp @@ -14,13 +14,16 @@ FirmwareUpdateDialog::FirmwareUpdateDialog(LibreVNADriver *dev, QWidget *parent) file(), timer(), state(State::Idle), - transferredBytes(0) + transferredBytes(0), + success(false), + deleteAfterUpdate(true) { dev->acquireControl(); setAttribute(Qt::WA_DeleteOnClose); ui->setupUi(this); ui->bFile->setIcon(this->style()->standardPixmap(QStyle::SP_FileDialogStart)); ui->bStart->setIcon(this->style()->standardPixmap(QStyle::SP_MediaPlay)); + connect(ui->lFile, &QLineEdit::textChanged, this, &FirmwareUpdateDialog::reloadFile); connect(&timer, &QTimer::timeout, this, &FirmwareUpdateDialog::timerCallback); } @@ -30,20 +33,41 @@ FirmwareUpdateDialog::~FirmwareUpdateDialog() delete ui; } +bool FirmwareUpdateDialog::FirmwareUpdate(LibreVNADriver *dev, QString file) +{ + FirmwareUpdateDialog d(dev); + d.deleteAfterUpdate = false; + d.ui->lFile->setText(file); + d.reloadFile(); + d.on_bStart_clicked(); + d.show(); + QEventLoop loop; + while(d.state != State::Idle) { + loop.processEvents(QEventLoop::AllEvents, 100); + } + return d.success; +} + void FirmwareUpdateDialog::on_bFile_clicked() { ui->bStart->setEnabled(false); auto filename = QFileDialog::getOpenFileName(nullptr, "Open firmware file", "", "Firmware file (*.vnafw)", nullptr, QFileDialog::DontUseNativeDialog); if (filename.length() > 0) { ui->lFile->setText(filename); - delete file; - file = new QFile(filename); - ui->bStart->setEnabled(true); + reloadFile(); } } +void FirmwareUpdateDialog::reloadFile() +{ + delete file; + file = new QFile(ui->lFile->text()); + ui->bStart->setEnabled(false); +} + void FirmwareUpdateDialog::on_bStart_clicked() { + success = false; ui->status->clear(); ui->bStart->setEnabled(false); if(!file->isOpen()) { @@ -113,6 +137,7 @@ void FirmwareUpdateDialog::abortWithError(QString error) tf.setForeground(QBrush(Qt::black)); ui->status->setCurrentCharFormat(tf); ui->bStart->setEnabled(true); + success = false; state = State::Idle; } @@ -133,8 +158,15 @@ void FirmwareUpdateDialog::timerCallback() case State::WaitBeforeInitializing: // Device had enough time to initialize, indicate that rebooted device is ready timer.stop(); - dev->connectDevice(serialnumber); - delete this; + if(dev->connectDevice(serialnumber)) { + success = true; + if(deleteAfterUpdate) { + delete this; + } + } else { + abortWithError("Failed to connect to updated device"); + } + state = State::Idle; break; default: abortWithError("Response timed out"); diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h index ebcd459..f1577f7 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/firmwareupdatedialog.h @@ -26,12 +26,15 @@ public: explicit FirmwareUpdateDialog(LibreVNADriver *dev, QWidget *parent = nullptr); ~FirmwareUpdateDialog(); + static bool FirmwareUpdate(LibreVNADriver *dev, QString file); + signals: void DeviceRebooting(); // emitted when the update process is triggered, the device should be disconnected void DeviceRebooted(QString serial); // emitted when an updated device is enumerated after the update private slots: void on_bFile_clicked(); + void reloadFile(); void on_bStart_clicked(); void timerCallback(); void receivedAck(); @@ -57,6 +60,8 @@ private: State state; unsigned int transferredBytes; QString serialnumber; + bool success; + bool deleteAfterUpdate; }; #endif // FIRMWAREUPDATEDIALOG_H diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp index 9545c21..ee21e7e 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.cpp @@ -731,3 +731,8 @@ bool LibreVNADriver::sendWithoutPayload(Protocol::PacketType type, std::function p.type = type; return SendPacket(p, cb); } + +bool LibreVNADriver::updateFirmware(QString file) +{ + return FirmwareUpdateDialog::FirmwareUpdate(this, file); +} diff --git a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.h b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.h index 4c0014c..3599d5a 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.h +++ b/Software/PC_Application/LibreVNA-GUI/Device/LibreVNA/librevnadriver.h @@ -179,6 +179,7 @@ signals: public: virtual bool SendPacket(const Protocol::PacketInfo& packet, std::function cb = nullptr, unsigned int timeout = 500) = 0; bool sendWithoutPayload(Protocol::PacketType type, std::function cb = nullptr); + virtual bool updateFirmware(QString file) override; unsigned int getMaxAmplitudePoints() const; diff --git a/Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h b/Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h index f2b3d38..3581694 100644 --- a/Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h +++ b/Software/PC_Application/LibreVNA-GUI/Device/devicedriver.h @@ -489,6 +489,7 @@ signals: public: bool connectDevice(QString serial, bool isIndepedentDriver = false); void disconnectDevice(); + virtual bool updateFirmware(QString file) {Q_UNUSED(file) return false;} static DeviceDriver* getActiveDriver() {return activeDriver;} static unsigned int SApoints(); diff --git a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp index 487fcf7..7c6c6ec 100644 --- a/Software/PC_Application/LibreVNA-GUI/appwindow.cpp +++ b/Software/PC_Application/LibreVNA-GUI/appwindow.cpp @@ -508,6 +508,23 @@ void AppWindow::SetupSCPI() return "Not connected"; } })); + scpi_dev->add(new SCPICommand("UPDATE", [=](QStringList params) -> QString { + if(params.size() != 1) { + // no file given + return SCPI::getResultName(SCPI::Result::Error); + } + if(!device) { + // not connected to any device + return SCPI::getResultName(SCPI::Result::Error); + } + if(!device->updateFirmware(params[0])) { + // update failed + return SCPI::getResultName(SCPI::Result::Error); + } else { + // update succeeded + return SCPI::getResultName(SCPI::Result::Empty); + } + }, nullptr, false)); scpi_dev->add(new SCPICommand("LIST", nullptr, [=](QStringList) -> QString { QString ret; for(auto driver : DeviceDriver::getDrivers()) {