2 ******************************************************************************
5 * @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
6 * @addtogroup GCSPlugins GCS Plugins
8 * @addtogroup Uploader Uploader Plugin
10 * @brief The uploader plugin
11 *****************************************************************************/
13 * This program is free software; you can redistribute it and/or modify
14 * it under the terms of the GNU General Public License as published by
15 * the Free Software Foundation; either version 3 of the License, or
16 * (at your option) any later version.
18 * This program is distributed in the hope that it will be useful, but
19 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
20 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
23 * You should have received a copy of the GNU General Public License along
24 * with this program; if not, write to the Free Software Foundation, Inc.,
25 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
30 #include <qwaitcondition.h>
32 #include <QtWidgets/QApplication>
34 using namespace OP_DFU
;
36 DFUObject::DFUObject(bool _debug
, bool _use_serial
, QString portname
) :
37 debug(_debug
), use_serial(_use_serial
), mready(true)
42 qRegisterMetaType
<OP_DFU::Status
>("Status");
45 info
= new port(portname
, false);
46 info
->rxBuf
= sspRxBuf
;
47 info
->rxBufSize
= MAX_PACKET_DATA_LEN
;
48 info
->txBuf
= sspTxBuf
;
49 info
->txBufSize
= MAX_PACKET_DATA_LEN
;
51 info
->timeoutLen
= 100;
52 if (info
->status() != port::open
) {
53 cout
<< "Could not open serial port\n";
57 serialhandle
= new qsspt(info
, false);
60 while ((serialhandle
->ssp_Synchronise() == false) && (count
< 10)) {
62 qDebug() << "SYNC failed, resending";
70 qDebug() << "SYNC Succeded";
71 serialhandle
->start();
74 QEventLoop m_eventloop;
75 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
77 QList<USBPortInfo> devices;
78 devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
79 if (devices.length() == 1) {
80 if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
82 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
88 // Wait for the board to appear on the USB bus:
89 USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader);
90 connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit()));
91 for (int x = 0; x < 4; ++x) {
92 qDebug() << "OP_DFU trying to detect bootloader:" << x;
95 QTimer::singleShot(10000, &m_eventloop, SLOT(quit()));
97 QTimer::singleShot(2000, &m_eventloop, SLOT(quit()));
100 devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
101 qDebug() << "Devices length: " << devices.length();
102 if (devices.length() == 1) {
103 qDebug() << "Opening device";
104 if (hidHandle.open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
105 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
107 qDebug() << "OP_DFU detected after delay";
109 qDebug() << "Detected";
115 qDebug() << devices.length() << " device(s) detected, don't know what to do!";
123 DFUObject::~DFUObject()
135 void DFUObject::sendReset(void)
137 qDebug() << "Requesting user mode reset";
138 uint8_t aa
[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x62, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; // 63
139 uint8_t ba
[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0xB9, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
140 uint8_t ca
[255] = { 0x02, 0x3E, 0x3C, 0x20, 0x75, 0x00, 0x20, 0x4F, 0x67, 0x34, 0x10, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
141 uint8_t bb
[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 0x8D, 0x19, 0x00, 0x00, 0x13 };
142 uint8_t ab
[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x47, 0x1B, 0x19, 0x00, 0x00, 0x76 };
143 uint8_t cb
[255] = { 0x02, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x66, 0x78, 0x1C, 0x00, 0x00, 0x25 };
146 hidHandle.send(0, aa, 64, 5000);
147 hidHandle.send(0, ab, 64, 5000);
149 hidHandle.send(0, ba, 64, 5000);
150 hidHandle.send(0, bb, 64, 5000);
152 hidHandle.send(0, ca, 64, 5000);
153 hidHandle.send(0, cb, 64, 5000);
160 memcpy(a
, aa
+ 2, 62);
161 memcpy(a
+ 62, ab
+ 2, 60);
162 memcpy(b
, ba
+ 2, 62);
163 memcpy(b
+ 62, bb
+ 2, 60);
164 memcpy(c
, ca
+ 2, 62);
165 memcpy(c
+ 62, cb
+ 2, 60);
166 for (int x
= 0; x
< 123; ++x
) {
167 info
->pfSerialWrite(a
[x
]);
170 for (int x
= 0; x
< 123; ++x
) {
171 info
->pfSerialWrite(b
[x
]);
174 for (int x
= 0; x
< 123; ++x
) {
175 info
->pfSerialWrite(c
[x
]);
180 bool DFUObject::SaveByteArrayToFile(QString
const & sfile
, const QByteArray
&array
)
184 if (!file
.open(QIODevice::WriteOnly
)) {
186 qDebug() << "Can't open file";
196 Tells the mainboard to enter DFU Mode.
198 bool DFUObject::enterDFU(int const &devNumber
)
202 buf
[0] = 0x02; // reportID
203 buf
[1] = OP_DFU::EnterDFU
; // DFU Command
204 buf
[2] = 0; // DFU Count
205 buf
[3] = 0; // DFU Count
206 buf
[4] = 0; // DFU Count
207 buf
[5] = 0; // DFU Count
208 buf
[6] = devNumber
; // DFU Data0
209 buf
[7] = 1; // DFU Data1
210 buf
[8] = 1; // DFU Data2
211 buf
[9] = 1; // DFU Data3
213 int result
= sendData(buf
, BUF_LEN
);
219 qDebug() << "EnterDFU: " << result
<< " bytes sent";
225 Tells the board to get ready for an upload. It will in particular
226 erase the memory to make room for the data. You will have to query
227 its status to wait until erase is done before doing the actual upload.
229 bool DFUObject::StartUpload(qint32
const & numberOfBytes
, TransferTypes
const & type
, quint32 crc
)
232 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
233 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
236 lastPacketCount
= 14;
239 lastPacketCount
= pad
;
242 buf
[0] = 0x02; // reportID
243 buf
[1] = setStartBit(OP_DFU::Upload
); // DFU Command
244 buf
[2] = numberOfPackets
>> 24; // DFU Count
245 buf
[3] = numberOfPackets
>> 16; // DFU Count
246 buf
[4] = numberOfPackets
>> 8; // DFU Count
247 buf
[5] = numberOfPackets
; // DFU Count
248 buf
[6] = (int)type
; // DFU Data0
249 buf
[7] = lastPacketCount
; // DFU Data1
255 qDebug() << "Number of packets:" << numberOfPackets
<< " Size of last packet:" << lastPacketCount
;
258 int result
= sendData(buf
, BUF_LEN
);
262 qDebug() << result
<< " bytes sent";
272 Does the actual data upload to the board. Needs to be called once the
273 board is ready to accept data following a StartUpload command, and it is erased.
275 bool DFUObject::UploadData(qint32
const & numberOfBytes
, QByteArray
& data
)
278 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
279 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
282 lastPacketCount
= 14;
285 lastPacketCount
= pad
;
288 qDebug() << "Start Uploading:" << numberOfPackets
<< "4Bytes";
291 buf
[0] = 0x02; // reportID
292 buf
[1] = OP_DFU::Upload
; // DFU Command
295 int laspercentage
= 0;
296 for (qint32 packetcount
= 0; packetcount
< numberOfPackets
; ++packetcount
) {
297 percentage
= (float)(packetcount
+ 1) / numberOfPackets
* 100;
298 if (laspercentage
!= (int)percentage
) {
299 printProgBar((int)percentage
, "UPLOADING");
301 laspercentage
= (int)percentage
;
302 if (packetcount
== numberOfPackets
) {
303 packetsize
= lastPacketCount
;
307 // qDebug()<<packetcount;
308 buf
[2] = packetcount
>> 24; // DFU Count
309 buf
[3] = packetcount
>> 16; // DFU Count
310 buf
[4] = packetcount
>> 8; // DFU Count
311 buf
[5] = packetcount
; // DFU Count
312 char *pointer
= data
.data();
313 pointer
= pointer
+ 4 * 14 * packetcount
;
315 // qDebug() << "Packet Number=" << packetcount << "Data0=" << (int)data[0] << " Data1=" << (int)data[1] << " Data0=" << (int)data[2] << " Data0=" << (int)data[3] << " buf6=" << (int)buf[6] << " buf7=" << (int)buf[7] << " buf8=" << (int)buf[8] << " buf9=" << (int)buf[9];
317 CopyWords(pointer
, buf
+ 6, packetsize
* 4);
318 // for (int y=0;y<packetsize*4;++y) {
319 // qDebug()<<y<<":"<<(int)data[packetcount*14*4+y]<<"---"<<(int)buf[6+y];
321 // qDebug()<<" Data0="<<(int)data[0]<<" Data0="<<(int)data[1]<<" Data0="<<(int)data[2]<<" Data0="<<(int)data[3]<<" buf6="<<(int)buf[6]<<" buf7="<<(int)buf[7]<<" buf8="<<(int)buf[8]<<" buf9="<<(int)buf[9];
322 // delay::msleep(send_delay);
324 if (StatusRequest() != OP_DFU::uploading
) {
327 int result
= sendData(buf
, BUF_LEN
);
329 // qDebug() << "sent:" << result;
335 // qDebug() << "UPLOAD:" << "Data=" << (int)buf[6] << (int)buf[7] << (int)buf[8] << (int)buf[9] << ";" << result << " bytes sent";
342 Sends the firmware description to the device
344 OP_DFU::Status
DFUObject::UploadDescription(QVariant desc
)
346 cout
<< "Starting uploading description\n";
349 if (desc
.type() == QVariant::String
) {
350 QString description
= desc
.toString();
351 if (description
.length() % 4 != 0) {
352 int pad
= description
.length() / 4;
354 pad
= pad
- description
.length();
356 padding
.fill(' ', pad
);
357 description
.append(padding
);
359 array
= description
.toLatin1();
360 } else if (desc
.type() == QVariant::ByteArray
) {
361 array
= desc
.toByteArray();
364 if (!StartUpload(array
.length(), OP_DFU::Descript
, 0)) {
365 return OP_DFU::abort
;
367 if (!UploadData(array
.length(), array
)) {
368 return OP_DFU::abort
;
370 if (!EndOperation()) {
371 return OP_DFU::abort
;
373 OP_DFU::Status ret
= StatusRequest();
377 qDebug() << "Upload description Status=" << StatusToString(ret
);
384 Downloads the description string for the current device.
385 You have to call enterDFU before calling this function.
387 QString
DFUObject::DownloadDescription(int const & numberOfChars
)
391 StartDownloadT(&arr
, numberOfChars
, OP_DFU::Descript
);
393 int index
= arr
.indexOf(255);
394 return QString((index
== -1) ? arr
: arr
.left(index
));
397 QByteArray
DFUObject::DownloadDescriptionAsBA(int const & numberOfChars
)
401 StartDownloadT(&arr
, numberOfChars
, OP_DFU::Descript
);
407 Starts a firmware download
408 @param firmwareArray: pointer to the location where we should store the firmware
409 @package device: the device to use for the download
411 bool DFUObject::DownloadFirmware(QByteArray
*firmwareArray
, int device
)
416 requestedOperation
= OP_DFU::Download
;
417 requestSize
= devices
[device
].SizeOfCode
;
418 requestTransferType
= OP_DFU::FW
;
419 requestStorage
= firmwareArray
;
426 Runs the upload or download operations.
428 void DFUObject::run()
430 switch (requestedOperation
) {
431 case OP_DFU::Download
:
432 StartDownloadT(requestStorage
, requestSize
, requestTransferType
);
433 emit(downloadFinished());
437 OP_DFU::Status ret
= UploadFirmwareT(requestFilename
, requestVerify
, requestDevice
);
438 emit(uploadFinished(ret
));
447 Downloads a certain number of bytes from a certain location, and stores in an array whose
448 pointer is passed as an argument
450 bool DFUObject::StartDownloadT(QByteArray
*fw
, qint32
const & numberOfBytes
, TransferTypes
const & type
)
454 // First of all, work out the number of DFU packets we should ask for:
455 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
456 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
459 lastPacketCount
= 14;
462 lastPacketCount
= pad
;
467 buf
[0] = 0x02; // reportID
468 buf
[1] = OP_DFU::Download_Req
; // DFU Command
469 buf
[2] = numberOfPackets
>> 24; // DFU Count
470 buf
[3] = numberOfPackets
>> 16; // DFU Count
471 buf
[4] = numberOfPackets
>> 8; // DFU Count
472 buf
[5] = numberOfPackets
; // DFU Count
473 buf
[6] = (int)type
; // DFU Data0
474 buf
[7] = lastPacketCount
; // DFU Data1
475 buf
[8] = 1; // DFU Data2
476 buf
[9] = 1; // DFU Data3
478 int result
= sendData(buf
, BUF_LEN
);
480 qDebug() << "StartDownload:" << numberOfPackets
<< "packets" << " Last Packet Size=" << lastPacketCount
<< " " << result
<< " bytes sent";
483 int laspercentage
= 0;
485 // Now get those packets:
486 for (qint32 x
= 0; x
< numberOfPackets
; ++x
) {
488 percentage
= (float)(x
+ 1) / numberOfPackets
* 100;
489 if (laspercentage
!= (int)percentage
) {
490 printProgBar((int)percentage
, "DOWNLOADING");
492 laspercentage
= (int)percentage
;
494 result
= receiveData(buf
, BUF_LEN
);
496 qDebug() << result
<< " bytes received" << " Count=" << x
<< "-" << (int)buf
[2] << ";" << (int)buf
[3] << ";" << (int)buf
[4] << ";" << (int)buf
[5] << " Data=" << (int)buf
[6] << ";" << (int)buf
[7] << ";" << (int)buf
[8] << ";" << (int)buf
[9];
498 if (x
== numberOfPackets
- 1) {
499 size
= lastPacketCount
* 4;
503 fw
->append(buf
+ 6, size
);
514 int DFUObject::ResetDevice(void)
518 buf
[0] = 0x02; // reportID
519 buf
[1] = OP_DFU::Reset
; // DFU Command
529 return sendData(buf
, BUF_LEN
);
530 // return hidHandle.send(0,buf, BUF_LEN, 500);
533 int DFUObject::AbortOperation(void)
537 buf
[0] = 0x02; // reportID
538 buf
[1] = OP_DFU::Abort_Operation
; // DFU Command
548 return sendData(buf
, BUF_LEN
);
551 Starts the firmware (leaves bootloader and boots the main software)
553 int DFUObject::JumpToApp(bool safeboot
, bool erase
)
557 buf
[0] = 0x02; // reportID
558 buf
[1] = OP_DFU::JumpFW
; // DFU Command
566 /* force system to safe boot mode (hwsettings == defaults) */
574 // force data flash clear
606 return sendData(buf
, BUF_LEN
);
609 OP_DFU::Status
DFUObject::StatusRequest()
613 buf
[0] = 0x02; // reportID
614 buf
[1] = OP_DFU::Status_Request
; // DFU Command
624 int result
= sendData(buf
, BUF_LEN
);
626 qDebug() << "StatusRequest: " << result
<< " bytes sent";
628 result
= receiveData(buf
, BUF_LEN
);
630 qDebug() << "StatusRequest: " << result
<< " bytes received";
632 if (buf
[1] == OP_DFU::Status_Rep
) {
633 return (OP_DFU::Status
)buf
[6];
635 return OP_DFU::abort
;
640 Ask the bootloader for the list of devices available
642 bool DFUObject::findDevices()
646 buf
[0] = 0x02; // reportID
647 buf
[1] = OP_DFU::Req_Capabilities
; // DFU Command
657 int result
= sendData(buf
, BUF_LEN
);
661 result
= receiveData(buf
, BUF_LEN
);
666 numberOfDevices
= buf
[7];
668 RWFlags
= RWFlags
<< 8 | buf
[9];
670 if (buf
[1] == OP_DFU::Rep_Capabilities
) {
671 for (int x
= 0; x
< numberOfDevices
; ++x
) {
673 dev
.Readable
= (bool)(RWFlags
>> (x
* 2) & 1);
674 dev
.Writable
= (bool)(RWFlags
>> (x
* 2 + 1) & 1);
676 buf
[0] = 0x02; // reportID
677 buf
[1] = OP_DFU::Req_Capabilities
; // DFU Command
686 sendData(buf
, BUF_LEN
);
687 receiveData(buf
, BUF_LEN
);
688 devices
[x
].ID
= buf
[14];
689 devices
[x
].ID
= devices
[x
].ID
<< 8 | (quint8
)buf
[15];
690 devices
[x
].BL_Version
= buf
[7];
691 devices
[x
].SizeOfDesc
= buf
[8];
694 aux
= (quint8
)buf
[10];
695 aux
= aux
<< 8 | (quint8
)buf
[11];
696 aux
= aux
<< 8 | (quint8
)buf
[12];
697 aux
= aux
<< 8 | (quint8
)buf
[13];
699 devices
[x
].FW_CRC
= aux
;
702 aux
= (quint8
)buf
[2];
703 aux
= aux
<< 8 | (quint8
)buf
[3];
704 aux
= aux
<< 8 | (quint8
)buf
[4];
705 aux
= aux
<< 8 | (quint8
)buf
[5];
706 devices
[x
].SizeOfCode
= aux
;
709 qDebug() << "Found " << numberOfDevices
<< " devices";
710 for (int x
= 0; x
< numberOfDevices
; ++x
) {
711 qDebug() << "Device #" << x
+ 1;
712 qDebug() << "Device ID=" << devices
[x
].ID
;
713 qDebug() << "Device Readable=" << devices
[x
].Readable
;
714 qDebug() << "Device Writable=" << devices
[x
].Writable
;
715 qDebug() << "Device SizeOfCode=" << devices
[x
].SizeOfCode
;
716 qDebug() << "Device SizeOfDesc=" << devices
[x
].SizeOfDesc
;
717 qDebug() << "BL Version=" << devices
[x
].BL_Version
;
718 qDebug() << "FW CRC=" << devices
[x
].FW_CRC
;
726 bool DFUObject::EndOperation()
730 buf
[0] = 0x02; // reportID
731 buf
[1] = OP_DFU::Op_END
; // DFU Command
741 int result
= sendData(buf
, BUF_LEN
);
743 qDebug() << result
<< " bytes sent";
754 Starts a firmware upload (asynchronous)
756 bool DFUObject::UploadFirmware(const QString
&sfile
, const bool &verify
, int device
)
761 requestedOperation
= OP_DFU::Upload
;
762 requestFilename
= sfile
;
763 requestDevice
= device
;
764 requestVerify
= verify
;
769 OP_DFU::Status
DFUObject::UploadFirmwareT(const QString
&sfile
, const bool &verify
, int device
)
774 qDebug() << "Starting Firmware Uploading...";
779 if (!file
.open(QIODevice::ReadOnly
)) {
781 qDebug() << "Cant open file";
783 return OP_DFU::abort
;
786 QByteArray arr
= file
.readAll();
789 qDebug() << "Bytes Loaded=" << arr
.length();
791 if (arr
.length() % 4 != 0) {
792 int pad
= arr
.length() / 4;
795 pad
= pad
- arr
.length();
796 arr
.append(QByteArray(pad
, 255));
798 if (devices
[device
].SizeOfCode
< (quint32
)arr
.length()) {
800 qDebug() << "ERROR file to big for device";
802 return OP_DFU::abort
;;
805 quint32 crc
= DFUObject::CRCFromQBArray(arr
, devices
[device
].SizeOfCode
);
807 qDebug() << "NEW FIRMWARE CRC=" << crc
;
810 if (!StartUpload(arr
.length(), OP_DFU::FW
, crc
)) {
811 ret
= StatusRequest();
813 qDebug() << "StartUpload failed";
814 qDebug() << "StartUpload returned:" << StatusToString(ret
);
819 emit
operationProgress(QString("Erasing, please wait..."));
822 qDebug() << "Erasing memory";
824 if (StatusRequest() == OP_DFU::abort
) {
825 return OP_DFU::abort
;
828 // TODO: why is there a loop there? The "if" statement
829 // will cause a break or return anyway!!
830 for (int x
= 0; x
< 3; ++x
) {
831 ret
= StatusRequest();
833 qDebug() << "Erase returned: " << StatusToString(ret
);
835 if (ret
== OP_DFU::uploading
) {
842 emit
operationProgress(QString("Uploading firmware"));
843 if (!UploadData(arr
.length(), arr
)) {
844 ret
= StatusRequest();
846 qDebug() << "Upload failed (upload data)";
847 qDebug() << "UploadData returned:" << StatusToString(ret
);
851 if (!EndOperation()) {
852 ret
= StatusRequest();
854 qDebug() << "Upload failed (end operation)";
855 qDebug() << "EndOperation returned:" << StatusToString(ret
);
859 ret
= StatusRequest();
860 if (ret
!= OP_DFU::Last_operation_Success
) {
865 emit
operationProgress(QString("Verifying firmware"));
866 cout
<< "Starting code verification\n";
868 StartDownloadT(&arr2
, arr
.length(), OP_DFU::FW
);
870 cout
<< "Verify:FAILED\n";
871 return OP_DFU::abort
;
876 qDebug() << "Status=" << ret
;
878 cout
<< "Firmware Uploading succeeded\n";
883 OP_DFU::Status
DFUObject::CompareFirmware(const QString
&sfile
, const CompareType
&type
, int device
)
885 cout
<< "Starting Firmware Compare...\n";
887 if (!file
.open(QIODevice::ReadOnly
)) {
889 qDebug() << "Cant open file";
891 return OP_DFU::abort
;
893 QByteArray arr
= file
.readAll();
896 qDebug() << "Bytes Loaded=" << arr
.length();
898 if (arr
.length() % 4 != 0) {
899 int pad
= arr
.length() / 4;
902 pad
= pad
- arr
.length();
903 arr
.append(QByteArray(pad
, 255));
905 if (type
== OP_DFU::crccompare
) {
906 quint32 crc
= DFUObject::CRCFromQBArray(arr
, devices
[device
].SizeOfCode
);
907 if (crc
== devices
[device
].FW_CRC
) {
908 cout
<< "Compare Successfull CRC MATCH!\n";
910 cout
<< "Compare failed CRC DONT MATCH!\n";
912 return StatusRequest();
915 StartDownloadT(&arr2
, arr
.length(), OP_DFU::FW
);
917 cout
<< "Compare Successfull ALL Bytes MATCH!\n";
919 cout
<< "Compare failed Bytes DONT MATCH!\n";
921 return StatusRequest();
925 void DFUObject::CopyWords(char *source
, char *destination
, int count
)
927 for (int x
= 0; x
< count
; x
= x
+ 4) {
928 *(destination
+ x
) = source
[x
+ 3];
929 *(destination
+ x
+ 1) = source
[x
+ 2];
930 *(destination
+ x
+ 2) = source
[x
+ 1];
931 *(destination
+ x
+ 3) = source
[x
+ 0];
934 QString
DFUObject::StatusToString(OP_DFU::Status
const & status
)
943 case wrong_packet_received
:
944 return "wrong_packet_received";
946 case too_many_packets
:
947 return "too_many_packets";
949 case too_few_packets
:
950 return "too_few_packets";
952 case Last_operation_Success
:
953 return "Last_operation_Success";
956 return "downloading";
961 case Last_operation_failed
:
962 return "Last_operation_failed";
964 case outsideDevCapabilities
:
965 return "outsideDevCapabilities";
968 return "CRC check FAILED";
971 return "Jmp to user FW failed";
976 case uploadingStarting
:
977 return "Uploading Starting";
985 Prints a progress bar with percentage & label during an operation.
987 Also outputs to stdout if we are in debug mode.
989 void DFUObject::printProgBar(int const & percent
, QString
const & label
)
993 emit(progressUpdated(percent
));
996 for (int i
= 0; i
< 50; i
++) {
997 if (i
< (percent
/ 2)) {
998 bar
.replace(i
, 1, "=");
999 } else if (i
== (percent
/ 2)) {
1000 bar
.replace(i
, 1, ">");
1002 bar
.replace(i
, 1, " ");
1006 std::cout
<< "\r" << label
.toLatin1().data() << "[" << bar
<< "] ";
1008 std::cout
<< percent
<< "% " << std::flush
;
1015 quint32
DFUObject::CRC32WideFast(quint32 Crc
, quint32 Size
, quint32
*Buffer
)
1017 // Size = Size >> 2; // /4 Size passed in as a byte count, assumed to be a multiple of 4
1020 static const quint32 CrcTable
[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
1021 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
1022 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
1025 Crc
= Crc
^ *((quint32
*)Buffer
); // Apply all 32-bits
1029 // Process 32-bits, 4 at a time, or 8 rounds
1031 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28]; // Assumes 32-bit reg, masking index to 4-bits
1032 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28]; // 0x04C11DB7 Polynomial used in STM32
1033 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1034 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1035 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1036 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1037 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1038 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1047 quint32
DFUObject::CRCFromQBArray(QByteArray array
, quint32 Size
)
1049 quint32 pad
= Size
- array
.length();
1051 array
.append(QByteArray(pad
, 255));
1052 quint32 t
[Size
/ 4];
1053 for (int x
= 0; x
< array
.length() / 4; x
++) {
1055 aux
= (char)array
[x
* 4 + 3] & 0xFF;
1057 aux
+= (char)array
[x
* 4 + 2] & 0xFF;
1059 aux
+= (char)array
[x
* 4 + 1] & 0xFF;
1061 aux
+= (char)array
[x
* 4 + 0] & 0xFF;
1064 return DFUObject::CRC32WideFast(0xFFFFFFFF, Size
/ 4, (quint32
*)t
);
1069 Send data to the bootloader, either through the serial port
1070 of through the HID handle, depending on the mode we're using
1072 int DFUObject::sendData(void *data
, int size
)
1074 /*if (!use_serial) {
1075 return hidHandle.send(0, data, size, 5000);
1079 if (serialhandle
->sendData((uint8_t *)data
+ 1, size
- 1)) {
1081 qDebug() << "packet sent" << "data0" << ((uint8_t *)data
+ 1)[0];
1086 qDebug() << "Serial send OVERRUN";
1093 Receive data from the bootloader, either through the serial port
1094 of through the HID handle, depending on the mode we're using
1096 int DFUObject::receiveData(void *data
, int size
)
1098 /*if (!use_serial) {
1099 return hidHandle.receive(0, data, size, 10000);
1108 if ((x
= serialhandle
->read_Packet(((char *)data
) + 1) != -1) || time
.elapsed() > 10000) {
1110 if (time
.elapsed() > 10000) {
1111 qDebug() << "____timeout";
1114 qDebug() << "Error buffer overrun";
1122 #define BOARD_ID_MB 1
1123 #define BOARD_ID_INS 2
1124 #define BOARD_ID_PIP 3
1125 #define BOARD_ID_CC 4
1126 #define BOARD_ID_REVO 9
1129 Gets the type of board connected
1131 OP_DFU::eBoardType
DFUObject::GetBoardType(int boardNum
)
1133 OP_DFU::eBoardType brdType
= eBoardUnkwn
;
1135 // First of all, check what Board type we are talking to
1136 int board
= devices
[boardNum
].ID
;
1138 qDebug() << "Board model: " << board
;
1139 switch (board
>> 8) {
1140 case BOARD_ID_MB
: // Mainboard family
1141 brdType
= eBoardMainbrd
;
1143 case BOARD_ID_INS
: // Inertial Nav
1144 brdType
= eBoardINS
;
1146 case BOARD_ID_PIP
: // PIP RF Modem
1147 brdType
= eBoardPip
;
1149 case BOARD_ID_CC
: // CopterControl family
1152 case BOARD_ID_REVO
: // Revo board
1153 brdType
= eBoardRevo
;