2 ******************************************************************************
5 * @author The LibrePilot Project, http://www.librepilot.org Copyright (C) 2017.
6 * The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
7 * @addtogroup GCSPlugins GCS Plugins
9 * @addtogroup Uploader Uploader Plugin
11 * @brief The uploader plugin
12 *****************************************************************************/
14 * This program is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU General Public License as published by
16 * the Free Software Foundation; either version 3 of the License, or
17 * (at your option) any later version.
19 * This program is distributed in the hope that it will be useful, but
20 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
21 * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
24 * You should have received a copy of the GNU General Public License along
25 * with this program; if not, write to the Free Software Foundation, Inc.,
26 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
31 #include "SSP/qsspt.h"
33 // #include <ophid/inc/ophid_hidapi.h>
34 // #include <ophid/inc/ophid_usbmon.h>
35 // #include <ophid/inc/ophid_usbsignal.h>
48 DFUObject::DFUObject(bool _debug
, bool _use_serial
, QString portname
) :
49 debug(_debug
), use_serial(_use_serial
), mready(true)
55 qRegisterMetaType
<DFU::Status
>("Status");
58 info
= new port(portname
, false);
59 info
->rxBuf
= sspRxBuf
;
60 info
->rxBufSize
= MAX_PACKET_DATA_LEN
;
61 info
->txBuf
= sspTxBuf
;
62 info
->txBufSize
= MAX_PACKET_DATA_LEN
;
64 info
->timeoutLen
= 100;
65 if (info
->status() != port::open
) {
66 cout
<< "Could not open serial port\n";
70 serialhandle
= new qsspt(info
, false /*debug*/);
73 while (!serialhandle
->ssp_Synchronise() && (count
< 10)) {
75 qDebug() << "SYNC failed, resending...";
81 qDebug() << "SYNC failed";
85 // transfer ownership of port to serialhandle thread
86 info
->moveToThread(serialhandle
);
87 connect(serialhandle
, SIGNAL(finished()), info
, SLOT(deleteLater()));
89 // start the serialhandle thread
90 serialhandle
->start();
93 hidHandle = new opHID_hidapi();
96 QEventLoop m_eventloop;
97 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
99 QList<USBPortInfo> devices;
100 devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
101 if (devices.length() == 1) {
102 if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
104 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
110 // Wait for the board to appear on the USB bus:
111 USBSignalFilter filter(0x20a0, -1, -1, USBMonitor::Bootloader);
112 connect(&filter, SIGNAL(deviceDiscovered()), &m_eventloop, SLOT(quit()));
113 for (int x = 0; x < 4; ++x) {
114 qDebug() << "DFU trying to detect bootloader:" << x;
117 QTimer::singleShot(10000, &m_eventloop, SLOT(quit()));
119 QTimer::singleShot(2000, &m_eventloop, SLOT(quit()));
122 devices = USBMonitor::instance()->availableDevices(0x20a0, -1, -1, USBMonitor::Bootloader);
123 qDebug() << "Devices length: " << devices.length();
124 if (devices.length() == 1) {
125 qDebug() << "Opening device";
126 if (hidHandle->open(1, devices.first().vendorID, devices.first().productID, 0, 0) == 1) {
127 QTimer::singleShot(200, &m_eventloop, SLOT(quit()));
129 qDebug() << "DFU detected after delay";
131 qDebug() << "Detected";
137 qDebug() << devices.length() << " device(s) detected, don't know what to do!";
146 DFUObject::~DFUObject()
160 bool DFUObject::SaveByteArrayToFile(QString
const & sfile
, const QByteArray
&array
)
164 if (!file
.open(QIODevice::WriteOnly
)) {
166 qDebug() << "Can't open file" << sfile
;
176 Tells the mainboard to enter DFU Mode.
178 bool DFUObject::enterDFU(int const &devNumber
)
182 buf
[0] = 0x02; // reportID
183 buf
[1] = DFU::EnterDFU
; // DFU Command
184 buf
[2] = 0; // DFU Count
185 buf
[3] = 0; // DFU Count
186 buf
[4] = 0; // DFU Count
187 buf
[5] = 0; // DFU Count
188 buf
[6] = devNumber
; // DFU Data0
189 buf
[7] = 1; // DFU Data1
190 buf
[8] = 1; // DFU Data2
191 buf
[9] = 1; // DFU Data3
193 int result
= sendData(buf
, BUF_LEN
);
198 qDebug() << "EnterDFU: " << result
<< " bytes sent";
204 Tells the board to get ready for an upload. It will in particular
205 erase the memory to make room for the data. You will have to query
206 its status to wait until erase is done before doing the actual upload.
208 bool DFUObject::StartUpload(qint32
const & numberOfBytes
, TransferTypes
const & type
, quint32 crc
)
211 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
212 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
215 lastPacketCount
= 14;
218 lastPacketCount
= pad
;
221 buf
[0] = 0x02; // reportID
222 buf
[1] = setStartBit(DFU::Upload
); // DFU Command
223 buf
[2] = numberOfPackets
>> 24; // DFU Count
224 buf
[3] = numberOfPackets
>> 16; // DFU Count
225 buf
[4] = numberOfPackets
>> 8; // DFU Count
226 buf
[5] = numberOfPackets
; // DFU Count
227 buf
[6] = (int)type
; // DFU Data0
228 buf
[7] = lastPacketCount
; // DFU Data1
234 qDebug() << "Number of packets:" << numberOfPackets
<< " Size of last packet:" << lastPacketCount
;
237 int result
= sendData(buf
, BUF_LEN
);
238 QThread::msleep(1000);
241 qDebug() << result
<< " bytes sent";
250 Does the actual data upload to the board. Needs to be called once the
251 board is ready to accept data following a StartUpload command, and it is erased.
253 bool DFUObject::UploadData(qint32
const & numberOfBytes
, QByteArray
& data
)
256 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
257 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
260 lastPacketCount
= 14;
263 lastPacketCount
= pad
;
266 qDebug() << "Start Uploading:" << numberOfPackets
<< "4Bytes";
269 buf
[0] = 0x02; // reportID
270 buf
[1] = DFU::Upload
; // DFU Command
273 int laspercentage
= 0;
274 for (qint32 packetcount
= 0; packetcount
< numberOfPackets
; ++packetcount
) {
275 percentage
= (float)(packetcount
+ 1) / numberOfPackets
* 100;
276 if (laspercentage
!= (int)percentage
) {
277 printProgBar((int)percentage
, "UPLOADING");
279 laspercentage
= (int)percentage
;
280 if (packetcount
== numberOfPackets
) {
281 packetsize
= lastPacketCount
;
285 // qDebug()<<packetcount;
286 buf
[2] = packetcount
>> 24; // DFU Count
287 buf
[3] = packetcount
>> 16; // DFU Count
288 buf
[4] = packetcount
>> 8; // DFU Count
289 buf
[5] = packetcount
; // DFU Count
290 char *pointer
= data
.data();
291 pointer
= pointer
+ 4 * 14 * packetcount
;
293 // 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];
295 CopyWords(pointer
, buf
+ 6, packetsize
* 4);
296 // for (int y=0;y<packetsize*4;++y) {
297 // qDebug()<<y<<":"<<(int)data[packetcount*14*4+y]<<"---"<<(int)buf[6+y];
299 // 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];
300 // QThread::msleep(send_delay);
302 if (StatusRequest() != DFU::uploading
) {
305 int result
= sendData(buf
, BUF_LEN
);
307 // qDebug() << "sent:" << result;
313 // qDebug() << "UPLOAD:" << "Data=" << (int)buf[6] << (int)buf[7] << (int)buf[8] << (int)buf[9] << ";" << result << " bytes sent";
320 Sends the firmware description to the device
322 DFU::Status
DFUObject::UploadDescription(QVariant desc
)
324 cout
<< "Starting uploading description\n";
326 emit
operationProgress("Uploading description");
329 if (desc
.type() == QVariant::String
) {
330 QString description
= desc
.toString();
331 if (description
.length() % 4 != 0) {
332 int pad
= description
.length() / 4;
334 pad
= pad
- description
.length();
336 padding
.fill(' ', pad
);
337 description
.append(padding
);
339 array
= description
.toLatin1();
340 } else if (desc
.type() == QVariant::ByteArray
) {
341 array
= desc
.toByteArray();
344 if (!StartUpload(array
.length(), DFU::Descript
, 0)) {
347 if (!UploadData(array
.length(), array
)) {
350 if (!EndOperation()) {
353 DFU::Status ret
= StatusRequest();
356 qDebug() << "Upload description Status=" << StatusToString(ret
);
363 Downloads the description string for the current device.
364 You have to call enterDFU before calling this function.
366 QString
DFUObject::DownloadDescription(int const & numberOfChars
)
370 StartDownloadT(&arr
, numberOfChars
, DFU::Descript
);
372 int index
= arr
.indexOf(255);
373 return QString((index
== -1) ? arr
: arr
.left(index
));
376 QByteArray
DFUObject::DownloadDescriptionAsBA(int const & numberOfChars
)
380 StartDownloadT(&arr
, numberOfChars
, DFU::Descript
);
386 Starts a firmware download
387 @param firmwareArray: pointer to the location where we should store the firmware
388 @package device: the device to use for the download
390 bool DFUObject::DownloadFirmware(QByteArray
*firmwareArray
, int device
)
395 requestedOperation
= DFU::Download
;
396 requestSize
= devices
[device
].SizeOfCode
;
397 requestTransferType
= DFU::FW
;
398 requestStorage
= firmwareArray
;
404 Runs the upload or download operations.
406 void DFUObject::run()
408 switch (requestedOperation
) {
410 StartDownloadT(requestStorage
, requestSize
, requestTransferType
);
411 emit(downloadFinished());
415 DFU::Status ret
= UploadFirmwareT(requestFilename
, requestVerify
, requestDevice
);
416 emit(uploadFinished(ret
));
425 Downloads a certain number of bytes from a certain location, and stores in an array whose
426 pointer is passed as an argument
428 bool DFUObject::StartDownloadT(QByteArray
*fw
, qint32
const & numberOfBytes
, TransferTypes
const & type
)
432 // First of all, work out the number of DFU packets we should ask for:
433 qint32 numberOfPackets
= numberOfBytes
/ 4 / 14;
434 int pad
= (numberOfBytes
- numberOfPackets
* 4 * 14) / 4;
437 lastPacketCount
= 14;
440 lastPacketCount
= pad
;
445 buf
[0] = 0x02; // reportID
446 buf
[1] = DFU::Download_Req
; // DFU Command
447 buf
[2] = numberOfPackets
>> 24; // DFU Count
448 buf
[3] = numberOfPackets
>> 16; // DFU Count
449 buf
[4] = numberOfPackets
>> 8; // DFU Count
450 buf
[5] = numberOfPackets
; // DFU Count
451 buf
[6] = (int)type
; // DFU Data0
452 buf
[7] = lastPacketCount
; // DFU Data1
453 buf
[8] = 1; // DFU Data2
454 buf
[9] = 1; // DFU Data3
456 int result
= sendData(buf
, BUF_LEN
);
458 qDebug() << "StartDownload:" << numberOfPackets
<< "packets" << " Last Packet Size=" << lastPacketCount
<< " " << result
<< " bytes sent";
461 int laspercentage
= 0;
463 // Now get those packets:
464 for (qint32 x
= 0; x
< numberOfPackets
; ++x
) {
466 percentage
= (float)(x
+ 1) / numberOfPackets
* 100;
467 if (laspercentage
!= (int)percentage
) {
468 printProgBar((int)percentage
, "DOWNLOADING");
470 laspercentage
= (int)percentage
;
472 result
= receiveData(buf
, BUF_LEN
);
474 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];
476 if (x
== numberOfPackets
- 1) {
477 size
= lastPacketCount
* 4;
481 fw
->append(buf
+ 6, size
);
491 int DFUObject::ResetDevice(void)
495 buf
[0] = 0x02; // reportID
496 buf
[1] = DFU::Reset
; // DFU Command
506 return sendData(buf
, BUF_LEN
);
507 // return hidHandle->send(0,buf, BUF_LEN, 500);
510 int DFUObject::AbortOperation(void)
514 buf
[0] = 0x02; // reportID
515 buf
[1] = DFU::Abort_Operation
; // DFU Command
525 return sendData(buf
, BUF_LEN
);
529 Starts the firmware (leaves bootloader and boots the main software)
531 int DFUObject::JumpToApp(bool safeboot
, bool erase
)
535 buf
[0] = 0x02; // reportID
536 buf
[1] = DFU::JumpFW
; // DFU Command
544 /* force system to safe boot mode (hwsettings == defaults) */
552 // force data flash clear
584 return sendData(buf
, BUF_LEN
);
587 DFU::Status
DFUObject::StatusRequest()
591 buf
[0] = 0x02; // reportID
592 buf
[1] = DFU::Status_Request
; // DFU Command
602 int result
= sendData(buf
, BUF_LEN
);
604 qDebug() << "StatusRequest: " << result
<< " bytes sent";
606 result
= receiveData(buf
, BUF_LEN
);
608 qDebug() << "StatusRequest: " << result
<< " bytes received";
610 if (buf
[1] == DFU::Status_Rep
) {
611 return (DFU::Status
)buf
[6];
618 Ask the bootloader for the list of devices available
620 bool DFUObject::findDevices()
624 buf
[0] = 0x02; // reportID
625 buf
[1] = DFU::Req_Capabilities
; // DFU Command
635 int result
= sendData(buf
, BUF_LEN
);
640 result
= receiveData(buf
, BUF_LEN
);
645 numberOfDevices
= buf
[7];
647 RWFlags
= RWFlags
<< 8 | buf
[9];
649 if (buf
[1] == DFU::Rep_Capabilities
) {
650 for (int x
= 0; x
< numberOfDevices
; ++x
) {
652 dev
.Readable
= (bool)(RWFlags
>> (x
* 2) & 1);
653 dev
.Writable
= (bool)(RWFlags
>> (x
* 2 + 1) & 1);
655 buf
[0] = 0x02; // reportID
656 buf
[1] = DFU::Req_Capabilities
; // DFU Command
665 sendData(buf
, BUF_LEN
);
666 receiveData(buf
, BUF_LEN
);
667 devices
[x
].ID
= buf
[14];
668 devices
[x
].ID
= devices
[x
].ID
<< 8 | (quint8
)buf
[15];
669 devices
[x
].BL_Version
= buf
[7];
670 devices
[x
].SizeOfDesc
= buf
[8];
673 aux
= (quint8
)buf
[10];
674 aux
= aux
<< 8 | (quint8
)buf
[11];
675 aux
= aux
<< 8 | (quint8
)buf
[12];
676 aux
= aux
<< 8 | (quint8
)buf
[13];
678 devices
[x
].FW_CRC
= aux
;
681 aux
= (quint8
)buf
[2];
682 aux
= aux
<< 8 | (quint8
)buf
[3];
683 aux
= aux
<< 8 | (quint8
)buf
[4];
684 aux
= aux
<< 8 | (quint8
)buf
[5];
685 devices
[x
].SizeOfCode
= aux
;
688 qDebug() << "Found " << numberOfDevices
<< " devices";
689 for (int x
= 0; x
< numberOfDevices
; ++x
) {
690 qDebug() << "Device #" << x
+ 1;
691 qDebug() << "Device ID=" << devices
[x
].ID
;
692 qDebug() << "Device Readable=" << devices
[x
].Readable
;
693 qDebug() << "Device Writable=" << devices
[x
].Writable
;
694 qDebug() << "Device SizeOfCode=" << devices
[x
].SizeOfCode
;
695 qDebug() << "Device SizeOfDesc=" << devices
[x
].SizeOfDesc
;
696 qDebug() << "BL Version=" << devices
[x
].BL_Version
;
697 qDebug() << "FW CRC=" << devices
[x
].FW_CRC
;
704 bool DFUObject::EndOperation()
708 buf
[0] = 0x02; // reportID
709 buf
[1] = DFU::END
; // DFU Command
719 int result
= sendData(buf
, BUF_LEN
);
721 qDebug() << result
<< " bytes sent";
730 Starts a firmware upload (asynchronous)
732 bool DFUObject::UploadFirmware(const QString
&sfile
, const bool &verify
, int device
)
737 requestedOperation
= DFU::Upload
;
738 requestFilename
= sfile
;
739 requestDevice
= device
;
740 requestVerify
= verify
;
745 DFU::Status
DFUObject::UploadFirmwareT(const QString
&sfile
, const bool &verify
, int device
)
750 qDebug() << "Starting Firmware Uploading...";
755 if (!file
.open(QIODevice::ReadOnly
)) {
757 qDebug() << "Failed to open file" << sfile
;
762 QByteArray arr
= file
.readAll();
765 qDebug() << "Bytes Loaded=" << arr
.length();
767 if (arr
.length() % 4 != 0) {
768 int pad
= arr
.length() / 4;
771 pad
= pad
- arr
.length();
772 arr
.append(QByteArray(pad
, 255));
774 if (devices
[device
].SizeOfCode
< (quint32
)arr
.length()) {
776 qDebug() << "ERROR file to big for device";
781 quint32 crc
= DFUObject::CRCFromQBArray(arr
, devices
[device
].SizeOfCode
);
783 qDebug() << "NEW FIRMWARE CRC=" << crc
;
786 if (!StartUpload(arr
.length(), DFU::FW
, crc
)) {
787 ret
= StatusRequest();
789 qDebug() << "StartUpload failed";
790 qDebug() << "StartUpload returned:" << StatusToString(ret
);
795 emit
operationProgress("Erasing, please wait...");
798 qDebug() << "Erasing memory";
800 if (StatusRequest() == DFU::abort
) {
804 // TODO: why is there a loop there? The "if" statement
805 // will cause a break or return anyway!!
806 for (int x
= 0; x
< 3; ++x
) {
807 ret
= StatusRequest();
809 qDebug() << "Erase returned: " << StatusToString(ret
);
811 if (ret
== DFU::uploading
) {
818 emit
operationProgress("Uploading firmware");
819 if (!UploadData(arr
.length(), arr
)) {
820 ret
= StatusRequest();
822 qDebug() << "Upload failed (upload data)";
823 qDebug() << "UploadData returned:" << StatusToString(ret
);
827 if (!EndOperation()) {
828 ret
= StatusRequest();
830 qDebug() << "Upload failed (end operation)";
831 qDebug() << "EndOperation returned:" << StatusToString(ret
);
835 ret
= StatusRequest();
836 if (ret
!= DFU::Last_operation_Success
) {
841 emit
operationProgress("Verifying firmware");
842 cout
<< "Starting code verification\n";
844 StartDownloadT(&arr2
, arr
.length(), DFU::FW
);
846 cout
<< "Verify:FAILED\n";
852 qDebug() << "Status=" << ret
;
854 cout
<< "Firmware Uploading succeeded\n";
858 DFU::Status
DFUObject::CompareFirmware(const QString
&sfile
, const CompareType
&type
, int device
)
860 cout
<< "Starting Firmware Compare...\n";
862 if (!file
.open(QIODevice::ReadOnly
)) {
864 qDebug() << "Cant open file";
868 QByteArray arr
= file
.readAll();
871 qDebug() << "Bytes Loaded=" << arr
.length();
873 if (arr
.length() % 4 != 0) {
874 int pad
= arr
.length() / 4;
877 pad
= pad
- arr
.length();
878 arr
.append(QByteArray(pad
, 255));
880 if (type
== DFU::crccompare
) {
881 quint32 crc
= DFUObject::CRCFromQBArray(arr
, devices
[device
].SizeOfCode
);
882 if (crc
== devices
[device
].FW_CRC
) {
883 cout
<< "Compare Successfull CRC MATCH!\n";
885 cout
<< "Compare failed CRC DONT MATCH!\n";
887 return StatusRequest();
890 StartDownloadT(&arr2
, arr
.length(), DFU::FW
);
892 cout
<< "Compare Successfull ALL Bytes MATCH!\n";
894 cout
<< "Compare failed Bytes DONT MATCH!\n";
896 return StatusRequest();
900 void DFUObject::CopyWords(char *source
, char *destination
, int count
)
902 for (int x
= 0; x
< count
; x
= x
+ 4) {
903 *(destination
+ x
) = source
[x
+ 3];
904 *(destination
+ x
+ 1) = source
[x
+ 2];
905 *(destination
+ x
+ 2) = source
[x
+ 1];
906 *(destination
+ x
+ 3) = source
[x
+ 0];
910 QString
DFUObject::StatusToString(DFU::Status
const & status
)
919 case wrong_packet_received
:
920 return "wrong_packet_received";
922 case too_many_packets
:
923 return "too_many_packets";
925 case too_few_packets
:
926 return "too_few_packets";
928 case Last_operation_Success
:
929 return "Last_operation_Success";
932 return "downloading";
937 case Last_operation_failed
:
938 return "Last_operation_failed";
940 case outsideDevCapabilities
:
941 return "outsideDevCapabilities";
944 return "CRC check FAILED";
947 return "Jmp to user FW failed";
952 case uploadingStarting
:
953 return "Uploading Starting";
961 Prints a progress bar with percentage & label during an operation.
963 Also outputs to stdout if we are in debug mode.
965 void DFUObject::printProgBar(int const & percent
, QString
const & label
)
967 emit(progressUpdated(percent
));
971 for (int i
= 0; i
< 50; i
++) {
972 if (i
< (percent
/ 2)) {
973 bar
.replace(i
, 1, "=");
974 } else if (i
== (percent
/ 2)) {
975 bar
.replace(i
, 1, ">");
977 bar
.replace(i
, 1, " ");
981 std::cout
<< "\r" << label
.toLatin1().data() << "[" << bar
<< "] ";
983 std::cout
<< percent
<< "% " << std::flush
;
990 quint32
DFUObject::CRC32WideFast(quint32 Crc
, quint32 Size
, quint32
*Buffer
)
992 // Size = Size >> 2; // /4 Size passed in as a byte count, assumed to be a multiple of 4
995 // Nibble lookup table for 0x04C11DB7 polynomial
996 static const quint32 CrcTable
[16] = {
997 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
998 0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61, 0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
1001 Crc
= Crc
^ *((quint32
*)Buffer
); // Apply all 32-bits
1005 // Process 32-bits, 4 at a time, or 8 rounds
1007 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28]; // Assumes 32-bit reg, masking index to 4-bits
1008 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28]; // 0x04C11DB7 Polynomial used in STM32
1009 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1010 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1011 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1012 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1013 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1014 Crc
= (Crc
<< 4) ^ CrcTable
[Crc
>> 28];
1023 quint32
DFUObject::CRCFromQBArray(QByteArray array
, quint32 Size
)
1025 quint32 pad
= Size
- array
.length();
1027 array
.append(QByteArray(pad
, 255));
1028 quint32 t
[Size
/ 4];
1029 for (int x
= 0; x
< array
.length() / 4; x
++) {
1031 aux
= (char)array
[x
* 4 + 3] & 0xFF;
1033 aux
+= (char)array
[x
* 4 + 2] & 0xFF;
1035 aux
+= (char)array
[x
* 4 + 1] & 0xFF;
1037 aux
+= (char)array
[x
* 4 + 0] & 0xFF;
1040 return DFUObject::CRC32WideFast(0xFFFFFFFF, Size
/ 4, (quint32
*)t
);
1044 Send data to the bootloader, either through the serial port
1045 of through the HID handle, depending on the mode we're using
1047 int DFUObject::sendData(void *data
, int size
)
1051 return hidHandle->send(0, data, size, 5000);
1056 if (serialhandle
->sendData((uint8_t *)data
+ 1, size
- 1)) {
1058 qDebug() << "packet sent" << "data0" << ((uint8_t *)data
+ 1)[0];
1063 qDebug() << "Serial send OVERRUN";
1069 Receive data from the bootloader, either through the serial port
1070 of through the HID handle, depending on the mode we're using
1072 int DFUObject::receiveData(void *data
, int size
)
1076 return hidHandle->receive(0, data, size, 10000);
1086 if ((x
= serialhandle
->read_Packet(((char *)data
) + 1) != -1) || time
.elapsed() > 10000) {
1087 QThread::msleep(10);
1088 if (time
.elapsed() > 10000) {
1089 qDebug() << "____timeout";
1092 qDebug() << "Error buffer overrun";
1100 #define BOARD_ID_MB 1
1101 #define BOARD_ID_INS 2
1102 #define BOARD_ID_PIP 3
1103 #define BOARD_ID_CC 4
1104 #define BOARD_ID_REVO 9
1105 #define BOARD_ID_SPARKY2 0x92
1108 Gets the type of board connected
1110 DFU::eBoardType
DFUObject::GetBoardType(int boardNum
)
1112 DFU::eBoardType brdType
= eBoardUnkwn
;
1114 // First of all, check what Board type we are talking to
1115 int board
= devices
[boardNum
].ID
;
1117 qDebug() << "Board model: " << board
;
1118 switch (board
>> 8) {
1119 case BOARD_ID_MB
: // Mainboard family
1120 brdType
= eBoardMainbrd
;
1122 case BOARD_ID_INS
: // Inertial Nav
1123 brdType
= eBoardINS
;
1125 case BOARD_ID_PIP
: // PIP RF Modem
1126 brdType
= eBoardPip
;
1128 case BOARD_ID_CC
: // CopterControl family
1131 case BOARD_ID_REVO
: // Revo board
1132 brdType
= eBoardRevo
;
1134 case BOARD_ID_SPARKY2
: // Sparky2 board
1135 brdType
= eBoardSparky2
;