FirmwareUpgradeController.h 11.3 KB
Newer Older
1 2 3 4 5 6 7 8 9
/****************************************************************************
 *
 *   (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.
 *
 ****************************************************************************/

10 11 12 13

/// @file
///     @author Don Gagne <don@thegagnes.com>

14 15
#ifndef FirmwareUpgradeController_H
#define FirmwareUpgradeController_H
16

17
#include "PX4FirmwareUpgradeThread.h"
18 19
#include "LinkManager.h"
#include "FirmwareImage.h"
20 21

#include <QObject>
22 23 24 25
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
26 27
#include <QPixmap>
#include <QQuickItem>
28
#include <QSerialPort>
29

30 31
#include <stdint.h>

32 33
/// Supported firmware types. If you modify these you will need to update the qml file as well.

34 35
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
36 37
{
    Q_OBJECT
38
    
39
public:
40 41 42
        typedef enum {
            AutoPilotStackPX4,
            AutoPilotStackAPM,
43 44
            PX4FlowPX4,
            PX4FlowAPM,
45 46
            ThreeDRRadio,
            SingleFirmwareMode
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63
        } AutoPilotStackType_t;

        typedef enum {
            StableFirmware,
            BetaFirmware,
            DeveloperFirmware,
            CustomFirmware
        } FirmwareType_t;

        typedef enum {
            QuadFirmware,
            X8Firmware,
            HexaFirmware,
            OctoFirmware,
            YFirmware,
            Y6Firmware,
            HeliFirmware,
Don Gagne's avatar
Don Gagne committed
64
            CopterFirmware,
65 66
            PlaneFirmware,
            RoverFirmware,
67
            SubFirmware,
68
            DefaultVehicleFirmware
69 70 71 72 73 74 75 76 77 78 79 80 81 82
        } FirmwareVehicleType_t;

        Q_ENUMS(AutoPilotStackType_t)
        Q_ENUMS(FirmwareType_t)
        Q_ENUMS(FirmwareVehicleType_t)

    class FirmwareIdentifier
    {
    public:
        FirmwareIdentifier(AutoPilotStackType_t stack = AutoPilotStackPX4,
                           FirmwareType_t firmware = StableFirmware,
                           FirmwareVehicleType_t vehicle = DefaultVehicleFirmware)
            : autopilotStackType(stack), firmwareType(firmware), firmwareVehicleType(vehicle) {}

83
        bool operator==(const FirmwareIdentifier& firmwareId) const
84
        {
85 86 87
            return (firmwareId.autopilotStackType == autopilotStackType &&
                    firmwareId.firmwareType == firmwareType &&
                    firmwareId.firmwareVehicleType == firmwareVehicleType);
88 89 90 91 92 93 94 95
        }

        // members
        AutoPilotStackType_t    autopilotStackType;
        FirmwareType_t          firmwareType;
        FirmwareVehicleType_t   firmwareVehicleType;
    };

96
    FirmwareUpgradeController(void);
Don Gagne's avatar
Don Gagne committed
97 98
    ~FirmwareUpgradeController();

99 100 101
    Q_PROPERTY(QString          boardPort                   READ boardPort                                              NOTIFY boardFound)
    Q_PROPERTY(QString          boardDescription            READ boardDescription                                       NOTIFY boardFound)
    Q_PROPERTY(QString          boardType                   MEMBER _foundBoardTypeName                                  NOTIFY boardFound)
102 103
    Q_PROPERTY(bool             pixhawkBoard                READ pixhawkBoard                                           NOTIFY boardFound)
    Q_PROPERTY(bool             px4FlowBoard                READ px4FlowBoard                                           NOTIFY boardFound)
104 105
    Q_PROPERTY(FirmwareType_t   selectedFirmwareType        READ selectedFirmwareType   WRITE setSelectedFirmwareType   NOTIFY selectedFirmwareTypeChanged)
    Q_PROPERTY(QStringList      apmAvailableVersions        READ apmAvailableVersions                                   NOTIFY apmAvailableVersionsChanged)
Don Gagne's avatar
Don Gagne committed
106
    Q_PROPERTY(QString          px4StableVersion            READ px4StableVersion                                       NOTIFY px4StableVersionChanged)
107
    Q_PROPERTY(QString          px4BetaVersion              READ px4BetaVersion                                         NOTIFY px4BetaVersionChanged)
108

109 110 111
    /// TextArea for log output
    Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
    
112 113
    /// Progress bar for you know what
    Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
114 115 116

    /// Starts searching for boards on the background thread
    Q_INVOKABLE void startBoardSearch(void);
117
    
118 119
    /// Cancels whatever state the upgrade worker thread is in
    Q_INVOKABLE void cancel(void);
120
    
121
    /// Called when the firmware type has been selected by the user to continue the flash process.
122 123 124
    Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
                           FirmwareType_t firmwareType = StableFirmware,
                           FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
125

126
    /// Called to flash when upgrade is running in singleFirmwareMode
Gus Grubba's avatar
Gus Grubba committed
127
    Q_INVOKABLE void flashSingleFirmwareMode(FirmwareType_t firmwareType);
128

129
    Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromVersionIndex(int index);
130
    
131 132 133
    // overload, not exposed to qml side
    void flash(const FirmwareIdentifier& firmwareId);

134
    // Property accessors
135
    
136 137 138
    QQuickItem* progressBar(void) { return _progressBar; }
    void setProgressBar(QQuickItem* progressBar) { _progressBar = progressBar; }
    
139 140 141
    QQuickItem* statusLog(void) { return _statusLog; }
    void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
    
142 143
    QString boardPort(void) { return _foundBoardInfo.portName(); }
    QString boardDescription(void) { return _foundBoardInfo.description(); }
144 145 146

    FirmwareType_t selectedFirmwareType(void) { return _selectedFirmwareType; }
    void setSelectedFirmwareType(FirmwareType_t firmwareType);
147
    QString firmwareTypeAsString(FirmwareType_t type) const;
148 149

    QStringList apmAvailableVersions(void);
Don Gagne's avatar
Don Gagne committed
150
    QString px4StableVersion(void) { return _px4StableVersion; }
151
    QString px4BetaVersion(void) { return _px4BetaVersion; }
152

153 154 155
    bool pixhawkBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePixhawk; }
    bool px4FlowBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePX4Flow; }

156
signals:
157 158 159 160 161 162
    void boardFound(void);
    void noBoardFound(void);
    void boardGone(void);
    void flashComplete(void);
    void flashCancelled(void);
    void error(void);
163 164
    void selectedFirmwareTypeChanged(FirmwareType_t firmwareType);
    void apmAvailableVersionsChanged(void);
Don Gagne's avatar
Don Gagne committed
165
    void px4StableVersionChanged(const QString& px4StableVersion);
166 167
    void px4BetaVersionChanged(const QString& px4BetaVersion);

168
private slots:
169 170 171
    void _firmwareDownloadProgress(qint64 curr, qint64 total);
    void _firmwareDownloadFinished(QString remoteFile, QString localFile);
    void _firmwareDownloadError(QString errorMsg);
172
    void _foundBoard(bool firstAttempt, const QSerialPortInfo& portInfo, int boardType, QString boardName);
173 174
    void _noBoardFound(void);
    void _boardGone();
175
    void _foundBootloader(int bootloaderVersion, int boardID, int flashSize);
176 177
    void _error(const QString& errorString);
    void _status(const QString& statusString);
178
    void _bootloaderSyncFailed(void);
179
    void _flashComplete(void);
180
    void _updateProgress(int curr, int total);
181 182
    void _eraseStarted(void);
    void _eraseComplete(void);
183
    void _eraseProgressTick(void);
184
    void _apmVersionDownloadFinished(QString remoteFile, QString localFile);
185 186
    void _px4ReleasesGithubDownloadFinished(QString remoteFile, QString localFile);
    void _px4ReleasesGithubDownloadError(QString errorMsg);
187 188

private:
189
    void _getFirmwareFile(FirmwareIdentifier firmwareId);
Pritam Ghanghas's avatar
Pritam Ghanghas committed
190
    void _initFirmwareHash();
191
    void _downloadFirmware(void);
192 193
    void _appendStatusLog(const QString& text, bool critical = false);
    void _errorCancel(const QString& msg);
194
    void _loadAPMVersions(uint32_t bootloaderBoardID);
195
    QHash<FirmwareIdentifier, QString>* _firmwareHashForBoardId(int boardId);
Don Gagne's avatar
Don Gagne committed
196
    void _determinePX4StableVersion(void);
197

198 199
    QString _singleFirmwareURL;
    bool    _singleFirmwareMode;
200 201 202
    QString _portName;
    QString _portDescription;

Pritam Ghanghas's avatar
Pritam Ghanghas committed
203
    // firmware hashes
204 205
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV5Firmware;
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV4PROFirmware;
Lorenz Meier's avatar
Lorenz Meier committed
206
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV4Firmware;
DonLakeFlyer's avatar
DonLakeFlyer committed
207
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV3Firmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
208 209
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
    QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
210
    QHash<FirmwareIdentifier, QString> _rgAUAVX2_1Firmware;
Henry Zhang's avatar
Henry Zhang committed
211
    QHash<FirmwareIdentifier, QString> _rgMindPXFMUV2Firmware;
212 213
    QHash<FirmwareIdentifier, QString> _rgTAPV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgASCV1Firmware;
214
    QHash<FirmwareIdentifier, QString> _rgCrazyflie2Firmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
215 216 217
    QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
    QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;

218 219 220
    QMap<FirmwareType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
    QList<FirmwareVehicleType_t>                                _apmVehicleTypeFromCurrentVersionList;

221 222 223 224 225 226
    /// 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
    
227 228
    bool                 _startFlashWhenBootloaderFound;
    FirmwareIdentifier   _startFlashWhenBootloaderFoundFirmwareIdentity;
229 230 231 232 233 234 235 236

    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
    
Ricardo de Almeida Gonzaga's avatar
Ricardo de Almeida Gonzaga committed
237
    /// @brief Thread controller which is used to run bootloader commands on separate thread
238 239 240 241 242 243 244 245 246 247
    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
    
248
    QQuickItem*     _statusLog;         ///< Status log TextArea Qml control
249
    QQuickItem*     _progressBar;
250 251
    
    bool _searchingForBoard;    ///< true: searching for board, false: search for bootloader
252
    
253 254 255 256 257 258
    QSerialPortInfo                 _foundBoardInfo;
    QGCSerialPortInfo::BoardType_t  _foundBoardType;
    QString                         _foundBoardTypeName;

    FirmwareType_t                  _selectedFirmwareType;

259
    FirmwareImage*  _image;
Don Gagne's avatar
Don Gagne committed
260 261

    QString _px4StableVersion;  // Version strange for latest PX4 stable
262
    QString _px4BetaVersion;    // Version strange for latest PX4 beta
263 264
};

265
// global hashing function
266
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);
267

268
#endif