diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp index 42344519c..66fc372d6 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.cpp @@ -17,7 +17,7 @@ AutoUpdatePage::AutoUpdatePage(SetupWizard *wizard, QWidget *parent) : Q_ASSERT(uploader); connect(ui->startUpdate, SIGNAL(clicked()), this, SLOT(disableButtons())); connect(ui->startUpdate, SIGNAL(clicked()), this, SLOT(autoUpdate())); - connect(uploader, SIGNAL(autoUpdateSignal(uploader::AutoUpdateStep, QVariant)), this, SLOT(updateStatus(uploader::AutoUpdateStep, QVariant))); + connect(uploader, SIGNAL(autoUpdateSignal(uploader::ProgressStep, QVariant)), this, SLOT(updateStatus(uploader::ProgressStep, QVariant))); } AutoUpdatePage::~AutoUpdatePage() @@ -44,7 +44,7 @@ void AutoUpdatePage::autoUpdate() uploader->autoUpdate(ui->eraseSettings->isChecked()); } -void AutoUpdatePage::updateStatus(uploader::AutoUpdateStep status, QVariant value) +void AutoUpdatePage::updateStatus(uploader::ProgressStep status, QVariant value) { QString msg; diff --git a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.h b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.h index 711e3ccf1..7a40345db 100644 --- a/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.h +++ b/ground/openpilotgcs/src/plugins/setupwizard/pages/autoupdatepage.h @@ -46,7 +46,7 @@ public: ~AutoUpdatePage(); private slots: - void updateStatus(uploader::AutoUpdateStep, QVariant); + void updateStatus(uploader::ProgressStep, QVariant); void disableButtons() { enableButtons(false); diff --git a/ground/openpilotgcs/src/plugins/uploader/enums.h b/ground/openpilotgcs/src/plugins/uploader/enums.h index 2b3f540e7..9f2d68057 100644 --- a/ground/openpilotgcs/src/plugins/uploader/enums.h +++ b/ground/openpilotgcs/src/plugins/uploader/enums.h @@ -29,6 +29,6 @@ namespace uploader { typedef enum { IAP_STATE_READY, IAP_STATE_STEP_1, IAP_STATE_STEP_2, IAP_STEP_RESET, IAP_STATE_BOOTLOADER } IAPStep; -typedef enum { WAITING_DISCONNECT, WAITING_CONNECT, JUMP_TO_BL, LOADING_FW, UPLOADING_FW, UPLOADING_DESC, BOOTING, SUCCESS, FAILURE } AutoUpdateStep; +typedef enum { WAITING_DISCONNECT, WAITING_CONNECT, JUMP_TO_BL, LOADING_FW, UPLOADING_FW, UPLOADING_DESC, BOOTING, SUCCESS, FAILURE } ProgressStep; } #endif // ENUMS_H diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.cpp index 04dbbfc75..e3b29b522 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.cpp @@ -45,7 +45,8 @@ Core::IUAVGadget *UploaderGadgetFactory::createGadget(QWidget *parent) isautocapable = gadgetWidget->autoUpdateCapable(); connect(this, SIGNAL(autoUpdate(bool)), gadgetWidget, SLOT(autoUpdate(bool))); - connect(gadgetWidget, SIGNAL(autoUpdateSignal(uploader::AutoUpdateStep, QVariant)), this, SIGNAL(autoUpdateSignal(uploader::AutoUpdateStep, QVariant))); + connect(this, SIGNAL(reboot()), gadgetWidget, SLOT(systemReset())); + connect(gadgetWidget, SIGNAL(autoUpdateSignal(uploader::ProgressStep, QVariant)), this, SIGNAL(autoUpdateSignal(uploader::ProgressStep, QVariant))); return new UploaderGadget(QString("Uploader"), gadgetWidget, parent); } diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.h index 1e1b1e2b6..7ba38e0d5 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetfactory.h @@ -49,9 +49,11 @@ public: bool isAutoUpdateCapable(); private: bool isautocapable; + signals: - void autoUpdateSignal(uploader::AutoUpdateStep, QVariant); + void autoUpdateSignal(uploader::ProgressStep, QVariant); void autoUpdate(bool erase); + void reboot(); }; #endif // UPLOADERGADGETFACTORY_H diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 42c1bdfef..28bb88a60 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -46,6 +46,7 @@ const int UploaderGadgetWidget::BOARD_EVENT_TIMEOUT = 20000; const int UploaderGadgetWidget::AUTOUPDATE_CLOSE_TIMEOUT = 7000; +const int UploaderGadgetWidget::AUTOUPDATE_TIMEOUT = 60000; TimedDialog::TimedDialog(const QString &title, const QString &labelText, int timeout, QWidget *parent, Qt::WindowFlags flags) : QProgressDialog(labelText, tr("Cancel"), 0, timeout, parent, flags), bar(new QProgressBar(this)) @@ -332,7 +333,7 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) clearLog(); log("IAP Step 1"); fwIAP->updated(); - emit autoUpdateSignal(JUMP_TO_BL, QVariant(1)); + emit progressUpdate(JUMP_TO_BL, QVariant(1)); break; case IAP_STATE_STEP_1: if (!success) { @@ -341,7 +342,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) currentStep = IAP_STATE_READY; disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(goToBootloader(UAVObject *, bool))); m_config->haltButton->setEnabled(true); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); break; } sleep(600); @@ -349,7 +351,7 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) currentStep = IAP_STATE_STEP_2; log("IAP Step 2"); fwIAP->updated(); - emit autoUpdateSignal(JUMP_TO_BL, QVariant(2)); + emit progressUpdate(JUMP_TO_BL, QVariant(2)); break; case IAP_STATE_STEP_2: if (!success) { @@ -358,14 +360,15 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) currentStep = IAP_STATE_READY; disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(goToBootloader(UAVObject *, bool))); m_config->haltButton->setEnabled(true); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); break; } sleep(600); fwIAP->getField("Command")->setValue("3344"); currentStep = IAP_STEP_RESET; log("IAP Step 3"); - emit autoUpdateSignal(JUMP_TO_BL, QVariant(3)); + emit progressUpdate(JUMP_TO_BL, QVariant(3)); fwIAP->updated(); break; case IAP_STEP_RESET: @@ -376,7 +379,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) log("Reset did NOT happen"); disconnect(fwIAP, SIGNAL(transactionCompleted(UAVObject *, bool)), this, SLOT(goToBootloader(UAVObject *, bool))); m_config->haltButton->setEnabled(true); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); break; } @@ -390,7 +394,7 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) cm->suspendPolling(); sleep(200); log("Board Halt"); - emit autoUpdateSignal(JUMP_TO_BL, QVariant(4)); + emit progressUpdate(JUMP_TO_BL, QVariant(4)); m_config->boardStatus->setText(tr("Bootloader")); if (dlj.startsWith("USB")) { m_config->telemetryLink->setCurrentIndex(m_config->telemetryLink->findText("USB")); @@ -419,7 +423,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) currentStep = IAP_STATE_READY; m_config->boardStatus->setText(tr("Bootloader?")); m_config->haltButton->setEnabled(true); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); return; } dfu->AbortOperation(); @@ -430,7 +435,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) cm->resumePolling(); currentStep = IAP_STATE_READY; m_config->boardStatus->setText(tr("Bootloader?")); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); return; } @@ -442,7 +448,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) delete dfu; dfu = NULL; cm->resumePolling(); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); return; } // Delete all previous tabs: @@ -462,7 +469,8 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) // Need to re-enable in case we were not connected bootButtonsSetEnable(true); - emit autoUpdateSignal(JUMP_TO_BL, QVariant(5)); + emit progressUpdate(JUMP_TO_BL, QVariant(5)); + emit bootloaderSuccess(); if (resetOnly) { resetOnly = false; @@ -470,12 +478,12 @@ void UploaderGadgetWidget::goToBootloader(UAVObject *callerObj, bool success) systemBoot(); break; } - emit boardHalted(); } break; case IAP_STATE_BOOTLOADER: // We should never end up here anyway. - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit bootloaderFailed(); break; } } @@ -540,7 +548,6 @@ void UploaderGadgetWidget::systemEraseBoot() } } - /** * Tells the system to boot (from Bootloader state) * @param[in] safeboot Indicates whether the firmware should use the stock HWSettings @@ -572,6 +579,7 @@ void UploaderGadgetWidget::commonSystemBoot(bool safeboot, bool erase) dfu = NULL; bootButtonsSetEnable(true); m_config->rescueButton->setEnabled(true); // Boot not possible, maybe Rescue OK? + emit bootFailed(); return; } log("Booting system..."); @@ -599,7 +607,7 @@ void UploaderGadgetWidget::commonSystemBoot(bool safeboot, bool erase) currentStep = IAP_STATE_READY; log("You can now reconnect telemetry..."); delete dfu; // Frees up the USB/Serial port too - emit boardBooted(); + emit bootSuccess(); dfu = NULL; } @@ -610,11 +618,17 @@ bool UploaderGadgetWidget::autoUpdateCapable() bool UploaderGadgetWidget::autoUpdate(bool erase) { + ResultEventLoop eventLoop; + connect(this, SIGNAL(bootloaderSuccess()), &eventLoop, SLOT(success())); + connect(this, SIGNAL(bootloaderFailed()), &eventLoop, SLOT(fail())); + goToBootloader(); - QEventLoop eventLoop; - connect(this, SIGNAL(boardHalted()), &eventLoop, SLOT(quit())); - eventLoop.exec(); + if (eventLoop.run(AUTOUPDATE_TIMEOUT) != 0) { + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); + return false; + } if (dfu) { delete dfu; @@ -624,31 +638,20 @@ bool UploaderGadgetWidget::autoUpdate(bool erase) Core::ConnectionManager *cm = Core::ICore::instance()->connectionManager(); dfu = new DFUObject(DFU_DEBUG, false, QString()); dfu->AbortOperation(); - emit autoUpdateSignal(JUMP_TO_BL, QVariant()); - if (!dfu->enterDFU(0)) { + emit progressUpdate(JUMP_TO_BL, QVariant()); + + if (!dfu->enterDFU(0) || !dfu->findDevices() || + (dfu->numberOfDevices != 1) || dfu->numberOfDevices > 5) { delete dfu; dfu = NULL; cm->resumePolling(); - emit autoUpdateSignal(FAILURE, QVariant()); - return false; - } - if (!dfu->findDevices() || (dfu->numberOfDevices != 1)) { - delete dfu; - dfu = NULL; - cm->resumePolling(); - emit autoUpdateSignal(FAILURE, QVariant()); - return false; - } - if (dfu->numberOfDevices > 5) { - delete dfu; - dfu = NULL; - cm->resumePolling(); - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } QString filename; - emit autoUpdateSignal(LOADING_FW, QVariant()); + emit progressUpdate(LOADING_FW, QVariant()); switch (dfu->devices[0].ID) { case 0x301: filename = "fw_oplinkmini"; @@ -670,61 +673,66 @@ bool UploaderGadgetWidget::autoUpdate(bool erase) filename = "fw_discoveryf4bare"; break; default: - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; - - break; } filename = ":/firmware/" + filename + ".opfw"; QByteArray firmware; if (!QFile::exists(filename)) { - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } QFile file(filename); if (!file.open(QIODevice::ReadOnly)) { - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } firmware = file.readAll(); QEventLoop eventLoop2; connect(dfu, SIGNAL(progressUpdated(int)), this, SLOT(autoUpdateFlashProgress(int))); connect(dfu, SIGNAL(uploadFinished(OP_DFU::Status)), &eventLoop2, SLOT(quit())); - emit autoUpdateSignal(UPLOADING_FW, QVariant()); + emit progressUpdate(UPLOADING_FW, QVariant()); if (!dfu->enterDFU(0)) { - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } dfu->AbortOperation(); if (!dfu->UploadFirmware(filename, false, 0)) { - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } eventLoop2.exec(); QByteArray desc = firmware.right(100); - emit autoUpdateSignal(UPLOADING_DESC, QVariant()); + emit progressUpdate(UPLOADING_DESC, QVariant()); if (dfu->UploadDescription(desc) != OP_DFU::Last_operation_Success) { - emit autoUpdateSignal(FAILURE, QVariant()); + emit progressUpdate(FAILURE, QVariant()); + emit autoUpdateFailed(); return false; } commonSystemBoot(false, erase); - emit autoUpdateSignal(SUCCESS, QVariant()); + emit progressUpdate(SUCCESS, QVariant()); + emit autoUpdateSuccess(); return true; } void UploaderGadgetWidget::autoUpdateDisconnectProgress(int value) { - emit autoUpdateSignal(WAITING_DISCONNECT, value); + emit progressUpdate(WAITING_DISCONNECT, value); } void UploaderGadgetWidget::autoUpdateConnectProgress(int value) { - emit autoUpdateSignal(WAITING_CONNECT, value); + emit progressUpdate(WAITING_CONNECT, value); } void UploaderGadgetWidget::autoUpdateFlashProgress(int value) { - emit autoUpdateSignal(UPLOADING_FW, value); + emit progressUpdate(UPLOADING_FW, value); } /** @@ -896,13 +904,13 @@ void UploaderGadgetWidget::startAutoUpdate(bool erase) m_config->autoUpdateGroupBox->setVisible(true); m_config->autoUpdateOkButton->setEnabled(false); - connect(this, SIGNAL(autoUpdateSignal(uploader::AutoUpdateStep, QVariant)), this, SLOT(autoUpdateStatus(uploader::AutoUpdateStep, QVariant))); + connect(this, SIGNAL(progressUpdate(uploader::ProgressStep, QVariant)), this, SLOT(autoUpdateStatus(uploader::ProgressStep, QVariant))); autoUpdate(erase); } void UploaderGadgetWidget::finishAutoUpdate() { - disconnect(this, SIGNAL(autoUpdateSignal(uploader::AutoUpdateStep, QVariant)), this, SLOT(autoUpdateStatus(uploader::AutoUpdateStep, QVariant))); + disconnect(this, SIGNAL(progressUpdate(uploader::ProgressStep, QVariant)), this, SLOT(autoUpdateStatus(uploader::ProgressStep, QVariant))); m_config->autoUpdateOkButton->setEnabled(true); // wait a bit and "close" auto update @@ -916,7 +924,7 @@ void UploaderGadgetWidget::closeAutoUpdate() m_config->splitter->setEnabled(true); } -void UploaderGadgetWidget::autoUpdateStatus(uploader::AutoUpdateStep status, QVariant value) +void UploaderGadgetWidget::autoUpdateStatus(uploader::ProgressStep status, QVariant value) { QString msg; int remaining; @@ -1043,3 +1051,19 @@ int UploaderGadgetWidget::cannotResetMessageBox() msgBox.setStandardButtons(QMessageBox::Ok); return msgBox.exec(); } + + +int ResultEventLoop::run(int millisTimout) { + m_timer.singleShot(millisTimout, this, SLOT(fail())); + return exec(); +} + +void ResultEventLoop::success() { + m_timer.stop(); + exit(0); +} + +void ResultEventLoop::fail() { + m_timer.stop(); + exit(-1); +} diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index 7697fc393..59ee13efc 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -91,6 +91,19 @@ private: int result; }; +class ResultEventLoop : public QEventLoop { + Q_OBJECT +public: + int run(int millisTimout); + +public slots: + void success(); + void fail(); + +private: + QTimer m_timer; +}; + class UPLOADER_EXPORT UploaderGadgetWidget : public QWidget { Q_OBJECT @@ -100,6 +113,7 @@ public: static const int BOARD_EVENT_TIMEOUT; static const int AUTOUPDATE_CLOSE_TIMEOUT; + static const int AUTOUPDATE_TIMEOUT; void log(QString str); bool autoUpdateCapable(); @@ -114,9 +128,13 @@ public slots: void autoUpdateFlashProgress(int); signals: - void autoUpdateSignal(uploader::AutoUpdateStep, QVariant); - void boardHalted(); - void boardBooted(); + void progressUpdate(uploader::ProgressStep, QVariant); + void bootloaderFailed(); + void bootloaderSuccess(); + void bootFailed(); + void bootSuccess(); + void autoUpdateFailed(); + void autoUpdateSuccess(); private: Ui_UploaderWidget *m_config; @@ -154,7 +172,7 @@ private slots: bool autoUpdate(bool erase); void finishAutoUpdate(); void closeAutoUpdate(); - void autoUpdateStatus(uploader::AutoUpdateStep status, QVariant value); + void autoUpdateStatus(uploader::ProgressStep status, QVariant value); }; #endif // UPLOADERGADGETWIDGET_H