FirmwareUpgradeController.h 14.9 KB
Newer Older
1 2
/****************************************************************************
 *
Gus Grubba's avatar
Gus Grubba committed
3
 * (c) 2009-2020 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
4 5 6 7 8 9
 *
 * QGroundControl is licensed according to the terms in the file
 * COPYING.md in the root of the source code directory.
 *
 ****************************************************************************/

10
#pragma once
11

12
#include "PX4FirmwareUpgradeThread.h"
13 14
#include "LinkManager.h"
#include "FirmwareImage.h"
15
#include "Fact.h"
16 17

#include <QObject>
18 19 20 21
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
22 23
#include <QPixmap>
#include <QQuickItem>
24
#include <QSerialPort>
25

26 27
#include <stdint.h>

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

30 31
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
32 33
{
    Q_OBJECT
34
    
35
public:
36
        typedef enum {
37
            AutoPilotStackPX4 = 0,
38
            AutoPilotStackAPM,
39 40
            PX4FlowPX4,
            PX4FlowAPM,
41 42
            ThreeDRRadio,
            SingleFirmwareMode
43 44 45
        } AutoPilotStackType_t;

        typedef enum {
46
            StableFirmware = 0,
47 48 49
            BetaFirmware,
            DeveloperFirmware,
            CustomFirmware
50
        } FirmwareBuildType_t;
51 52

        typedef enum {
53
            CopterFirmware = 0,
Don Gagne's avatar
Don Gagne committed
54
            HeliFirmware,
55 56
            PlaneFirmware,
            RoverFirmware,
57
            SubFirmware,
58
            DefaultVehicleFirmware
59 60
        } FirmwareVehicleType_t;

61
        Q_ENUM(AutoPilotStackType_t)
62
        Q_ENUM(FirmwareBuildType_t)
63
        Q_ENUM(FirmwareVehicleType_t)
64 65 66 67 68

    class FirmwareIdentifier
    {
    public:
        FirmwareIdentifier(AutoPilotStackType_t stack = AutoPilotStackPX4,
69
                           FirmwareBuildType_t firmware = StableFirmware,
70 71 72
                           FirmwareVehicleType_t vehicle = DefaultVehicleFirmware)
            : autopilotStackType(stack), firmwareType(firmware), firmwareVehicleType(vehicle) {}

73
        bool operator==(const FirmwareIdentifier& firmwareId) const
74
        {
75 76 77
            return (firmwareId.autopilotStackType == autopilotStackType &&
                    firmwareId.firmwareType == firmwareType &&
                    firmwareId.firmwareVehicleType == firmwareVehicleType);
78 79 80 81
        }

        // members
        AutoPilotStackType_t    autopilotStackType;
82
        FirmwareBuildType_t          firmwareType;
83 84 85
        FirmwareVehicleType_t   firmwareVehicleType;
    };

86
    FirmwareUpgradeController(void);
Don Gagne's avatar
Don Gagne committed
87 88
    ~FirmwareUpgradeController();

89 90 91 92 93 94 95 96
    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)
97
    Q_PROPERTY(int                  apmFirmwareNamesBestIndex   MEMBER _apmFirmwareNamesBestIndex                                   NOTIFY apmFirmwareNamesChanged)
98 99 100
    Q_PROPERTY(QStringList          apmFirmwareUrls             MEMBER _apmFirmwareUrls                                             NOTIFY apmFirmwareNamesChanged)
    Q_PROPERTY(QString              px4StableVersion            READ px4StableVersion                                               NOTIFY px4StableVersionChanged)
    Q_PROPERTY(QString              px4BetaVersion              READ px4BetaVersion                                                 NOTIFY px4BetaVersionChanged)
101

102 103 104
    /// TextArea for log output
    Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
    
105 106
    /// Progress bar for you know what
    Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
107 108 109

    /// Starts searching for boards on the background thread
    Q_INVOKABLE void startBoardSearch(void);
110
    
111 112
    /// Cancels whatever state the upgrade worker thread is in
    Q_INVOKABLE void cancel(void);
113
    
114
    /// Called when the firmware type has been selected by the user to continue the flash process.
115
    Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
116
                           FirmwareBuildType_t firmwareType = StableFirmware,
117
                           FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
118

119 120
    Q_INVOKABLE void flashFirmwareUrl(QString firmwareUrl);

121
    /// Called to flash when upgrade is running in singleFirmwareMode
122
    Q_INVOKABLE void flashSingleFirmwareMode(FirmwareBuildType_t firmwareType);
123

124
    Q_INVOKABLE FirmwareVehicleType_t vehicleTypeFromFirmwareSelectionIndex(int index);
125
    
126 127 128
    // overload, not exposed to qml side
    void flash(const FirmwareIdentifier& firmwareId);

129
    // Property accessors
130
    
131 132 133
    QQuickItem* progressBar(void) { return _progressBar; }
    void setProgressBar(QQuickItem* progressBar) { _progressBar = progressBar; }
    
134 135 136
    QQuickItem* statusLog(void) { return _statusLog; }
    void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
    
137 138
    QString boardPort(void) { return _foundBoardInfo.portName(); }
    QString boardDescription(void) { return _foundBoardInfo.description(); }
139

140 141 142
    FirmwareBuildType_t selectedFirmwareBuildType(void) { return _selectedFirmwareBuildType; }
    void setSelectedFirmwareBuildType(FirmwareBuildType_t firmwareType);
    QString firmwareTypeAsString(FirmwareBuildType_t type) const;
143

144 145
    QString     px4StableVersion    (void) { return _px4StableVersion; }
    QString     px4BetaVersion  (void) { return _px4BetaVersion; }
146

147 148 149
    bool pixhawkBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePixhawk; }
    bool px4FlowBoard(void) const { return _foundBoardType == QGCSerialPortInfo::BoardTypePX4Flow; }

150 151 152 153 154 155 156
    /**
     * @brief Return a human friendly string of available boards
     *
     * @return availableBoardNames
     */
    Q_INVOKABLE QStringList availableBoardsName(void);

157
signals:
158
    void boardFound                     (void);
159
    void bootloaderFound                (void);
160 161 162 163 164 165 166 167 168 169
    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);
170

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

private:
194
    QHash<FirmwareIdentifier, QString>* _firmwareHashForBoardId(int boardId);
195 196 197 198 199 200 201
    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);
202

203 204
    QString _singleFirmwareURL;
    bool    _singleFirmwareMode;
205
    bool    _downloadingFirmwareList;
206 207 208
    QString _portName;
    QString _portDescription;

209 210 211 212 213
    // Firmware hashes
    QHash<FirmwareIdentifier, QString> _rgFMUV5Firmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV4PROFirmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV4Firmware;
    QHash<FirmwareIdentifier, QString> _rgFMUV3Firmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
214 215
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
    QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
216
    QHash<FirmwareIdentifier, QString> _rgAUAVX2_1Firmware;
Henry Zhang's avatar
Henry Zhang committed
217
    QHash<FirmwareIdentifier, QString> _rgMindPXFMUV2Firmware;
218 219
    QHash<FirmwareIdentifier, QString> _rgTAPV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgASCV1Firmware;
220
    QHash<FirmwareIdentifier, QString> _rgCrazyflie2Firmware;
221
    QHash<FirmwareIdentifier, QString> _rgOmnibusF4SDFirmware;
222
    QHash<FirmwareIdentifier, QString> _rgKakuteF7Firmware;
223
    QHash<FirmwareIdentifier, QString> _rgDurandalV1Firmware;
224
    QHash<FirmwareIdentifier, QString> _rgFMUK66V3Firmware;
225
    QHash<FirmwareIdentifier, QString> _rgModalFCV1Firmware;
junwoo091400's avatar
junwoo091400 committed
226
    QHash<FirmwareIdentifier, QString> _rgUVifyCoreFirmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
227 228 229
    QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
    QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;

230 231 232 233
    // Hash map for ArduPilot ChibiOS lookup by board name
    QHash<FirmwareIdentifier, QString> _rgAPMChibiosReplaceNamedBoardFirmware;
    QHash<FirmwareIdentifier, QString> _rgFirmwareDynamic;

234
    QMap<FirmwareBuildType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
235 236
    QList<FirmwareVehicleType_t>                                _apmVehicleTypeFromCurrentVersionList;

237 238 239 240 241 242
    /// 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
    
243 244
    bool                 _startFlashWhenBootloaderFound;
    FirmwareIdentifier   _startFlashWhenBootloaderFoundFirmwareIdentity;
245 246 247 248 249 250 251 252

    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
253
    /// @brief Thread controller which is used to run bootloader commands on separate thread
254 255 256 257 258 259 260 261 262 263
    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
    
264
    QQuickItem*     _statusLog;         ///< Status log TextArea Qml control
265
    QQuickItem*     _progressBar;
266 267
    
    bool _searchingForBoard;    ///< true: searching for board, false: search for bootloader
268
    
269 270 271 272
    QSerialPortInfo                 _foundBoardInfo;
    QGCSerialPortInfo::BoardType_t  _foundBoardType;
    QString                         _foundBoardTypeName;

273
    FirmwareBuildType_t                  _selectedFirmwareBuildType;
274

275
    FirmwareImage*  _image;
Don Gagne's avatar
Don Gagne committed
276 277

    QString _px4StableVersion;  // Version strange for latest PX4 stable
278
    QString _px4BetaVersion;    // Version strange for latest PX4 beta
279 280

    const QString _apmBoardDescriptionReplaceText;
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305

    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;
Don Gagne's avatar
Don Gagne committed
306
        bool                    fmuv2;
307 308 309 310 311 312 313
    } ManifestFirmwareInfo_t;


    QList<ManifestFirmwareInfo_t>           _rgManifestFirmwareInfo;
    QMap<QString, FirmwareBuildType_t>      _manifestMavFirmwareVersionTypeToFirmwareBuildTypeMap;
    QMap<QString, FirmwareVehicleType_t>    _manifestMavTypeToFirmwareVehicleTypeMap;
    QStringList                             _apmFirmwareNames;
314
    int                                     _apmFirmwareNamesBestIndex = 0;
315 316 317 318 319 320
    QStringList                             _apmFirmwareUrls;
    Fact*                                   _apmChibiOSSetting;
    Fact*                                   _apmVehicleTypeSetting;

    FirmwareBuildType_t     _manifestMavFirmwareVersionTypeToFirmwareBuildType  (const QString& manifestMavFirmwareVersionType);
    FirmwareVehicleType_t   _manifestMavTypeToFirmwareVehicleType               (const QString& manifestMavType);
321 322
};

323
// global hashing function
324
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);