diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp index e86d4794b..67d30aadb 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp +++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.cpp @@ -261,18 +261,45 @@ QByteArray UAVObjectUtilManager::getBoardCPUSerial() loop.exec(); UAVObjectField* cpuField = obj->getField("CPUSerial"); - for (int i = 0; i < cpuField->getNumElements(); ++i) { + for (uint i = 0; i < cpuField->getNumElements(); ++i) { cpuSerial.append(cpuField->getValue(i).toUInt()); } return cpuSerial; } +quint32 UAVObjectUtilManager::getFirmwareCRC() +{ + quint32 fwCRC; + ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); + if (!pm) + return 0; + UAVObjectManager *om = pm->getObject(); + if (!om) + return 0; + + UAVDataObject *obj = dynamic_cast(om->getObject(QString("FirmwareIAPObj"))); + obj->getField("crc")->setValue(0); + obj->updated(); + // The code below will ask for the object update and wait for the updated to be received, + // or the timeout of the timer, set to 1 second. + QEventLoop loop; + connect(obj, SIGNAL(objectUpdated(UAVObject*)), &loop, SLOT(quit())); + QTimer::singleShot(1000, &loop, SLOT(quit())); // Create a timeout + obj->requestUpdate(); + loop.exec(); + + UAVObjectField* fwCRCField = obj->getField("crc"); + + fwCRC=(quint32)fwCRCField->getValue().toLongLong(); + return fwCRC; +} + /** * Get the UAV Board Description, for anyone interested. */ -QString UAVObjectUtilManager::getBoardDescription() +QByteArray UAVObjectUtilManager::getBoardDescription() { - QString description; + QByteArray ret; ExtensionSystem::PluginManager *pm = ExtensionSystem::PluginManager::instance(); if (!pm) return 0; @@ -291,10 +318,10 @@ QString UAVObjectUtilManager::getBoardDescription() UAVObjectField* descriptionField = obj->getField("Description"); // Description starts with an offset of - for (int i = 14; i < descriptionField->getNumElements(); ++i) { - description.append(descriptionField->getValue(i).toChar()); + for (uint i = 0; i < descriptionField->getNumElements(); ++i) { + ret.append(descriptionField->getValue(i).toInt()); } - return description; + return ret; } diff --git a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h index de61068ca..298374862 100644 --- a/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h +++ b/ground/openpilotgcs/src/plugins/uavobjectutil/uavobjectutilmanager.h @@ -63,7 +63,8 @@ public: int getBoardModel(); QByteArray getBoardCPUSerial(); - QString getBoardDescription(); + quint32 getFirmwareCRC(); + QByteArray getBoardDescription(); UAVObjectManager* getObjectManager(); void saveObjectToSD(UAVObject *obj); diff --git a/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.cpp b/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.cpp new file mode 100644 index 000000000..ffbc2cb69 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.cpp @@ -0,0 +1,5 @@ +#include "devicedescriptorstruct.h" + +deviceDescriptorStruct::deviceDescriptorStruct() +{ +} diff --git a/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.h b/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.h new file mode 100644 index 000000000..1304127e1 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uploader/devicedescriptorstruct.h @@ -0,0 +1,36 @@ +#ifndef DEVICEDESCRIPTORSTRUCT_H +#define DEVICEDESCRIPTORSTRUCT_H + +#include +struct deviceDescriptorStruct +{ +public: + QString gitTag; + QString buildDate; + QString description; + int boardType; + int boardRevision; + static QString idToBoardName(int id) + { + switch (id | 0x0011) { + case 0x0111://MB + return QString("Board name: OpenPilot MainBoard"); + break; + case 0x0311://PipX + return QString("Board name: PipXtreame"); + break; + case 0x0411://Coptercontrol + return QString("Board name: CopterControl"); + break; + case 0x0211://INS + return QString("Board name: OpenPilot INS"); + break; + default: + return QString(""); + break; + } + } + deviceDescriptorStruct(); +}; + +#endif // DEVICEDESCRIPTORSTRUCT_H diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp index a5c68e252..7751ee416 100644 --- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.cpp @@ -34,16 +34,18 @@ deviceWidget::deviceWidget(QWidget *parent) : devicePic = NULL; // Initialize pointer to null // Initialization of the Device icon display - myDevice->devicePicture->setScene(new QGraphicsScene(this)); - - connect(myDevice->verifyButton, SIGNAL(clicked()), this, SLOT(verifyFirmware())); + myDevice->verticalGroupBox_loaded->setVisible(false); + myDevice->groupCustom->setVisible(false); + myDevice->youdont->setVisible(false); + myDevice->gVDevice->setScene(new QGraphicsScene(this)); connect(myDevice->retrieveButton, SIGNAL(clicked()), this, SLOT(downloadFirmware())); connect(myDevice->updateButton, SIGNAL(clicked()), this, SLOT(uploadFirmware())); - + connect(myDevice->pbLoad, SIGNAL(clicked()), this, SLOT(loadFirmware())); + connect(myDevice->youdont, SIGNAL(stateChanged(int)), this, SLOT(confirmCB(int))); QPixmap pix = QPixmap(QString(":uploader/images/view-refresh.svg")); myDevice->statusIcon->setPixmap(pix); - myDevice->certifiedFW->setText(""); + myDevice->lblCertified->setText(""); } @@ -54,14 +56,16 @@ void deviceWidget::showEvent(QShowEvent *event) // widget is shown, otherwise it cannot compute its values and // the result is usually a ahrsbargraph that is way too small. if (devicePic) - myDevice->devicePicture->fitInView(devicePic,Qt::KeepAspectRatio); + { + myDevice->gVDevice->fitInView(devicePic,Qt::KeepAspectRatio); + } } void deviceWidget::resizeEvent(QResizeEvent* event) { Q_UNUSED(event); if (devicePic) - myDevice->devicePicture->fitInView(devicePic, Qt::KeepAspectRatio); + myDevice->gVDevice->fitInView(devicePic, Qt::KeepAspectRatio); } @@ -74,21 +78,43 @@ void deviceWidget::setDfu(DFUObject *dfu) m_dfu = dfu; } +QString deviceWidget::idToBoardName(int id) +{ + switch (id | 0x0011) { + case 0x0111://MB + return QString("Board name: OpenPilot MainBoard"); + break; + case 0x0311://PipX + return QString("Board name: PipXtreame"); + break; + case 0x0411://Coptercontrol + return QString("Board name: CopterControl"); + break; + case 0x0211://INS + return QString("Board name: OpenPilot INS"); + break; + default: + return QString(""); + break; + } +} + /** Fills the various fields for the device */ void deviceWidget::populate() { + int id = m_dfu->devices[deviceID].ID; - myDevice->deviceID->setText(QString("Device ID: ") + QString::number(id, 16)); + myDevice->lbldevID->setText(QString("Device ID: ") + QString::number(id, 16)); // DeviceID tells us what sort of HW we have detected: // display a nice icon: - myDevice->devicePicture->scene()->clear(); - if (devicePic) - delete devicePic; + myDevice->gVDevice->scene()->clear(); + myDevice->lblDevName->setText(deviceDescriptorStruct::idToBoardName(id)); + myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x0011, 16)); + devicePic = new QGraphicsSvgItem(); devicePic->setSharedRenderer(new QSvgRenderer()); - switch (id) { case 0x0101: devicePic->renderer()->load(QString(":/uploader/images/deviceID-0101.svg")); @@ -106,35 +132,35 @@ void deviceWidget::populate() break; } devicePic->setElementId("device"); - myDevice->devicePicture->scene()->addItem(devicePic); - myDevice->devicePicture->setSceneRect(devicePic->boundingRect()); - myDevice->devicePicture->fitInView(devicePic,Qt::KeepAspectRatio); + myDevice->gVDevice->scene()->addItem(devicePic); + myDevice->gVDevice->setSceneRect(devicePic->boundingRect()); + myDevice->gVDevice->fitInView(devicePic,Qt::KeepAspectRatio); bool r = m_dfu->devices[deviceID].Readable; bool w = m_dfu->devices[deviceID].Writable; - myDevice->deviceACL->setText(QString("Access: ") + QString(r ? "R" : "-") + QString(w ? "W" : "-")); - myDevice->maxCodeSize->setText(QString("Max code size: ") +QString::number(m_dfu->devices[deviceID].SizeOfCode)); - myDevice->fwCRC->setText(QString("FW CRC: ") + QString::number(m_dfu->devices[deviceID].FW_CRC)); - myDevice->BLVersion->setText(QString("BL Version: ") + QString::number(m_dfu->devices[deviceID].BL_Version)); + myDevice->lblAccess->setText(QString("Flash access: ") + QString(r ? "R" : "-") + QString(w ? "W" : "-")); + myDevice->lblMaxCode->setText(QString("Max code size: ") +QString::number(m_dfu->devices[deviceID].SizeOfCode)); + myDevice->lblCRC->setText(QString("Firmware CRC: ") + QString::number(m_dfu->devices[deviceID].FW_CRC)); + myDevice->lblBLVer->setText(QString("BL version: ") + QString::number(m_dfu->devices[deviceID].BL_Version)); int size=((OP_DFU::device)m_dfu->devices[deviceID]).SizeOfDesc; m_dfu->enterDFU(deviceID); QByteArray desc = m_dfu->DownloadDescriptionAsBA(size); - if (! populateStructuredDescription(desc)) { + + if (! populateBoardStructuredDescription(desc)) { + //TODO // desc was not a structured description QString str = m_dfu->DownloadDescription(size); - myDevice->description->setMaxLength(size); - myDevice->description->setText(str.left(str.indexOf(QChar(255)))); - QPixmap pix = QPixmap(QString(":uploader/images/gtk-info.svg")); - myDevice->certifiedFW->setPixmap(pix); - myDevice->certifiedFW->setToolTip(tr("Custom Firmware Build")); - myDevice->buildDate->setText("Warning: development firmware"); - myDevice->commitTag->setText(""); + myDevice->lblDescription->setText(QString("Firmware custom description: ")+str.left(str.indexOf(QChar(255)))); + QPixmap pix = QPixmap(QString(":uploader/images/warning.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Custom Firmware Build")); + myDevice->lblBuildDate->setText("Warning: development firmware"); + myDevice->lblGitTag->setText(""); + myDevice->lblBrdName->setText(""); } - status("Ready...", STATUSICON_INFO); - } /** @@ -143,61 +169,75 @@ void deviceWidget::populate() */ void deviceWidget::freeze() { - myDevice->description->setEnabled(false); - myDevice->updateButton->setEnabled(false); - myDevice->verifyButton->setEnabled(false); - myDevice->retrieveButton->setEnabled(false); + myDevice->description->setEnabled(false); + myDevice->updateButton->setEnabled(false); + myDevice->retrieveButton->setEnabled(false); } - /** Populates the widget field with the description in case it is structured properly */ -bool deviceWidget::populateStructuredDescription(QByteArray desc) +bool deviceWidget::populateBoardStructuredDescription(QByteArray desc) { - if (desc.startsWith("OpFw")) { - // This looks like a binary with a description at the end - /* - # 4 bytes: header: "OpFw" - # 4 bytes: GIT commit tag (short version of SHA1) - # 4 bytes: Unix timestamp of compile time - # 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. - # 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded - # ---- 40 bytes limit --- - # 20 bytes: SHA1 sum of the firmware. - # 40 bytes: free for now. - */ + if(UploaderGadgetWidget::descriptionToStructure(desc,&onBoardDescrition)) + { + myDevice->lblGitTag->setText("Git commit tag: "+onBoardDescrition.gitTag); + myDevice->lblBuildDate->setText(QString("Firmware date: ") + onBoardDescrition.buildDate); + if(onBoardDescrition.description.startsWith("release",Qt::CaseInsensitive)) + { + myDevice->lblDescription->setText(QString("Firmware tag: ")+onBoardDescrition.description); + QPixmap pix = QPixmap(QString(":uploader/images/application-certificate.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Official Firmware Build")); - // Note: the ARM binary is big-endian: - quint32 gitCommitTag = desc.at(7)&0xFF; - for (int i=1;i<4;i++) { - gitCommitTag = gitCommitTag<<8; - gitCommitTag += desc.at(7-i) & 0xFF; } - myDevice->commitTag->setText("GIT tag 0x" + QString::number(gitCommitTag,16)); - quint32 buildDate = desc.at(11)&0xFF; - for (int i=1;i<4;i++) { - buildDate = buildDate<<8; - buildDate += desc.at(11-i) & 0xFF; + else + { + myDevice->lblDescription->setText(QString("Firmware tag: ")+onBoardDescrition.description+QString(" (beta or custom build)")); + QPixmap pix = QPixmap(QString(":uploader/images/warning.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Custom Firmware Build")); } - myDevice->buildDate->setText(QString("Build time: ") + QDateTime::fromTime_t(buildDate).toString()); - QByteArray targetPlatform = desc.mid(12,2); - // TODO: check platform compatibility - QString dscText = QString(desc.mid(14,26)); - myDevice->description->setText(dscText); + myDevice->lblBrdName->setText(idToBoardName(onBoardDescrition.boardType<<8)); - QPixmap pix = QPixmap(QString(":uploader/images/application-certificate.svg")); - myDevice->certifiedFW->setPixmap(pix); - myDevice->certifiedFW->setToolTip(tr("Official Firmware Build")); return true; } return false; } +bool deviceWidget::populateLoadedStructuredDescription(QByteArray desc) +{ + if(UploaderGadgetWidget::descriptionToStructure(desc,&LoadedDescrition)) + { + myDevice->lblGitTagL->setText("Git commit tag: "+LoadedDescrition.gitTag); + myDevice->lblBuildDateL->setText(QString("Firmware date: ") + LoadedDescrition.buildDate); + if(LoadedDescrition.description.startsWith("release",Qt::CaseInsensitive)) + { + myDevice->lblDescritpionL->setText(QString("Firmware tag: ")+LoadedDescrition.description); + myDevice->description->setText(LoadedDescrition.description); + QPixmap pix = QPixmap(QString(":uploader/images/application-certificate.svg")); + myDevice->lblCertifiedL->setPixmap(pix); + myDevice->lblCertifiedL->setToolTip(tr("Official Firmware Build")); + } + else + { + myDevice->lblDescritpionL->setText(QString("Firmware tag: ")+LoadedDescrition.description+QString(" (beta or custom build)")); + myDevice->description->setText(LoadedDescrition.description); + QPixmap pix = QPixmap(QString(":uploader/images/warning.svg")); + myDevice->lblCertifiedL->setPixmap(pix); + myDevice->lblCertifiedL->setToolTip(tr("Custom Firmware Build")); + } + myDevice->lblBrdNameL->setText(deviceDescriptorStruct::idToBoardName(LoadedDescrition.boardType<<8)); + return true; + } + + return false; + +} /** Updates status message for messages coming from DFU */ @@ -206,6 +246,16 @@ void deviceWidget::dfuStatus(QString str) status(str, STATUSICON_RUNNING); } +void deviceWidget::confirmCB(int value) +{ + if(value==Qt::Checked) + { + myDevice->updateButton->setEnabled(true); + } + else + myDevice->updateButton->setEnabled(false); +} + /** Updates status message */ @@ -229,11 +279,74 @@ void deviceWidget::status(QString str, StatusIcon ic) myDevice->statusIcon->setPixmap(px); } -/** - Verifies the firmware CRC - */ -void deviceWidget::verifyFirmware() + +void deviceWidget::loadFirmware() { + myDevice->verticalGroupBox_loaded->setVisible(false); + myDevice->groupCustom->setVisible(false); + + filename = setOpenFileName(); + + if (filename.isEmpty()) { + status("Empty filename", STATUSICON_FAIL); + return; + } + + QFile file(filename); + if (!file.open(QIODevice::ReadOnly)) { + status("Can't open file", STATUSICON_FAIL); + return; + } + + loadedFW = file.readAll(); + myDevice->youdont->setVisible(false); + myDevice->youdont->setChecked(false); + QByteArray desc = loadedFW.right(100); + QPixmap px; + myDevice->lblCRCL->setText(QString("FW CRC: ") + QString::number(DFUObject::CRCFromQBArray(loadedFW,m_dfu->devices[deviceID].SizeOfCode))); + myDevice->lblFirmwareSizeL->setText(QString("Firmware size: ")+QVariant(loadedFW.length()).toString()+ QString(" bytes")); + if (populateLoadedStructuredDescription(desc)) + { + myDevice->youdont->setChecked(true); + myDevice->verticalGroupBox_loaded->setVisible(true); + myDevice->groupCustom->setVisible(false); + if(myDevice->lblCRC->text()==myDevice->lblCRCL->text()) + { + myDevice->statusLabel->setText(tr("The loaded firmware maches the firmware on the board. You shouldn't upload it")); + px.load(QString(":/uploader/images/warning.svg")); + } + else if(myDevice->lblDevName->text()!=myDevice->lblBrdNameL->text()) + { + myDevice->statusLabel->setText(tr("The loaded firmware is not suited for the HW connected. You shouldn't upload it")); + px.load(QString(":/uploader/images/warning.svg")); + } + else if(QDateTime::fromString(onBoardDescrition.buildDate)>QDateTime::fromString(LoadedDescrition.buildDate)) + { + myDevice->statusLabel->setText(tr("The loaded firmware is older then the firmware on the board. You shouldn't upload it")); + px.load(QString(":/uploader/images/warning.svg")); + } + else if(!LoadedDescrition.description.startsWith("release",Qt::CaseInsensitive)) + { + myDevice->statusLabel->setText(tr("The loaded firmware is not an oficial OpenPilot release. You should upload it only if you know what you are doing")); + px.load(QString(":/uploader/images/warning.svg")); + } + else + { + myDevice->statusLabel->setText(tr("Everything seems OK. You should upload the loaded firmware by pressing 'upload'")); + px.load(QString(":/uploader/images/gtk-info.svg")); + } + } + else + { + myDevice->statusLabel->setText(tr("The loaded firmware was not packaged with a compatible format. You shouldn't' upload it, if you know what you are doing and still want to upload it confirm it by checking the checkbox bellow")); + px.load(QString(":/uploader/images/warning.svg")); + myDevice->youdont->setChecked(false); + myDevice->youdont->setVisible(true); + myDevice->verticalGroupBox_loaded->setVisible(false); + myDevice->groupCustom->setVisible(true); + } + myDevice->statusIcon->setPixmap(px); + //myDevice->updateButton->setEnabled(true); } @@ -253,22 +366,8 @@ void deviceWidget::uploadFirmware() verify = true; */ - QString filename = setOpenFileName(); - - if (filename.isEmpty()) { - status("Empty filename", STATUSICON_FAIL); - return; - } - - QFile file(filename); - if (!file.open(QIODevice::ReadOnly)) { - status("Can't open file", STATUSICON_FAIL); - return; - } - - QByteArray arr = file.readAll(); - QByteArray desc = arr.right(100); - if (populateStructuredDescription(desc)) { + QByteArray desc = loadedFW.right(100); + if (desc.startsWith("OpFw")) { descriptionArray = desc; // Now do sanity checking: // - Check whether board type matches firmware: @@ -280,7 +379,7 @@ void deviceWidget::uploadFirmware() } // Check the firmware embedded in the file: QByteArray firmwareHash = desc.mid(40,20); - QByteArray fileHash = QCryptographicHash::hash(arr.left(arr.length()-100), QCryptographicHash::Sha1); + QByteArray fileHash = QCryptographicHash::hash(loadedFW.left(loadedFW.length()-100), QCryptographicHash::Sha1); if (firmwareHash != fileHash) { status("Error: firmware file corrupt", STATUSICON_FAIL); return; @@ -370,27 +469,27 @@ void deviceWidget::uploadFinished(OP_DFU::Status retstatus) status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL); return; } else - if (!descriptionArray.isEmpty()) { - // We have a structured array to save - status(QString("Updating description"), STATUSICON_RUNNING); - repaint(); // Make sure the text above shows right away - retstatus = m_dfu->UploadDescription(descriptionArray); - if( retstatus != OP_DFU::Last_operation_Success) { - status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL); - return; + if (!descriptionArray.isEmpty()) { + // We have a structured array to save + status(QString("Updating description"), STATUSICON_RUNNING); + repaint(); // Make sure the text above shows right away + retstatus = m_dfu->UploadDescription(descriptionArray); + if( retstatus != OP_DFU::Last_operation_Success) { + status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL); + return; + } + + } else if (!myDevice->description->text().isEmpty()) { + // Fallback: we save the description field: + status(QString("Updating description"), STATUSICON_RUNNING); + repaint(); // Make sure the text above shows right away + retstatus = m_dfu->UploadDescription(myDevice->description->text()); + if( retstatus != OP_DFU::Last_operation_Success) { + status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL); + return; + } } - - } else if (!myDevice->description->text().isEmpty()) { - // Fallback: we save the description field: - status(QString("Updating description"), STATUSICON_RUNNING); - repaint(); // Make sure the text above shows right away - retstatus = m_dfu->UploadDescription(myDevice->description->text()); - if( retstatus != OP_DFU::Last_operation_Success) { - status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL); - return; - } - } - + populate(); status("Upload successful", STATUSICON_OK); } diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.h b/ground/openpilotgcs/src/plugins/uploader/devicewidget.h index 68905c0c2..772216e3b 100644 --- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.h @@ -38,9 +38,9 @@ #include #include #include - +#include "uavobjectutilmanager.h" +#include "devicedescriptorstruct.h" using namespace OP_DFU; - class deviceWidget : public QWidget { Q_OBJECT @@ -54,6 +54,10 @@ public: QString setOpenFileName(); QString setSaveFileName(); private: + deviceDescriptorStruct onBoardDescrition; + deviceDescriptorStruct LoadedDescrition; + QByteArray loadedFW; + QString idToBoardName(int id); Ui_deviceWidget *myDevice; int deviceID; DFUObject *m_dfu; @@ -62,19 +66,20 @@ private: QGraphicsSvgItem *devicePic; QByteArray descriptionArray; void status(QString str, StatusIcon ic); - bool populateStructuredDescription(QByteArray arr); - + bool populateBoardStructuredDescription(QByteArray arr); + bool populateLoadedStructuredDescription(QByteArray arr); signals: public slots: - void verifyFirmware(); void uploadFirmware(); + void loadFirmware(); void downloadFirmware(); void setProgress(int); void downloadFinished(); void uploadFinished(OP_DFU::Status); void dfuStatus(QString); + void confirmCB(int); protected: void showEvent(QShowEvent *event); diff --git a/ground/openpilotgcs/src/plugins/uploader/devicewidget.ui b/ground/openpilotgcs/src/plugins/uploader/devicewidget.ui index ec45f52df..0543bcbc9 100644 --- a/ground/openpilotgcs/src/plugins/uploader/devicewidget.ui +++ b/ground/openpilotgcs/src/plugins/uploader/devicewidget.ui @@ -7,7 +7,7 @@ 0 0 516 - 253 + 582 @@ -15,164 +15,310 @@ - - - - - true - - - - - - - DeviceID - - - - - - - 0 - - - - - - - ReadWrite - - - - - - - - 160 - 160 - - - - background: transparent - - - QFrame::NoFrame - - - - - - - false - - - Verify... - - - - - - - Update the firmware on this board. - - - Update... - - - - - - - Download the current board firmware to your computer - - - Retrieve... - - - - - - - BootLoaderVersion - - - - - - - fwCRC - - - - - - - MaxCodeSize - - - - - - - - - ic - - - - - - - - 0 - 0 - - - - - 75 - true - - - - Status - - - - - - - - - Commit tag - - - - - - - - - certified - - - - - - - - 0 - 0 - - - - buildDate - - - - - - + + + Device Information + + + + + + + + + 160 + 160 + + + + background: transparent + + + + + + + + + lblDevName + + + + + + + DeviceID + + + + + + + lblHWRev + + + + + + + RW + + + + + + + BL Version + + + + + + + MaxCodeSize + + + + + + + + + + + Loads the firmware + + + Open + + + + + + + false + + + Update the firmware on this board. + + + Flash + + + + + + + Download the current board firmware to your computer + + + Retrieve... + + + + + + + + + + + 0 + + + + + + + + + ic + + + + + + + + 0 + 0 + + + + + 75 + true + + + + Status + + + true + + + + + + + + + I know what I'm doing + + + true + + + + + + + + + + Firmware currently on the device + + + + + + + + + + lblBrdName + + + + + + + lblDescription + + + + + + + lblBuildDate + + + + + + + lblGitTag + + + + + + + lblCRC + + + + + + + + + lblCertified + + + false + + + + + + + + + + + + true + + + Loaded Firmware + + + + + + + + + + lblBrdName + + + + + + + lblDescritpionL + + + + + + + lblBuildDate + + + + + + + lblGitTag + + + + + + + lblCRC + + + + + + + lblFirmwareSizeL + + + + + + + + + lblCertifiedL + + + + + + + + + + + + + + + Custom description: + + + + + + + + diff --git a/ground/openpilotgcs/src/plugins/uploader/images/warning.svg b/ground/openpilotgcs/src/plugins/uploader/images/warning.svg new file mode 100644 index 000000000..cd684c4e1 --- /dev/null +++ b/ground/openpilotgcs/src/plugins/uploader/images/warning.svg @@ -0,0 +1,102 @@ + + + +image/svg+xml + + + + + + + + + + + + + \ No newline at end of file diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp index a3fe178c6..8a9045233 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.cpp @@ -718,7 +718,7 @@ OP_DFU::Status DFUObject::UploadFirmwareT(const QString &sfile, const bool &veri return OP_DFU::abort;; } - quint32 crc=CRCFromQBArray(arr,devices[device].SizeOfCode); + quint32 crc=DFUObject::CRCFromQBArray(arr,devices[device].SizeOfCode); if (debug) qDebug() << "NEW FIRMWARE CRC=" << crc; @@ -817,7 +817,7 @@ OP_DFU::Status DFUObject::CompareFirmware(const QString &sfile, const CompareTyp } if(type==OP_DFU::crccompare) { - quint32 crc=CRCFromQBArray(arr,devices[device].SizeOfCode); + quint32 crc=DFUObject::CRCFromQBArray(arr,devices[device].SizeOfCode); if(crc==devices[device].FW_CRC) { cout<<"Compare Successfull CRC MATCH!\n"; @@ -971,7 +971,7 @@ quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size) aux+=(char)array[x*4+0]&0xFF; t[x]=aux; } - return CRC32WideFast(0xFFFFFFFF,Size/4,(quint32*)t); + return DFUObject::CRC32WideFast(0xFFFFFFFF,Size/4,(quint32*)t); } diff --git a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h index c58621f67..420e0a3ea 100644 --- a/ground/openpilotgcs/src/plugins/uploader/op_dfu.h +++ b/ground/openpilotgcs/src/plugins/uploader/op_dfu.h @@ -108,7 +108,7 @@ namespace OP_DFU { Q_OBJECT; public: - + static quint32 CRCFromQBArray(QByteArray array, quint32 Size); //DFUObject(bool debug); DFUObject(bool debug,bool use_serial,QString port); @@ -152,7 +152,7 @@ namespace OP_DFU { // Helper functions: QString StatusToString(OP_DFU::Status const & status); - quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer); + static quint32 CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer); @@ -179,7 +179,7 @@ namespace OP_DFU { // USB Bootloader: pjrc_rawhid hidHandle; int setStartBit(int command){ return command|0x20; } - quint32 CRCFromQBArray(QByteArray array, quint32 Size); + void CopyWords(char * source, char* destination, int count); void printProgBar( int const & percent,QString const& label); bool StartUpload(qint32 const &numberOfBytes, TransferTypes const & type,quint32 crc); diff --git a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp index f1511e746..9b56f2dfb 100644 --- a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.cpp @@ -25,7 +25,8 @@ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "runningdevicewidget.h" - +#include "devicedescriptorstruct.h" +#include "uploadergadgetwidget.h" runningDeviceWidget::runningDeviceWidget(QWidget *parent) : QWidget(parent) { @@ -68,8 +69,11 @@ void runningDeviceWidget::populate() UAVObjectUtilManager* utilMngr = pm->getObject(); int id = utilMngr->getBoardModel(); - myDevice->deviceID->setText(QString("Device ID: ") + QString::number(id, 16)); - + myDevice->lblDeviceID->setText(QString("Device ID: ") + QString::number(id, 16)); + myDevice->lblBoardName->setText(deviceDescriptorStruct::idToBoardName(id)); + myDevice->lblHWRev->setText(QString(tr("HW Revision: "))+QString::number(id & 0x0011, 16)); + qDebug()<<"CRC"<getFirmwareCRC(); + myDevice->lblCRC->setText(QString(tr("Firmware CRC: "))+QVariant(utilMngr->getFirmwareCRC()).toString()); // DeviceID tells us what sort of HW we have detected: // display a nice icon: myDevice->devicePicture->scene()->clear(); @@ -100,13 +104,41 @@ void runningDeviceWidget::populate() myDevice->devicePicture->fitInView(devicePic,Qt::KeepAspectRatio); QString serial = utilMngr->getBoardCPUSerial().toHex(); - myDevice->cpuSerial->setText(serial); + myDevice->lblCPU->setText(QString("CPU serial number: "+serial)); - QString description = utilMngr->getBoardDescription(); - myDevice->description->setText(description); + QByteArray description = utilMngr->getBoardDescription(); + deviceDescriptorStruct devDesc; + if(UploaderGadgetWidget::descriptionToStructure(description,&devDesc)) + { + if(devDesc.description.startsWith("release",Qt::CaseInsensitive)) + { + myDevice->lblFWTag->setText(QString("Firmware tag: ")+devDesc.description); + QPixmap pix = QPixmap(QString(":uploader/images/application-certificate.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Official Firmware Build")); + } + else + { + myDevice->lblFWTag->setText(QString("Firmware tag: ")+devDesc.description+QString(" (beta or custom build)")); + QPixmap pix = QPixmap(QString(":uploader/images/warning.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Custom Firmware Build")); + } + myDevice->lblGitCommitTag->setText("Git commit tag: "+devDesc.gitTag); + myDevice->lblFWDate->setText(QString("Firmware date: ") + devDesc.buildDate); + } + else + { + + myDevice->lblFWTag->setText(QString("Firmware tag: ")+QString(description).left(QString(description).indexOf(QChar(255)))); + myDevice->lblGitCommitTag->setText("Git commit tag: Unknown"); + myDevice->lblFWDate->setText(QString("Firmware date: Unknown")); + QPixmap pix = QPixmap(QString(":uploader/images/warning.svg")); + myDevice->lblCertified->setPixmap(pix); + myDevice->lblCertified->setToolTip(tr("Custom Firmware Build")); + } status("Ready...", STATUSICON_INFO); - } diff --git a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.h b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.h index 413a406fd..a1b77b3ba 100644 --- a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.h @@ -29,7 +29,7 @@ #define RUNNINGDEVICEWIDGET_H #include "ui_runningdevicewidget.h" -#include "uploadergadgetwidget.h" + #include #include #include diff --git a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.ui b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.ui index 4a730c509..1f69d407f 100644 --- a/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.ui +++ b/ground/openpilotgcs/src/plugins/uploader/runningdevicewidget.ui @@ -14,9 +14,114 @@ Form + + + + Device Information + + + + + + + 160 + 160 + + + + background: transparent + + + QFrame::NoFrame + + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + + + + Firmware Information + + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + TextLabel + + + + + + + + + TextLabel + + + + + + - + @@ -46,50 +151,6 @@ - - - - DeviceID - - - - - - - CPU Serial: - - - - - - - - 160 - 160 - - - - background: transparent - - - QFrame::NoFrame - - - - - - - true - - - - - - - true - - - diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader.pro b/ground/openpilotgcs/src/plugins/uploader/uploader.pro index 05742868d..32424509b 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploader.pro +++ b/ground/openpilotgcs/src/plugins/uploader/uploader.pro @@ -22,7 +22,8 @@ HEADERS += uploadergadget.h \ SSP/qssp.h \ SSP/qsspt.h \ SSP/common.h \ - runningdevicewidget.h + runningdevicewidget.h \ + devicedescriptorstruct.h SOURCES += uploadergadget.cpp \ uploadergadgetconfiguration.cpp \ uploadergadgetfactory.cpp \ @@ -35,7 +36,8 @@ SOURCES += uploadergadget.cpp \ SSP/port.cpp \ SSP/qssp.cpp \ SSP/qsspt.cpp \ - runningdevicewidget.cpp + runningdevicewidget.cpp \ + devicedescriptorstruct.cpp OTHER_FILES += Uploader.pluginspec FORMS += \ diff --git a/ground/openpilotgcs/src/plugins/uploader/uploader.qrc b/ground/openpilotgcs/src/plugins/uploader/uploader.qrc index 1008ef3ba..f51ea265c 100644 --- a/ground/openpilotgcs/src/plugins/uploader/uploader.qrc +++ b/ground/openpilotgcs/src/plugins/uploader/uploader.qrc @@ -10,5 +10,6 @@ images/deviceID-0201.svg images/deviceID-0101.svg images/application-certificate.svg + images/warning.svg diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp index 397533c2b..3a5427a6c 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.cpp @@ -27,7 +27,44 @@ #include "uploadergadgetwidget.h" #define DFU_DEBUG true +bool UploaderGadgetWidget::descriptionToStructure(QByteArray desc,deviceDescriptorStruct * struc) +{ + if (desc.startsWith("OpFw")) { + // This looks like a binary with a description at the end + /* + # 4 bytes: header: "OpFw" + # 4 bytes: GIT commit tag (short version of SHA1) + # 4 bytes: Unix timestamp of compile time + # 2 bytes: target platform. Should follow same rule as BOARD_TYPE and BOARD_REVISION in board define files. + # 26 bytes: commit tag if it is there, otherwise "Unreleased". Zero-padded + # ---- 40 bytes limit --- + # 20 bytes: SHA1 sum of the firmware. + # 40 bytes: free for now. + */ + // Note: the ARM binary is big-endian: + quint32 gitCommitTag = desc.at(7)&0xFF; + for (int i=1;i<4;i++) { + gitCommitTag = gitCommitTag<<8; + gitCommitTag += desc.at(7-i) & 0xFF; + } + struc->gitTag=QString::number(gitCommitTag,16); + quint32 buildDate = desc.at(11)&0xFF; + for (int i=1;i<4;i++) { + buildDate = buildDate<<8; + buildDate += desc.at(11-i) & 0xFF; + } + struc->buildDate= QDateTime::fromTime_t(buildDate).toLocalTime().toString("yyyy MMMM dd HH:mm:ss"); + QByteArray targetPlatform = desc.mid(12,2); + // TODO: check platform compatibility + QString dscText = QString(desc.mid(14,26)); + struc->boardType=(int)targetPlatform.at(0); + struc->boardRevision=(int)targetPlatform.at(1); + struc->description=dscText; + return true; + } + return false; +} UploaderGadgetWidget::UploaderGadgetWidget(QWidget *parent) : QWidget(parent) { m_config = new Ui_UploaderWidget(); diff --git a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h index 8fb167a82..81d39e44f 100755 --- a/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h +++ b/ground/openpilotgcs/src/plugins/uploader/uploadergadgetwidget.h @@ -52,20 +52,23 @@ #include #include #include - +#include "devicedescriptorstruct.h" #include using namespace OP_DFU; + class UploaderGadgetWidget : public QWidget { Q_OBJECT + public: UploaderGadgetWidget(QWidget *parent = 0); ~UploaderGadgetWidget(); typedef enum { IAP_STATE_READY, IAP_STATE_STEP_1, IAP_STATE_STEP_2, IAP_STEP_RESET, IAP_STATE_BOOTLOADER} IAPStep; void log(QString str); + static bool descriptionToStructure(QByteArray desc,deviceDescriptorStruct * struc); public slots: void onAutopilotConnect();