mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-11-30 08:24:11 +01:00
GCS-side implementation: if a firmware is package with description 100 byte bin blob at the end, it will use it, and parse it back
if description is structured the same way.
This commit is contained in:
parent
b61bd5bf31
commit
4af0c562e3
@ -117,9 +117,16 @@ void deviceWidget::populate()
|
|||||||
|
|
||||||
int size=((OP_DFU::device)m_dfu->devices[deviceID]).SizeOfDesc;
|
int size=((OP_DFU::device)m_dfu->devices[deviceID]).SizeOfDesc;
|
||||||
m_dfu->enterDFU(deviceID);
|
m_dfu->enterDFU(deviceID);
|
||||||
QString str = m_dfu->DownloadDescription(size);
|
QByteArray desc = m_dfu->DownloadDescriptionAsBA(size);
|
||||||
myDevice->description->setMaxLength(size);
|
if (! populateStructuredDescription(desc)) {
|
||||||
myDevice->description->setText(str.left(str.indexOf(QChar(255))));
|
// 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))));
|
||||||
|
myDevice->buildDate->setText("Warning: development firmware");
|
||||||
|
myDevice->commitTag->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
status("Ready...", STATUSICON_INFO);
|
status("Ready...", STATUSICON_INFO);
|
||||||
|
|
||||||
@ -137,6 +144,51 @@ void deviceWidget::freeze()
|
|||||||
myDevice->retrieveButton->setEnabled(false);
|
myDevice->retrieveButton->setEnabled(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Populates the widget field with the description in case
|
||||||
|
it is structured properly
|
||||||
|
*/
|
||||||
|
bool deviceWidget::populateStructuredDescription(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.
|
||||||
|
*/
|
||||||
|
// I don't want to use structs, ok ?
|
||||||
|
quint32 gitCommitTag = desc.at(4)&0xFF;
|
||||||
|
for (int i=1;i<4;i++) {
|
||||||
|
gitCommitTag = gitCommitTag<<8;
|
||||||
|
gitCommitTag += desc.at(4+i) & 0xFF;
|
||||||
|
}
|
||||||
|
myDevice->commitTag->setText("GIT tag 0x" + QString::number(gitCommitTag,16));
|
||||||
|
quint32 buildDate = desc.at(8)&0xFF;
|
||||||
|
for (int i=1;i<4;i++) {
|
||||||
|
buildDate = buildDate<<8;
|
||||||
|
buildDate += desc.at(8+i) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Updates status message for messages coming from DFU
|
Updates status message for messages coming from DFU
|
||||||
*/
|
*/
|
||||||
@ -199,8 +251,6 @@ void deviceWidget::uploadFirmware()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO : parse the firmware last 100 bytes and see whether it is
|
|
||||||
// packaged:
|
|
||||||
QFile file(filename);
|
QFile file(filename);
|
||||||
if (!file.open(QIODevice::ReadOnly)) {
|
if (!file.open(QIODevice::ReadOnly)) {
|
||||||
status("Can't open file", STATUSICON_FAIL);
|
status("Can't open file", STATUSICON_FAIL);
|
||||||
@ -209,36 +259,11 @@ void deviceWidget::uploadFirmware()
|
|||||||
|
|
||||||
QByteArray arr = file.readAll();
|
QByteArray arr = file.readAll();
|
||||||
QByteArray desc = arr.right(100);
|
QByteArray desc = arr.right(100);
|
||||||
if (desc.startsWith("OpFw")) {
|
if (populateStructuredDescription(desc)) {
|
||||||
// This looks like a binary with a description at the end
|
descriptionArray = desc;
|
||||||
/*
|
|
||||||
# 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.
|
|
||||||
*/
|
|
||||||
// I don't want to use structs, ok ?
|
|
||||||
QByteArray gitCommitTag = desc.mid(4,4);
|
|
||||||
quint32 buildDate = desc.at(8)&0xFF;
|
|
||||||
for (int i=1;i<4;i++) {
|
|
||||||
buildDate = buildDate<<8;
|
|
||||||
buildDate += desc.at(8+i) & 0xFF;
|
|
||||||
}
|
|
||||||
|
|
||||||
myDevice->buildDate->setText(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);
|
|
||||||
|
|
||||||
return;
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
// TODO : tell the user that the firmware is not packaged.
|
// TODO : tell the user that the firmware is not packaged.
|
||||||
|
descriptionArray.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -320,15 +345,27 @@ void deviceWidget::uploadFinished(OP_DFU::Status retstatus)
|
|||||||
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
||||||
return;
|
return;
|
||||||
} else
|
} else
|
||||||
if(!myDevice->description->text().isEmpty()) {
|
if (!descriptionArray.isEmpty()) {
|
||||||
|
// We have a structured array to save
|
||||||
status(QString("Updating description"), STATUSICON_RUNNING);
|
status(QString("Updating description"), STATUSICON_RUNNING);
|
||||||
repaint(); // Make sure the text above shows right away
|
repaint(); // Make sure the text above shows right away
|
||||||
retstatus = m_dfu->UploadDescription(myDevice->description->text());
|
retstatus = m_dfu->UploadDescription(descriptionArray);
|
||||||
if( retstatus != OP_DFU::Last_operation_Success) {
|
if( retstatus != OP_DFU::Last_operation_Success) {
|
||||||
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
status(QString("Upload failed with code: ") + m_dfu->StatusToString(retstatus).toLatin1().data(), STATUSICON_FAIL);
|
||||||
return;
|
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;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
status("Upload successful", STATUSICON_OK);
|
status("Upload successful", STATUSICON_OK);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,9 @@ private:
|
|||||||
QByteArray downloadedFirmware;
|
QByteArray downloadedFirmware;
|
||||||
QString filename;
|
QString filename;
|
||||||
QGraphicsSvgItem *devicePic;
|
QGraphicsSvgItem *devicePic;
|
||||||
|
QByteArray descriptionArray;
|
||||||
void status(QString str, StatusIcon ic);
|
void status(QString str, StatusIcon ic);
|
||||||
|
bool populateStructuredDescription(QByteArray arr);
|
||||||
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
|
@ -137,17 +137,17 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
<item row="6" column="0">
|
<item row="3" column="0" colspan="2">
|
||||||
<widget class="QLabel" name="buildDate">
|
<widget class="QLabel" name="buildDate">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Compile Date</string>
|
<string>Build Date</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
<item row="3" column="0" colspan="2">
|
<item row="6" column="0">
|
||||||
<widget class="QLabel" name="commitTag">
|
<widget class="QLabel" name="commitTag">
|
||||||
<property name="text">
|
<property name="text">
|
||||||
<string>Commit tag:</string>
|
<string>Commit tag</string>
|
||||||
</property>
|
</property>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
|
@ -276,22 +276,31 @@ bool DFUObject::UploadData(qint32 const & numberOfBytes, QByteArray & data)
|
|||||||
/**
|
/**
|
||||||
Sends the firmware description to the device
|
Sends the firmware description to the device
|
||||||
*/
|
*/
|
||||||
OP_DFU::Status DFUObject::UploadDescription(QString description)
|
OP_DFU::Status DFUObject::UploadDescription(QVariant desc)
|
||||||
{
|
{
|
||||||
cout<<"Starting uploading description\n";
|
cout<<"Starting uploading description\n";
|
||||||
if(description.length()%4!=0)
|
QByteArray array;
|
||||||
{
|
|
||||||
int pad=description.length()/4;
|
if (desc.type() == QMetaType::QString) {
|
||||||
pad=(pad+1)*4;
|
QString description = desc.toString();
|
||||||
pad=pad-description.length();
|
if(description.length()%4!=0)
|
||||||
QString padding;
|
{
|
||||||
padding.fill(' ',pad);
|
int pad=description.length()/4;
|
||||||
description.append(padding);
|
pad=(pad+1)*4;
|
||||||
|
pad=pad-description.length();
|
||||||
|
QString padding;
|
||||||
|
padding.fill(' ',pad);
|
||||||
|
description.append(padding);
|
||||||
|
}
|
||||||
|
array=description.toAscii();
|
||||||
|
|
||||||
|
} else if (desc.type() == QMetaType::QByteArray) {
|
||||||
|
array = desc.toByteArray();
|
||||||
}
|
}
|
||||||
if(!StartUpload(description.length(),OP_DFU::Descript,0))
|
|
||||||
|
if(!StartUpload(array.length(),OP_DFU::Descript,0))
|
||||||
return OP_DFU::abort;
|
return OP_DFU::abort;
|
||||||
QByteArray array=description.toAscii();
|
if(!UploadData(array.length(),array))
|
||||||
if(!UploadData(description.length(),array))
|
|
||||||
{
|
{
|
||||||
return OP_DFU::abort;
|
return OP_DFU::abort;
|
||||||
}
|
}
|
||||||
@ -301,6 +310,7 @@ OP_DFU::Status DFUObject::UploadDescription(QString description)
|
|||||||
}
|
}
|
||||||
OP_DFU::Status ret = StatusRequest();
|
OP_DFU::Status ret = StatusRequest();
|
||||||
|
|
||||||
|
|
||||||
if(debug)
|
if(debug)
|
||||||
qDebug() << "Upload description Status=" << StatusToString(ret);
|
qDebug() << "Upload description Status=" << StatusToString(ret);
|
||||||
return ret;
|
return ret;
|
||||||
@ -321,6 +331,15 @@ QString DFUObject::DownloadDescription(int const & numberOfChars)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QByteArray DFUObject::DownloadDescriptionAsBA(int const & numberOfChars)
|
||||||
|
{
|
||||||
|
|
||||||
|
QByteArray arr;
|
||||||
|
StartDownloadT(&arr, numberOfChars,OP_DFU::Descript);
|
||||||
|
return arr;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Starts a firmware download
|
Starts a firmware download
|
||||||
@param firmwareArray: pointer to the location where we should store the firmware
|
@param firmwareArray: pointer to the location where we should store the firmware
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include <QMetaType>
|
#include <QMetaType>
|
||||||
#include <QCryptographicHash>
|
#include <QCryptographicHash>
|
||||||
#include <QList>
|
#include <QList>
|
||||||
|
#include <QVariant>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include "delay.h"
|
#include "delay.h"
|
||||||
#include <qextserialport/src/qextserialport.h>
|
#include <qextserialport/src/qextserialport.h>
|
||||||
@ -124,12 +125,13 @@ namespace OP_DFU {
|
|||||||
bool ready() { return mready; }
|
bool ready() { return mready; }
|
||||||
|
|
||||||
// Upload (send to device) commands
|
// Upload (send to device) commands
|
||||||
OP_DFU::Status UploadDescription(QString description);
|
OP_DFU::Status UploadDescription(QVariant description);
|
||||||
bool UploadFirmware(const QString &sfile, const bool &verify,int device);
|
bool UploadFirmware(const QString &sfile, const bool &verify,int device);
|
||||||
|
|
||||||
// Download (get from device) commands:
|
// Download (get from device) commands:
|
||||||
// DownloadDescription is synchronous
|
// DownloadDescription is synchronous
|
||||||
QString DownloadDescription(int const & numberOfChars);
|
QString DownloadDescription(int const & numberOfChars);
|
||||||
|
QByteArray DownloadDescriptionAsBA(int const & numberOfChars);
|
||||||
// Asynchronous firmware download: initiates fw download,
|
// Asynchronous firmware download: initiates fw download,
|
||||||
// and a downloadFinished signal is emitted when download
|
// and a downloadFinished signal is emitted when download
|
||||||
// if finished:
|
// if finished:
|
||||||
|
Loading…
Reference in New Issue
Block a user