FirmwareUpgradeController.h 11.6 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
        } AutoPilotStackType_t;

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

        typedef enum {
Don Gagne's avatar
Don Gagne committed
57
            CopterFirmware,
Don Gagne's avatar
Don Gagne committed
58
            HeliFirmware,
59 60
            PlaneFirmware,
            RoverFirmware,
61
            SubFirmware,
Don Gagne's avatar
Don Gagne committed
62 63 64 65 66
            CopterChibiOSFirmware,
            HeliChibiOSFirmware,
            PlaneChibiOSFirmware,
            RoverChibiOSFirmware,
            SubChibiOSFirmware,
67
            DefaultVehicleFirmware
68 69
        } FirmwareVehicleType_t;

70 71 72
        Q_ENUM(AutoPilotStackType_t)
        Q_ENUM(FirmwareType_t)
        Q_ENUM(FirmwareVehicleType_t)
73 74 75 76 77 78 79 80 81

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

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

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

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

98 99 100
    Q_PROPERTY(QString          boardPort                   READ boardPort                                              NOTIFY boardFound)
    Q_PROPERTY(QString          boardDescription            READ boardDescription                                       NOTIFY boardFound)
    Q_PROPERTY(QString          boardType                   MEMBER _foundBoardTypeName                                  NOTIFY boardFound)
101 102
    Q_PROPERTY(bool             pixhawkBoard                READ pixhawkBoard                                           NOTIFY boardFound)
    Q_PROPERTY(bool             px4FlowBoard                READ px4FlowBoard                                           NOTIFY boardFound)
103 104
    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
105
    Q_PROPERTY(QString          px4StableVersion            READ px4StableVersion                                       NOTIFY px4StableVersionChanged)
106
    Q_PROPERTY(QString          px4BetaVersion              READ px4BetaVersion                                         NOTIFY px4BetaVersionChanged)
107

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

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

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

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

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

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

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

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

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

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

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

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

202 203 204 205 206
    // 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
207 208
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
    QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
209
    QHash<FirmwareIdentifier, QString> _rgAUAVX2_1Firmware;
Henry Zhang's avatar
Henry Zhang committed
210
    QHash<FirmwareIdentifier, QString> _rgMindPXFMUV2Firmware;
211 212
    QHash<FirmwareIdentifier, QString> _rgTAPV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgASCV1Firmware;
213
    QHash<FirmwareIdentifier, QString> _rgCrazyflie2Firmware;
214
    QHash<FirmwareIdentifier, QString> _rgOmnibusF4SDFirmware;
215
    QHash<FirmwareIdentifier, QString> _rgNXPHliteV3Firmware;
Pritam Ghanghas's avatar
Pritam Ghanghas committed
216 217 218
    QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
    QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;

219 220 221 222
    // Hash map for ArduPilot ChibiOS lookup by board name
    QHash<FirmwareIdentifier, QString> _rgAPMChibiosReplaceNamedBoardFirmware;
    QHash<FirmwareIdentifier, QString> _rgFirmwareDynamic;

223 224 225
    QMap<FirmwareType_t, QMap<FirmwareVehicleType_t, QString> > _apmVersionMap;
    QList<FirmwareVehicleType_t>                                _apmVehicleTypeFromCurrentVersionList;

226 227 228 229 230 231
    /// 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
    
232 233
    bool                 _startFlashWhenBootloaderFound;
    FirmwareIdentifier   _startFlashWhenBootloaderFoundFirmwareIdentity;
234 235 236 237 238 239 240 241

    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
242
    /// @brief Thread controller which is used to run bootloader commands on separate thread
243 244 245 246 247 248 249 250 251 252
    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
    
253
    QQuickItem*     _statusLog;         ///< Status log TextArea Qml control
254
    QQuickItem*     _progressBar;
255 256
    
    bool _searchingForBoard;    ///< true: searching for board, false: search for bootloader
257
    
258 259 260 261 262 263
    QSerialPortInfo                 _foundBoardInfo;
    QGCSerialPortInfo::BoardType_t  _foundBoardType;
    QString                         _foundBoardTypeName;

    FirmwareType_t                  _selectedFirmwareType;

264
    FirmwareImage*  _image;
Don Gagne's avatar
Don Gagne committed
265 266

    QString _px4StableVersion;  // Version strange for latest PX4 stable
267
    QString _px4BetaVersion;    // Version strange for latest PX4 beta
268 269

    const QString _apmBoardDescriptionReplaceText;
270 271
};

272
// global hashing function
273
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);
274

275
#endif