FirmwareUpgradeController.h 8.49 KB
Newer Older
1 2 3 4
/*=====================================================================
 
 QGroundControl Open Source Ground Control Station
 
5
 (c) 2009, 2015 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
 
 This file is part of the QGROUNDCONTROL project
 
 QGROUNDCONTROL is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.
 
 QGROUNDCONTROL is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 
 You should have received a copy of the GNU General Public License
 along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
 
 ======================================================================*/

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

27 28
#ifndef FirmwareUpgradeController_H
#define FirmwareUpgradeController_H
29

30
#include "PX4FirmwareUpgradeThread.h"
31 32
#include "LinkManager.h"
#include "FirmwareImage.h"
33 34

#include <QObject>
35 36 37 38
#include <QUrl>
#include <QTimer>
#include <QNetworkAccessManager>
#include <QNetworkReply>
39 40
#include <QPixmap>
#include <QQuickItem>
41

42 43
#include "qextserialport.h"

44 45
#include <stdint.h>

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

48 49
// Firmware Upgrade MVC Controller for FirmwareUpgrade.qml.
class FirmwareUpgradeController : public QObject
50 51
{
    Q_OBJECT
52
    
53
public:
54 55 56 57
        typedef enum {
            AutoPilotStackPX4,
            AutoPilotStackAPM,
            PX4Flow,
58
            ThreeDRRadio
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
        } AutoPilotStackType_t;

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

        typedef enum {
            QuadFirmware,
            X8Firmware,
            HexaFirmware,
            OctoFirmware,
            YFirmware,
            Y6Firmware,
            HeliFirmware,
            PlaneFirmware,
            RoverFirmware,
            DefaultVehicleFirmware = QuadFirmware,
        } 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) {}

93
        bool operator==(const FirmwareIdentifier& firmwareId) const
94
        {
95 96 97
            return (firmwareId.autopilotStackType == autopilotStackType &&
                    firmwareId.firmwareType == firmwareType &&
                    firmwareId.firmwareVehicleType == firmwareVehicleType);
98 99 100 101 102 103 104 105
        }

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

106 107
    FirmwareUpgradeController(void);
    
108 109 110
    Q_PROPERTY(QString boardPort READ boardPort NOTIFY boardFound)
    Q_PROPERTY(QString boardDescription READ boardDescription NOTIFY boardFound)
    Q_PROPERTY(QString boardType MEMBER _foundBoardType NOTIFY boardFound)
111 112 113 114
    
    /// TextArea for log output
    Q_PROPERTY(QQuickItem* statusLog READ statusLog WRITE setStatusLog)
    
115 116
    /// Progress bar for you know what
    Q_PROPERTY(QQuickItem* progressBar READ progressBar WRITE setProgressBar)
117 118 119

    /// Returns true if there are active QGC connections
    Q_PROPERTY(bool qgcConnections READ qgcConnections NOTIFY qgcConnectionsChanged)
120
    
121 122
    /// Starts searching for boards on the background thread
    Q_INVOKABLE void startBoardSearch(void);
123
    
124 125
    /// Cancels whatever state the upgrade worker thread is in
    Q_INVOKABLE void cancel(void);
126
    
127
    /// Called when the firmware type has been selected by the user to continue the flash process.
128 129 130
    Q_INVOKABLE void flash(AutoPilotStackType_t stackType,
                           FirmwareType_t firmwareType = StableFirmware,
                           FirmwareVehicleType_t vehicleType = DefaultVehicleFirmware );
131
    
132 133 134
    // overload, not exposed to qml side
    void flash(const FirmwareIdentifier& firmwareId);

135
    // Property accessors
136
    
137 138 139
    QQuickItem* progressBar(void) { return _progressBar; }
    void setProgressBar(QQuickItem* progressBar) { _progressBar = progressBar; }
    
140 141 142
    QQuickItem* statusLog(void) { return _statusLog; }
    void setStatusLog(QQuickItem* statusLog) { _statusLog = statusLog; }
    
143 144 145 146 147
    bool qgcConnections(void);
    
    QString boardPort(void) { return _foundBoardInfo.portName(); }
    QString boardDescription(void) { return _foundBoardInfo.description(); }
    
148
signals:
149 150 151 152 153 154 155
    void boardFound(void);
    void noBoardFound(void);
    void boardGone(void);
    void flashComplete(void);
    void flashCancelled(void);
    void qgcConnectionsChanged(bool connections);
    void error(void);
156
    
157 158 159 160
private slots:
    void _downloadProgress(qint64 curr, qint64 total);
    void _downloadFinished(void);
    void _downloadError(QNetworkReply::NetworkError code);
161 162 163
    void _foundBoard(bool firstAttempt, const QSerialPortInfo& portInfo, int type);
    void _noBoardFound(void);
    void _boardGone();
164
    void _foundBootloader(int bootloaderVersion, int boardID, int flashSize);
165 166
    void _error(const QString& errorString);
    void _status(const QString& statusString);
167
    void _bootloaderSyncFailed(void);
168
    void _flashComplete(void);
169
    void _updateProgress(int curr, int total);
170 171
    void _eraseStarted(void);
    void _eraseComplete(void);
172
    void _eraseProgressTick(void);
173
    void _linkDisconnected(LinkInterface* link);
174 175

private:
176
    void _getFirmwareFile(FirmwareIdentifier firmwareId);
Pritam Ghanghas's avatar
Pritam Ghanghas committed
177
    void _initFirmwareHash();
178
    void _downloadFirmware(void);
179 180 181
    void _appendStatusLog(const QString& text, bool critical = false);
    void _errorCancel(const QString& msg);
    
182 183 184
    QString _portName;
    QString _portDescription;

Pritam Ghanghas's avatar
Pritam Ghanghas committed
185 186 187 188 189 190 191
    // firmware hashes
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV2Firmware;
    QHash<FirmwareIdentifier, QString> _rgAeroCoreFirmware;
    QHash<FirmwareIdentifier, QString> _rgPX4FMUV1Firmware;
    QHash<FirmwareIdentifier, QString> _rgPX4FLowFirmware;
    QHash<FirmwareIdentifier, QString> _rg3DRRadioFirmware;

192 193 194 195 196 197
    /// 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
    
198 199
    bool                 _startFlashWhenBootloaderFound;
    FirmwareIdentifier   _startFlashWhenBootloaderFoundFirmwareIdentity;
200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218

    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 seperate 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
    
219
    QQuickItem*     _statusLog;         ///< Status log TextArea Qml control
220
    QQuickItem*     _progressBar;
221 222
    
    bool _searchingForBoard;    ///< true: searching for board, false: search for bootloader
223 224 225 226 227
    
    QSerialPortInfo _foundBoardInfo;
    QString         _foundBoardType;
    
    FirmwareImage*  _image;
228 229
};

230
// global hashing function
231
uint qHash(const FirmwareUpgradeController::FirmwareIdentifier& firmwareId);
232

233
#endif