Newer
Older
/****************************************************************************
*
* (c) 2009-2016 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
*
* QGroundControl is licensed according to the terms in the file
* COPYING.md in the root of the source code directory.
*
****************************************************************************/
#include "LinkManager.h"
#include "FirmwareImage.h"
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
/// Supported firmware types. If you modify these you will need to update the qml file as well.
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
typedef enum {
AutoPilotStackAPM,
PX4FlowPX4,
PX4FlowAPM,
ThreeDRRadio,
SingleFirmwareMode
} AutoPilotStackType_t;
typedef enum {
BetaFirmware,
DeveloperFirmware,
CustomFirmware
typedef enum {
PlaneFirmware,
RoverFirmware,
DefaultVehicleFirmware
} FirmwareVehicleType_t;
class FirmwareIdentifier
{
public:
FirmwareIdentifier(AutoPilotStackType_t stack = AutoPilotStackPX4,
FirmwareVehicleType_t vehicle = DefaultVehicleFirmware)
: autopilotStackType(stack), firmwareType(firmware), firmwareVehicleType(vehicle) {}
bool operator==(const FirmwareIdentifier& firmwareId) const
return (firmwareId.autopilotStackType == autopilotStackType &&
firmwareId.firmwareType == firmwareType &&
firmwareId.firmwareVehicleType == firmwareVehicleType);
}
// members
AutoPilotStackType_t autopilotStackType;
FirmwareVehicleType_t firmwareVehicleType;
};
Q_PROPERTY(bool downloadingFirmwareList MEMBER _downloadingFirmwareList NOTIFY downloadingFirmwareListChanged)
Q_PROPERTY(QString boardPort READ boardPort NOTIFY boardFound)
Q_PROPERTY(QString boardDescription READ boardDescription NOTIFY boardFound)
Q_PROPERTY(QString boardType MEMBER _foundBoardTypeName NOTIFY boardFound)
Q_PROPERTY(bool pixhawkBoard READ pixhawkBoard NOTIFY boardFound)
Q_PROPERTY(bool px4FlowBoard READ px4FlowBoard NOTIFY boardFound)
Q_PROPERTY(FirmwareBuildType_t selectedFirmwareBuildType READ selectedFirmwareBuildType WRITE setSelectedFirmwareBuildType NOTIFY selectedFirmwareBuildTypeChanged)
Q_PROPERTY(QStringList apmFirmwareNames MEMBER _apmFirmwareNames NOTIFY apmFirmwareNamesChanged)
Q_PROPERTY(QStringList apmFirmwareUrls MEMBER _apmFirmwareUrls NOTIFY apmFirmwareNamesChanged)
Q_PROPERTY(QString px4StableVersion READ px4StableVersion NOTIFY px4StableVersionChanged)
Q_PROPERTY(QString px4BetaVersion READ px4BetaVersion NOTIFY px4BetaVersionChanged)
/// TextArea for log output
Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
/// Progress bar for you know what
Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
/// Starts searching for boards on the background thread
Q_INVOKABLE void startBoardSearch(void);
/// Cancels whatever state the upgrade worker thread is in
Q_INVOKABLE void cancel(void);
/// Called when the firmware type has been selected by the user to continue the flash process.
Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
/// Called to flash when upgrade is running in singleFirmwareMode
Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromFirmwareSelectionIndex(int index);
// overload, not exposed to qml side
void flash(const FirmwareIdentifier& firmwareId);
QQuickItem* progressBar(void) { return _progressBar; }
void setProgressBar(QQuickItem* progressBar) { _progressBar = progressBar; }
QQuickItem* statusLog(void) { return _statusLog; }
void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
QString boardPort(void) { return _foundBoardInfo.portName(); }
QString boardDescription(void) { return _foundBoardInfo.description(); }
FirmwareBuildType_t selectedFirmwareBuildType(void) { return _selectedFirmwareBuildType; }
void setSelectedFirmwareBuildType(FirmwareBuildType_t firmwareType);
QString firmwareTypeAsString(FirmwareBuildType_t type) const;
QString px4StableVersion (void) { return _px4StableVersion; }
QString px4BetaVersion (void) { return _px4BetaVersion; }
bool pixhawkBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePixhawk; }
bool px4FlowBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePX4Flow; }
/**
* @brief Return a human friendly string of available boards
*
* @return availableBoardNames
*/
Q_INVOKABLE QStringList availableBoardsName(void);
void boardFound (void);
void noBoardFound (void);
void boardGone (void);
void flashComplete (void);
void flashCancelled (void);
void error (void);
void selectedFirmwareBuildTypeChanged(FirmwareBuildType_t firmwareType);
void apmFirmwareNamesChanged (void);
void px4StableVersionChanged (const QString& px4StableVersion);
void px4BetaVersionChanged (const QString& px4BetaVersion);
void downloadingFirmwareListChanged (bool downloadingFirmwareList);
void _firmwareDownloadProgress(qint64 curr, qint64 total);
void _firmwareDownloadFinished(QString remoteFile, QString localFile);
void _firmwareDownloadError(QString errorMsg);
void _foundBoard(bool firstAttempt, const QSerialPortInfo& portInfo, int boardType, QString boardName);
void _noBoardFound(void);
void _boardGone();
void _foundBootloader(int bootloaderVersion, int boardID, int flashSize);
void _error(const QString& errorString);
void _status(const QString& statusString);
void _updateProgress(int curr, int total);
void _eraseStarted(void);
void _eraseComplete(void);
void _px4ReleasesGithubDownloadFinished(QString remoteFile, QString localFile);
void _px4ReleasesGithubDownloadError(QString errorMsg);
void _ardupilotManifestDownloadFinished(QString remoteFile, QString localFile);
void _ardupilotManifestDownloadError(QString errorMsg);
void _buildAPMFirmwareNames(void);
QHash<FirmwareIdentifier, QString>* _firmwareHashForBoardId(int boardId);
void _getFirmwareFile(FirmwareIdentifier firmwareId);
void _initFirmwareHash (void);
void _downloadFirmware (void);
void _appendStatusLog (const QString& text, bool critical = false);
void _errorCancel (const QString& msg);
void _determinePX4StableVersion (void);
void _downloadArduPilotManifest (void);
QString _singleFirmwareURL;
bool _singleFirmwareMode;
QString _portName;
QString _portDescription;
// Firmware hashes
QHash<FirmwareIdentifier, QString> _rgFMUV5Firmware;
QHash<FirmwareIdentifier, QString> _rgFMUV4PROFirmware;
QHash<FirmwareIdentifier, QString> _rgFMUV4Firmware;
QHash<FirmwareIdentifier, QString> _rgFMUV3Firmware;
QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
QHash<FirmwareIdentifier, QString> _rgAUAVX2_1Firmware;
QHash<FirmwareIdentifier, QString> _rgMindPXFMUV2Firmware;
QHash<FirmwareIdentifier, QString> _rgTAPV1Firmware;
QHash<FirmwareIdentifier, QString> _rgASCV1Firmware;
QHash<FirmwareIdentifier, QString> _rgCrazyflie2Firmware;
QHash<FirmwareIdentifier, QString> _rgOmnibusF4SDFirmware;
QHash<FirmwareIdentifier, QString> _rgKakuteF7Firmware;
QHash<FirmwareIdentifier, QString> _rgFMUK66V3Firmware;
QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;
// Hash map for ArduPilot ChibiOS lookup by board name
QHash<FirmwareIdentifier, QString> _rgAPMChibiosReplaceNamedBoardFirmware;
QHash<FirmwareIdentifier, QString> _rgFirmwareDynamic;
QMap<FirmwareBuildType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
QList<FirmwareVehicleType_t> _apmVehicleTypeFromCurrentVersionList;
/// Information which comes back from the bootloader
bool _bootloaderFound; ///< true: we have received the foundBootloader signals
uint32_t _bootloaderVersion; ///< Bootloader version
uint32_t _bootloaderBoardID; ///< Board ID
uint32_t _bootloaderBoardFlashSize; ///< Flash size in bytes of board
bool _startFlashWhenBootloaderFound;
FirmwareIdentifier _startFlashWhenBootloaderFoundFirmwareIdentity;
QPixmap _boardIcon; ///< Icon used to display image of board
QString _firmwareFilename; ///< Image which we are going to flash to the board
QNetworkAccessManager* _downloadManager; ///< Used for firmware file downloading across the internet
QNetworkReply* _downloadNetworkReply; ///< Used for firmware file downloading across the internet
/// @brief Thread controller which is used to run bootloader commands on separate thread
PX4FirmwareUpgradeThreadController* _threadController;
static const int _eraseTickMsec = 500; ///< Progress bar update tick time for erase
static const int _eraseTotalMsec = 15000; ///< Estimated amount of time erase takes
int _eraseTickCount; ///< Number of ticks for erase progress update
QTimer _eraseTimer; ///< Timer used to update progress bar for erase
static const int _findBoardTimeoutMsec = 30000; ///< Amount of time for user to plug in USB
static const int _findBootloaderTimeoutMsec = 5000; ///< Amount time to look for bootloader
QQuickItem* _statusLog; ///< Status log TextArea Qml control
bool _searchingForBoard; ///< true: searching for board, false: search for bootloader
QSerialPortInfo _foundBoardInfo;
QGCSerialPortInfo::BoardType_t _foundBoardType;
QString _foundBoardTypeName;
QString _px4StableVersion; // Version strange for latest PX4 stable
QString _px4BetaVersion; // Version strange for latest PX4 beta
static const char* _manifestFirmwareJsonKey;
static const char* _manifestBoardIdJsonKey;
static const char* _manifestMavTypeJsonKey;
static const char* _manifestFormatJsonKey;
static const char* _manifestUrlJsonKey;
static const char* _manifestMavFirmwareVersionTypeJsonKey;
static const char* _manifestUSBIDJsonKey;
static const char* _manifestMavFirmwareVersionJsonKey;
static const char* _manifestBootloaderStrJsonKey;
static const char* _manifestLatestKey;
static const char* _manifestPlatformKey;
static const char* _manifestBrandNameKey;
typedef struct {
uint32_t boardId;
FirmwareBuildType_t firmwareBuildType;
FirmwareVehicleType_t vehicleType;
QString url;
QString version;
QStringList rgBootloaderPortString;
QList<int> rgVID;
QList<int> rgPID;
QString friendlyName;
bool chibios;
} ManifestFirmwareInfo_t;
QList<ManifestFirmwareInfo_t> _rgManifestFirmwareInfo;
QMap<QString, FirmwareBuildType_t> _manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap;
QMap<QString, FirmwareVehicleType_t> _manifestMavTypeToFirmwareVehicleTypeMap;
QStringList _apmFirmwareNames;
QStringList _apmFirmwareUrls;
Fact* _apmChibiOSSetting;
Fact* _apmVehicleTypeSetting;
FirmwareBuildType_t _manifestMavFirmwareVersionTypeToFirmwareBuildType (const QString& manifestMavFirmwareVersionType);
FirmwareVehicleType_t _manifestMavTypeToFirmwareVehicleType (const QString& manifestMavType);
// global hashing function
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);