Files
edgetx-gx12/companion/src/flashfirmwaredialog.cpp
T
Romolo Manfredini dc5e36c543 Implement profile specific settings for backup folder.
Profile backup path if set overrides general one, in any case the backup will be performed if either profile specific setting or general settings ones are enabled.
Disabling backup in profile will not disable backups if generic settings are enabled
2015-05-02 12:58:46 +02:00

319 lines
9.4 KiB
C++
Executable File

#include "flashfirmwaredialog.h"
#include "ui_flashfirmwaredialog.h"
#include "appdata.h"
#include "converteeprom.h"
#include "eeprominterface.h"
#include "firmwareinterface.h"
#include "process_flash.h"
#include "helpers.h"
#include "hexinterface.h"
#include "progressdialog.h"
#include "radiointerface.h"
#include "splashlibrary.h"
#include "progresswidget.h"
#if defined WIN32 || !defined __GNUC__
#include <windows.h>
#define sleep(x) Sleep(x*1000)
#else
#include <unistd.h>
#endif
FlashFirmwareDialog::FlashFirmwareDialog(QWidget *parent):
QDialog(parent),
ui(new Ui::FlashFirmwareDialog),
fwName(g.profile[g.id()].fwName())
{
ui->setupUi(this);
if (!g.profile[g.id()].splashFile().isEmpty()){
imageSource = PROFILE;
imageFile = g.profile[g.id()].splashFile();
ui->useProfileSplash->setChecked(true);
}
else {
imageSource = FIRMWARE;
imageFile = "";
ui->useProfileSplash->setDisabled(true);
}
if (IS_TARANIS(GetEepromInterface()->getBoard())) {
// No backup on Taranis ... could be done if in massstorage
ui->backupEEprom->hide();
ui->backupEEprom->setCheckState(Qt::Unchecked);
}
else {
ui->backupEEprom->setCheckState(g.backupOnFlash() ? Qt::Checked : Qt::Unchecked);
}
QString backupPath = g.profile[g.id()].pBackupDir();
if (backupPath.isEmpty()) {
backupPath=g.backupDir();
}
if (backupPath.isEmpty() || !QDir(backupPath).exists()) {
ui->backupEEprom->setEnabled(false);
}
ui->checkHardwareCompatibility->setChecked(g.checkHardwareCompatibility());
updateUI();
resize(0, 0); // TODO needed?
}
FlashFirmwareDialog::~FlashFirmwareDialog()
{
delete ui;
}
void FlashFirmwareDialog::updateUI()
{
ui->firmwareFilename->setText(fwName);
ui->burnButton->setEnabled(QFile(fwName).exists());
FirmwareInterface firmware(fwName);
if (firmware.isValid()) {
ui->firmwareInfoFrame->show();
ui->date->setText(firmware.getDate() + " " + firmware.getTime());
ui->version->setText(firmware.getVersion());
ui->variant->setText(firmware.getEEpromId());
ui->date->setEnabled(true);
ui->version->setEnabled(true);
ui->variant->setEnabled(true);
if (firmware.hasSplash()) {
ui->splashFrame->show();
ui->splash->setFixedSize(firmware.getSplashWidth(), firmware.getSplashHeight());
}
else {
ui->splashFrame->hide();
}
}
else {
imageSource = FIRMWARE;
ui->firmwareInfoFrame->hide();
ui->splashFrame->hide();
}
QImage image;
switch(imageSource) {
case FIRMWARE:
ui->useFirmwareSplash->setChecked(true);
image = firmware.getSplash();
break;
case PROFILE:
ui->useProfileSplash->setChecked(true);
image.load(g.profile[g.id()].splashFile());
break;
case LIBRARY:
ui->useLibrarySplash->setChecked(true);
image.load(imageFile);
break;
case EXTERNAL:
ui->useExternalSplash->setChecked(true);
image.load(imageFile);
break;
}
if (!image.isNull()) {
ui->splash->setPixmap(makePixMap(image, g.profile[g.id()].fwType()));
}
}
void FlashFirmwareDialog::on_firmwareLoad_clicked()
{
QString fileName = QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g.flashDir(), FLASH_FILES_FILTER);
if (!fileName.isEmpty()) {
fwName = fileName;
if (!fwName.isEmpty() && !FirmwareInterface(fwName).isValid()) {
QMessageBox::warning(this, tr("Warning"), tr("%1 may not be a valid firmware file").arg(fwName));
}
updateUI();
}
}
void FlashFirmwareDialog::on_useFirmwareSplash_clicked()
{
FirmwareInterface firmware(fwName);
if (!firmware.isValid()) {
QMessageBox::warning(this, tr("Error"), tr( "The firmware file is not valid." ));
}
else if (!firmware.hasSplash()) {
QMessageBox::warning(this, tr("Error"), tr( "There is no start screen image in the firmware file." ));
}
else {
imageSource = FIRMWARE;
}
updateUI();
}
void FlashFirmwareDialog::on_useProfileSplash_clicked()
{
QString fileName = g.profile[g.id()].splashFile();
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("Profile image %1 is invalid.").arg(fileName));
}
else {
imageSource = PROFILE;
}
}
updateUI();
}
void FlashFirmwareDialog::on_useExternalSplash_clicked()
{
QString supportedImageFormats;
for (int formatIndex = 0; formatIndex < QImageReader::supportedImageFormats().count(); formatIndex++) {
supportedImageFormats += QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex];
}
QString fileName = QFileDialog::getOpenFileName(this, tr("Open image file to use as radio start screen"), g.imagesDir(), tr("Images (%1)").arg(supportedImageFormats));
if (!fileName.isEmpty()){
g.imagesDir( QFileInfo(fileName).dir().absolutePath() );
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("Image could not be loaded from %1").arg(fileName));
}
else{
imageSource = EXTERNAL;
imageFile = fileName;
}
}
updateUI();
}
void FlashFirmwareDialog::on_useLibrarySplash_clicked()
{
QString fileName;
splashLibrary *ld = new splashLibrary(this, &fileName);
ld->exec();
if (!fileName.isEmpty()) {
QImage image(fileName);
if (image.isNull()) {
QMessageBox::critical(this, tr("Error"), tr("The library image could not be loaded"));
}
else {
imageSource = LIBRARY;
imageFile = fileName;
}
}
updateUI();
}
void FlashFirmwareDialog::on_burnButton_clicked()
{
g.flashDir(QFileInfo(fwName).dir().absolutePath());
g.checkHardwareCompatibility(ui->checkHardwareCompatibility->isChecked());
g.backupOnFlash(ui->backupEEprom->isChecked());
qDebug() << "FlashFirmwareDialog: flashing" << fwName;
if (imageSource != FIRMWARE) {
// load the splash image
const QPixmap * pixmap = ui->splash->pixmap();
QImage image;
if (pixmap) {
image = pixmap->toImage().scaled(ui->splash->width(), ui->splash->height());
}
if (image.isNull()) {
QMessageBox::critical(this, tr("Warning"), tr("Splash image not found"));
return;
}
// write the customized firmware
QString tempFile;
if (getFileType(fwName) == FILE_TYPE_HEX)
tempFile = generateProcessUniqueTempFileName("flash.hex");
else
tempFile = generateProcessUniqueTempFileName("flash.bin");
qDebug() << "FlashFirmwareDialog: patching" << fwName << "with custom splash screen and saving to" << tempFile;
FirmwareInterface firmware(fwName);
firmware.setSplash(image);
if (firmware.save(tempFile) <= 0) {
QMessageBox::critical(this, tr("Warning"), tr("Cannot save customized firmware"));
return;
}
startFlash(tempFile);
}
else {
startFlash(fwName);
}
}
void FlashFirmwareDialog::on_cancelButton_clicked()
{
close();
}
void FlashFirmwareDialog::shrink()
{
resize(0, 0);
}
void FlashFirmwareDialog::startFlash(const QString &filename)
{
bool backup = g.backupOnFlash();
close();
ProgressDialog progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
// check hardware compatibility if requested
if (g.checkHardwareCompatibility()) {
QString tempFirmware = generateProcessUniqueTempFileName("flash-check.bin");
if (!readFirmware(tempFirmware, progressDialog.progress())) {
QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
return;
}
FirmwareInterface previousFirmware(tempFirmware);
qunlink(tempFirmware);
FirmwareInterface newFirmware(filename);
qDebug() << "startFlash: checking firmware compatibility between " << tempFirmware << "and" << filename;
if (!newFirmware.isHardwareCompatible(previousFirmware)) {
QMessageBox::warning(this, tr("Firmware check failed"), tr("New firmware is not compatible with the one currently installed!"));
if (isTempFileName(filename)) {
qDebug() << "startFlash: removing temporary file" << filename;
qunlink(filename);
}
return;
}
}
// backup if requested
bool result = true;
QString backupFilename;
QString backupPath;
if (backup) {
backupPath = g.profile[g.id()].pBackupDir();
if (backupPath.isEmpty()) {
backupPath=g.backupDir();
}
backupFilename = backupPath + "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
result = readEeprom(backupFilename, progressDialog.progress());
sleep(2);
}
// flash
result = (result && writeFirmware(filename, progressDialog.progress()));
// restore if backup requested
if (backup && result) {
sleep(2);
QString restoreFilename = generateProcessUniqueTempFileName("restore.bin");
if (!convertEEprom(backupFilename, restoreFilename, filename)) {
QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
restoreFilename = backupFilename;
}
if (!writeEeprom(restoreFilename, progressDialog.progress())) {
QMessageBox::warning(this, tr("Restore failed"), tr("Could not restore Models and Settings to Radio. The models and settings data file can be found at: %1").arg(backupFilename));
}
}
progressDialog.progress()->setInfo(tr("Flashing done"));
progressDialog.exec();
if (isTempFileName(filename)) {
qDebug() << "startFlash: removing temporary file" << filename;
qunlink(filename);
}
}