1 #include "flashfirmwaredialog.h"
2 #include "ui_flashfirmwaredialog.h"
4 #include "converteeprom.h"
5 #include "eeprominterface.h"
6 #include "firmwareinterface.h"
7 #include "process_flash.h"
9 #include "hexinterface.h"
10 #include "progressdialog.h"
11 #include "radiointerface.h"
12 #include "splashlibrary.h"
13 #include "progresswidget.h"
15 #if defined WIN32 || !defined __GNUC__
17 #define sleep(x) Sleep(x*1000)
22 FlashFirmwareDialog::FlashFirmwareDialog(QWidget
*parent
):
24 ui(new Ui::FlashFirmwareDialog
),
25 fwName(g
.profile
[g
.id()].fwName())
29 if (!g
.profile
[g
.id()].splashFile().isEmpty()){
30 imageSource
= PROFILE
;
31 imageFile
= g
.profile
[g
.id()].splashFile();
32 ui
->useProfileSplash
->setChecked(true);
35 imageSource
= FIRMWARE
;
37 ui
->useProfileSplash
->setDisabled(true);
40 if (IS_TARANIS(GetEepromInterface()->getBoard())) {
41 // No backup on Taranis ... could be done if in massstorage
42 ui
->backupEEprom
->hide();
43 ui
->backupEEprom
->setCheckState(Qt::Unchecked
);
46 ui
->backupEEprom
->setCheckState(g
.backupOnFlash() ? Qt::Checked
: Qt::Unchecked
);
49 QString backupPath
= g
.profile
[g
.id()].pBackupDir();
50 if (backupPath
.isEmpty()) {
51 backupPath
=g
.backupDir();
53 if (backupPath
.isEmpty() || !QDir(backupPath
).exists()) {
54 ui
->backupEEprom
->setEnabled(false);
57 ui
->checkHardwareCompatibility
->setChecked(g
.checkHardwareCompatibility());
61 resize(0, 0); // TODO needed?
64 FlashFirmwareDialog::~FlashFirmwareDialog()
69 void FlashFirmwareDialog::updateUI()
71 ui
->firmwareFilename
->setText(fwName
);
72 ui
->burnButton
->setEnabled(QFile(fwName
).exists());
74 FirmwareInterface
firmware(fwName
);
75 if (firmware
.isValid()) {
76 ui
->firmwareInfoFrame
->show();
77 ui
->date
->setText(firmware
.getDate() + " " + firmware
.getTime());
78 ui
->version
->setText(firmware
.getVersion());
79 ui
->variant
->setText(firmware
.getEEpromId());
80 ui
->date
->setEnabled(true);
81 ui
->version
->setEnabled(true);
82 ui
->variant
->setEnabled(true);
83 if (firmware
.hasSplash()) {
84 ui
->splashFrame
->show();
85 ui
->splash
->setFixedSize(firmware
.getSplashWidth(), firmware
.getSplashHeight());
88 ui
->splashFrame
->hide();
92 imageSource
= FIRMWARE
;
93 ui
->firmwareInfoFrame
->hide();
94 ui
->splashFrame
->hide();
100 ui
->useFirmwareSplash
->setChecked(true);
101 image
= firmware
.getSplash();
104 ui
->useProfileSplash
->setChecked(true);
105 image
.load(g
.profile
[g
.id()].splashFile());
108 ui
->useLibrarySplash
->setChecked(true);
109 image
.load(imageFile
);
112 ui
->useExternalSplash
->setChecked(true);
113 image
.load(imageFile
);
117 if (!image
.isNull()) {
118 ui
->splash
->setPixmap(makePixMap(image
, g
.profile
[g
.id()].fwType()));
122 void FlashFirmwareDialog::on_firmwareLoad_clicked()
124 QString fileName
= QFileDialog::getOpenFileName(this, tr("Open Firmware File"), g
.flashDir(), FLASH_FILES_FILTER
);
125 if (!fileName
.isEmpty()) {
127 if (!fwName
.isEmpty() && !FirmwareInterface(fwName
).isValid()) {
128 QMessageBox::warning(this, tr("Warning"), tr("%1 may not be a valid firmware file").arg(fwName
));
134 void FlashFirmwareDialog::on_useFirmwareSplash_clicked()
136 FirmwareInterface
firmware(fwName
);
137 if (!firmware
.isValid()) {
138 QMessageBox::warning(this, tr("Error"), tr( "The firmware file is not valid." ));
140 else if (!firmware
.hasSplash()) {
141 QMessageBox::warning(this, tr("Error"), tr( "There is no start screen image in the firmware file." ));
144 imageSource
= FIRMWARE
;
149 void FlashFirmwareDialog::on_useProfileSplash_clicked()
151 QString fileName
= g
.profile
[g
.id()].splashFile();
152 if (!fileName
.isEmpty()) {
153 QImage
image(fileName
);
154 if (image
.isNull()) {
155 QMessageBox::critical(this, tr("Error"), tr("Profile image %1 is invalid.").arg(fileName
));
158 imageSource
= PROFILE
;
164 void FlashFirmwareDialog::on_useExternalSplash_clicked()
166 QString supportedImageFormats
;
167 for (int formatIndex
= 0; formatIndex
< QImageReader::supportedImageFormats().count(); formatIndex
++) {
168 supportedImageFormats
+= QLatin1String(" *.") + QImageReader::supportedImageFormats()[formatIndex
];
170 QString fileName
= QFileDialog::getOpenFileName(this, tr("Open image file to use as radio start screen"), g
.imagesDir(), tr("Images (%1)").arg(supportedImageFormats
));
171 if (!fileName
.isEmpty()){
172 g
.imagesDir( QFileInfo(fileName
).dir().absolutePath() );
173 QImage
image(fileName
);
174 if (image
.isNull()) {
175 QMessageBox::critical(this, tr("Error"), tr("Image could not be loaded from %1").arg(fileName
));
178 imageSource
= EXTERNAL
;
179 imageFile
= fileName
;
185 void FlashFirmwareDialog::on_useLibrarySplash_clicked()
188 splashLibrary
*ld
= new splashLibrary(this, &fileName
);
190 if (!fileName
.isEmpty()) {
191 QImage
image(fileName
);
192 if (image
.isNull()) {
193 QMessageBox::critical(this, tr("Error"), tr("The library image could not be loaded"));
196 imageSource
= LIBRARY
;
197 imageFile
= fileName
;
203 void FlashFirmwareDialog::on_burnButton_clicked()
205 g
.flashDir(QFileInfo(fwName
).dir().absolutePath());
206 g
.checkHardwareCompatibility(ui
->checkHardwareCompatibility
->isChecked());
207 g
.backupOnFlash(ui
->backupEEprom
->isChecked());
209 qDebug() << "FlashFirmwareDialog: flashing" << fwName
;
211 if (imageSource
!= FIRMWARE
) {
212 // load the splash image
213 const QPixmap
* pixmap
= ui
->splash
->pixmap();
216 image
= pixmap
->toImage().scaled(ui
->splash
->width(), ui
->splash
->height());
218 if (image
.isNull()) {
219 QMessageBox::critical(this, tr("Warning"), tr("Splash image not found"));
222 // write the customized firmware
224 if (getFileType(fwName
) == FILE_TYPE_HEX
)
225 tempFile
= generateProcessUniqueTempFileName("flash.hex");
227 tempFile
= generateProcessUniqueTempFileName("flash.bin");
228 qDebug() << "FlashFirmwareDialog: patching" << fwName
<< "with custom splash screen and saving to" << tempFile
;
229 FirmwareInterface
firmware(fwName
);
230 firmware
.setSplash(image
);
231 if (firmware
.save(tempFile
) <= 0) {
232 QMessageBox::critical(this, tr("Warning"), tr("Cannot save customized firmware"));
235 startFlash(tempFile
);
242 void FlashFirmwareDialog::on_cancelButton_clicked()
247 void FlashFirmwareDialog::shrink()
252 void FlashFirmwareDialog::startFlash(const QString
&filename
)
254 bool backup
= g
.backupOnFlash();
258 ProgressDialog
progressDialog(this, tr("Write Firmware to Radio"), CompanionIcon("write_flash.png"));
260 // check hardware compatibility if requested
261 if (g
.checkHardwareCompatibility()) {
262 QString tempFirmware
= generateProcessUniqueTempFileName("flash-check.bin");
263 if (!readFirmware(tempFirmware
, progressDialog
.progress())) {
264 QMessageBox::warning(this, tr("Firmware check failed"), tr("Could not check firmware from radio"));
267 FirmwareInterface
previousFirmware(tempFirmware
);
268 qunlink(tempFirmware
);
269 FirmwareInterface
newFirmware(filename
);
270 qDebug() << "startFlash: checking firmware compatibility between " << tempFirmware
<< "and" << filename
;
271 if (!newFirmware
.isHardwareCompatible(previousFirmware
)) {
272 QMessageBox::warning(this, tr("Firmware check failed"), tr("New firmware is not compatible with the one currently installed!"));
273 if (isTempFileName(filename
)) {
274 qDebug() << "startFlash: removing temporary file" << filename
;
281 // backup if requested
283 QString backupFilename
;
286 backupPath
= g
.profile
[g
.id()].pBackupDir();
287 if (backupPath
.isEmpty()) {
288 backupPath
=g
.backupDir();
290 backupFilename
= backupPath
+ "/backup-" + QDateTime().currentDateTime().toString("yyyy-MM-dd-HHmmss") + ".bin";
291 result
= readEeprom(backupFilename
, progressDialog
.progress());
296 result
= (result
&& writeFirmware(filename
, progressDialog
.progress()));
298 // restore if backup requested
299 if (backup
&& result
) {
301 QString restoreFilename
= generateProcessUniqueTempFileName("restore.bin");
302 if (!convertEEprom(backupFilename
, restoreFilename
, filename
)) {
303 QMessageBox::warning(this, tr("Conversion failed"), tr("Cannot convert Models and Settings for use with this firmware, original data will be used"));
304 restoreFilename
= backupFilename
;
306 if (!writeEeprom(restoreFilename
, progressDialog
.progress())) {
307 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
));
311 progressDialog
.progress()->setInfo(tr("Flashing done"));
312 progressDialog
.exec();
314 if (isTempFileName(filename
)) {
315 qDebug() << "startFlash: removing temporary file" << filename
;