dRonin  adbada4
dRonin GCS
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Groups Pages
tl_dfu.cpp
Go to the documentation of this file.
1 
13 /*
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.
18  *
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
22  * for more details.
23  *
24  * You should have received a copy of the GNU General Public License along
25  * with this program; if not, see <http://www.gnu.org/licenses/>
26  *
27  * Additional note on redistribution: The copyright and license notices above
28  * must be maintained in each individual source file that is a derivative work
29  * of this source file; otherwise redistribution is prohibited.
30  */
31 
32 #include "tl_dfu.h"
33 
34 #include <QApplication>
35 #include <QThread>
36 
37 #define TL_DFU_DEBUG
38 #ifdef TL_DFU_DEBUG
39 #define TL_DFU_QXTLOG_DEBUG(...) qDebug() << __VA_ARGS__
40 #else // TL_DFU_DEBUG
41 #define TL_DFU_QXTLOG_DEBUG(...)
42 #endif // TL_DFU_DEBUG
43 
44 using namespace tl_dfu;
45 
47  : m_hidHandle(NULL)
48 {
49  qRegisterMetaType<tl_dfu::Status>("TL_DFU::Status");
50 }
51 
53 {
55 }
56 
60 bool DFUObject::EnterDFU()
61 {
62  bl_messages message;
63  message.flags_command = BL_MSG_ENTER_DFU;
64  message.v.enter_dfu.device_number = 0;
65  int result = SendData(message);
66  if (result < 1)
67  return false;
68  TL_DFU_QXTLOG_DEBUG(QString("EnterDFU:%0 bytes sent").arg(result));
69  return true;
70 }
71 
81 bool DFUObject::StartUpload(qint32 const &numberOfBytes, dfu_partition_label const &label,
82  quint32 crc)
83 {
84  messagePackets msg = CalculatePadding(numberOfBytes);
85  bl_messages message;
86  message.flags_command = BL_MSG_WRITE_START;
87  message.v.xfer_start.expected_crc = ntohl(crc);
88  message.v.xfer_start.packets_in_transfer = ntohl(msg.numberOfPackets);
89  message.v.xfer_start.words_in_last_packet = msg.lastPacketCount;
90  message.v.xfer_start.label = label;
91 
92  TL_DFU_QXTLOG_DEBUG(QString("Number of packets:%0 Size of last packet:%1")
93  .arg(msg.numberOfPackets)
94  .arg(msg.lastPacketCount));
95 
96  int result = SendData(message);
97  QEventLoop m_eventloop;
98  QTimer::singleShot(500, &m_eventloop, &QEventLoop::quit);
99  m_eventloop.exec();
100  TL_DFU_QXTLOG_DEBUG(QString("%0 bytes sent").arg(result));
101  if (result > 0)
102  return true;
103  return false;
104 }
105 
113 bool DFUObject::UploadData(qint32 const &numberOfBytes, QByteArray &data)
114 {
115  messagePackets msg = CalculatePadding(numberOfBytes);
116  TL_DFU_QXTLOG_DEBUG(QString("Start Uploading:%0 56 byte packets").arg(msg.numberOfPackets));
117  bl_messages message;
118  message.flags_command = BL_MSG_WRITE_CONT;
119  int packetsize;
120  float percentage;
121  int laspercentage = 0;
122  for (quint32 packetcount = 0; packetcount < msg.numberOfPackets; ++packetcount) {
123  percentage = (float)(packetcount + 1) / msg.numberOfPackets * 100;
124  if (laspercentage != (int)percentage)
125  emit operationProgress("", percentage);
126  laspercentage = (int)percentage;
127  if (packetcount == msg.numberOfPackets)
128  packetsize = msg.lastPacketCount;
129  else
130  packetsize = 14;
131  message.v.xfer_cont.current_packet_number = ntohl(packetcount);
132  char *pointer = data.data();
133  pointer = pointer + 4 * 14 * packetcount;
134  CopyWords(pointer, reinterpret_cast<char *>(message.v.xfer_cont.data), packetsize * 4);
135  int result = SendData(message);
136  if (result < 1)
137  return false;
138  }
139  return true;
140 }
141 
146 QByteArray DFUObject::DownloadDescriptionAsByteArray(int const &numberOfChars)
147 {
148  QByteArray array;
149  DownloadPartition(&array, numberOfChars, DFU_PARTITION_DESC);
150  return array;
151 }
152 
159 bool DFUObject::DownloadPartitionThreaded(QByteArray *firmwareArray, dfu_partition_label partition,
160  int size)
161 {
162  TL_DFU_QXTLOG_DEBUG(QString("DOWNLOAD PARTITION- SETTING DOWNLOAD CONFIG PARTITION=%1 SIZE:%2")
163  .arg(partition)
164  .arg(size));
165  if (isRunning())
166  return false;
167  threadJob.requestedOperation = ThreadJobStruc::Download;
168  threadJob.requestSize = size;
169  threadJob.requestTransferType = partition;
170  threadJob.requestStorage = firmwareArray;
171  start();
172  return true;
173 }
174 
180 {
181  bl_messages message;
182  message.flags_command = BL_MSG_WIPE_PARTITION;
183  message.v.wipe_partition.label = partition;
184  int result = SendData(message);
185  return (result > 0);
186 }
187 
192 {
193  bool downloadResult;
194  tl_dfu::Status uploadStatus;
195  switch (threadJob.requestedOperation) {
196  case ThreadJobStruc::Download:
197  TL_DFU_QXTLOG_DEBUG("DOWNLOAD THREAD STARTED");
198  downloadResult = DownloadPartition(threadJob.requestStorage, threadJob.requestSize,
199  threadJob.requestTransferType);
200  TL_DFU_QXTLOG_DEBUG("DOWNLOAD FINISHED");
201  emit downloadFinished(downloadResult);
202  break;
203  case ThreadJobStruc::Upload:
204  uploadStatus = UploadPartition(*threadJob.requestStorage, threadJob.requestTransferType);
205  TL_DFU_QXTLOG_DEBUG("UPLOAD FINISHED");
206  emit uploadFinished(uploadStatus);
207  break;
208  default:
209  break;
210  }
211  return;
212 }
213 
221 bool DFUObject::DownloadPartition(QByteArray *fw, qint32 const &numberOfBytes,
222  dfu_partition_label const &partition)
223 {
224  int numTries = 3;
225  quint32 x = 0;
226  quint32 offset = 0;
227 
228  EnterDFU();
229  emit operationProgress(
230  QString("Downloading %0 partition...").arg(partitionStringFromLabel(partition)), -1);
231  messagePackets msg = CalculatePadding(numberOfBytes);
232 
233 retry:
234  offset = x;
235 
236  bl_messages message;
237  message.flags_command = BL_MSG_READ_START;
238  message.v.xfer_start.packets_in_transfer = ntohl(msg.numberOfPackets + offset);
239  message.v.xfer_start.words_in_last_packet = msg.lastPacketCount;
240  message.v.xfer_start.label = partition;
241 
242  int result = SendData(message);
243  Q_UNUSED(result);
244 
245  TL_DFU_QXTLOG_DEBUG(QString("StartDownload %0 Last Packet Size %1 Bytes sent %2")
246  .arg(msg.numberOfPackets)
247  .arg(msg.lastPacketCount)
248  .arg(result));
249  float percentage;
250  int laspercentage = 0;
251 
252  // Now get those packets:
253  for (; x < msg.numberOfPackets; ++x) {
254  int size;
255  percentage = (float)(x + 1) / msg.numberOfPackets * 100;
256  if (laspercentage != (int)percentage)
257  operationProgress("", (int)percentage);
258  laspercentage = (int)percentage;
259 
260  result = ReceiveData(message);
261 
262  if (message.flags_command != BL_MSG_READ_CONT) {
263  qDebug()
264  << "Message different from BL_MSG_READ_CONT received while downloading partition";
265  return false;
266  }
267  if (ntohl(message.v.xfer_cont.current_packet_number) != (x - offset)) {
268  qDebug() << QString(
269  "Wrong packet number received while downloading partition- %0 vs %1")
270  .arg(ntohl(message.v.xfer_cont.current_packet_number))
271  .arg(x - offset);
272  if (ntohl(message.v.xfer_cont.current_packet_number) > (x - offset)) {
273  if ((numTries--) > 0) {
274  AbortOperation();
275 
276  // Drain out pending packets.
277  for (unsigned int i = 0; i < (msg.numberOfPackets + 10); i++) {
278  bl_messages dummy;
279  if (ReceiveData(dummy, 400) <= 0) {
280  break;
281  }
282  }
283 
284  StatusRequest();
285 
286  goto retry;
287  }
288  }
289  return false;
290  }
291  if (x == msg.numberOfPackets - 1)
292  size = msg.lastPacketCount * 4;
293  else
294  size = 14 * 4;
295  fw->append(reinterpret_cast<char *>(message.v.xfer_cont.data), size);
296 
297  numTries = 3;
298  }
299 
300  StatusRequest();
301 
302  TL_DFU_QXTLOG_DEBUG(QString("Download operation completed-- %1 bytes").arg(fw->size()));
303  return true;
304 }
305 
310 {
311  StatusRequest();
312 
313  bl_messages message;
314  message.flags_command = BL_MSG_RESET;
315  return SendData(message);
316 }
317 
321 int DFUObject::AbortOperation(void)
322 {
323  bl_messages message;
324  message.flags_command = BL_MSG_OP_ABORT;
325  return SendData(message);
326 }
327 
335 DFUObject::messagePackets DFUObject::CalculatePadding(quint32 numberOfBytes)
336 {
337  messagePackets msg;
338 
339  msg.numberOfPackets = numberOfBytes / 4 / 14;
340  msg.pad = (numberOfBytes - msg.numberOfPackets * 4 * 14) / 4;
341  if (msg.pad == 0) {
342  msg.lastPacketCount = 14;
343  } else {
344  ++msg.numberOfPackets;
345  msg.lastPacketCount = msg.pad;
346  }
347  return msg;
348 }
349 
353 int DFUObject::JumpToApp(bool safeboot)
354 {
355  bl_messages message;
356  message.flags_command = BL_MSG_JUMP_FW;
357 
358  // 0x5afe must have the bytes flipped for consistency
359  // with how the bootloader process this.
360  if (safeboot)
361  message.v.jump_fw.safe_word = ntohs((quint16)0x5afe);
362  else
363  message.v.jump_fw.safe_word = 0x0000;
364  // older f1 bootloader assumes these bytes are zero
365  message.v.jump_fw.unused2[0] = 0;
366  message.v.jump_fw.unused2[1] = 0;
367  return SendData(message);
368 }
369 
373 DFUObject::statusReport DFUObject::StatusRequest()
374 {
375  DFUObject::statusReport rep;
376 
377  bl_messages message;
378  message.flags_command = BL_MSG_STATUS_REQ;
379  int result = SendData(message);
380  Q_UNUSED(result);
381 
382  TL_DFU_QXTLOG_DEBUG(QString("StatusRequest:%0 bytes sent").arg(result));
383  result = ReceiveData(message);
384  TL_DFU_QXTLOG_DEBUG(QString("StatusRequest:%0 bytes received").arg(result));
385  if (message.flags_command == BL_MSG_STATUS_REP) {
386  TL_DFU_QXTLOG_DEBUG(QString("Status:%0").arg(message.v.status_rep.current_state));
387  rep.status = (tl_dfu::Status)message.v.status_rep.current_state;
388  rep.additional = (quint32)ntohl(message.v.status_rep.additional_state);
389  } else {
390  rep.status = tl_dfu::not_in_dfu;
391  rep.additional = 0;
392  }
393 
394  return rep;
395 }
396 
401 {
402  device currentDevice;
403  TL_DFU_QXTLOG_DEBUG("FINDDEVICES BEGIN");
404  bl_messages message;
405  message.flags_command = BL_MSG_CAP_REQ;
406  message.v.cap_req.device_number = 1;
407  TL_DFU_QXTLOG_DEBUG(
408  QString("FINDDEVICES SENDING CAPABILITIES REQUEST BUFFER_SIZE:%0").arg(BUF_LEN));
409  int result = SendData(message);
410  TL_DFU_QXTLOG_DEBUG(QString("FINDDEVICES CAPABILITIES REQUEST BYTES_SENT:%0").arg(result));
411  if (result < 1)
412  return currentDevice;
413 
414  result = ReceiveData(message);
415  TL_DFU_QXTLOG_DEBUG(QString("FINDDEVICES CAPABILITIES ANSWER BYTES_RECEIVED:%0").arg(result));
416  if ((result < 1) || (message.flags_command != BL_MSG_CAP_REP))
417  return currentDevice;
418 
419  currentDevice.BL_Version = message.v.cap_rep_specific.bl_version;
420  currentDevice.HW_Rev = message.v.cap_rep_specific.board_rev;
421  if (message.v.cap_rep_specific.cap_extension_magic == BL_CAP_EXTENSION_MAGIC)
422  currentDevice.CapExt = true;
423  else
424  currentDevice.CapExt = false;
425  currentDevice.SizeOfDesc = message.v.cap_rep_specific.desc_size;
426  currentDevice.ID = ntohs(message.v.cap_rep_specific.device_id);
427  message.v.cap_rep_specific.device_number = 1;
428  currentDevice.FW_CRC = ntohl(message.v.cap_rep_specific.fw_crc);
429  currentDevice.SizeOfCode = ntohl(message.v.cap_rep_specific.fw_size);
430  if (currentDevice.CapExt) {
431  for (int partition = 0; partition < 10; ++partition) {
432  currentDevice.PartitionSizes.append(
433  ntohl(message.v.cap_rep_specific.partition_sizes[partition]));
434  }
435  }
436  {
437  TL_DFU_QXTLOG_DEBUG(QString("Device ID=%0").arg(currentDevice.ID));
438  TL_DFU_QXTLOG_DEBUG(QString("Device SizeOfCode=%0").arg(currentDevice.SizeOfCode));
439  TL_DFU_QXTLOG_DEBUG(QString("Device SizeOfDesc=%0").arg(currentDevice.SizeOfDesc));
440  TL_DFU_QXTLOG_DEBUG(QString("BL Version=%0").arg(currentDevice.BL_Version));
441  TL_DFU_QXTLOG_DEBUG(QString("FW CRC=%0").arg(currentDevice.FW_CRC));
442  if (currentDevice.PartitionSizes.size() > 0) {
443  for (int partition = 0; partition < 10; ++partition)
444  TL_DFU_QXTLOG_DEBUG(QString("Partition %0 Size %1")
445  .arg(partition)
446  .arg(currentDevice.PartitionSizes.at(partition)));
447  } else {
448  TL_DFU_QXTLOG_DEBUG("No partition found, probably using old bootloader");
449  }
450  }
451  return currentDevice;
452 }
453 
460 {
461  int retries = 3;
462 
463  QEventLoop m_eventloop;
464 retry:
465  // If device was unplugged the previous coms are
466  // not closed. We must close it before opening
467  // a new one.
469 
470  QTimer::singleShot(200, &m_eventloop, &QEventLoop::quit);
471  m_eventloop.exec();
472  hid_init();
473  m_hidHandle = hid_open_path(port.path.toLatin1());
474  if (m_hidHandle) {
475  QTimer::singleShot(200, &m_eventloop, &QEventLoop::quit);
476  m_eventloop.exec();
477  AbortOperation();
478  if (!EnterDFU()) {
479  TL_DFU_QXTLOG_DEBUG(QString("Could not process enterDFU command"));
480  if ((retries--) > 0)
481  goto retry;
482 
484  return false;
485  }
486  if (StatusRequest().status != tl_dfu::DFUidle) {
487  TL_DFU_QXTLOG_DEBUG(QString("Status different that DFUidle after enterDFU command"));
488  if ((retries--) > 0)
489  goto retry;
490 
492  return false;
493  }
494 
495  return true;
496  } else {
497  TL_DFU_QXTLOG_DEBUG(QString("Could not open USB port"));
498 
499  if ((retries--) > 0)
500  goto retry;
501 
503  return false;
504  }
505 
506  return false;
507 }
508 
513 {
514  if (m_hidHandle) {
515  hid_close(m_hidHandle);
516 
517  m_hidHandle = NULL;
518  }
519 }
520 
524 bool DFUObject::EndOperation()
525 {
526  bl_messages message;
527  message.flags_command = BL_MSG_OP_END;
528  int result = SendData(message);
529  TL_DFU_QXTLOG_DEBUG(QString("%0 bytes sent").arg(result));
530  if (result > 0)
531  return true;
532  return false;
533 }
534 
542 bool DFUObject::UploadPartitionThreaded(QByteArray &sourceArray, dfu_partition_label partition,
543  int size)
544 {
545  if (isRunning())
546  return false;
547  threadJob.requestedOperation = ThreadJobStruc::Upload;
548  threadJob.requestTransferType = partition;
549  threadJob.requestStorage = &sourceArray;
550  threadJob.partition_size = size;
551  start();
552  return true;
553 }
554 
561 tl_dfu::Status DFUObject::UploadPartition(QByteArray &sourceArray, dfu_partition_label partition)
562 {
563  DFUObject::statusReport ret;
564 
565  // causes f1 bl to go into DFUidle state, required for StartUpload to succeed
566  StatusRequest();
567 
568  TL_DFU_QXTLOG_DEBUG("Starting Firmware Upload...");
569  emit operationProgress(QString("Starting upload"), -1);
570  TL_DFU_QXTLOG_DEBUG(QString("Bytes Loaded=%0").arg(sourceArray.length()));
571  if (sourceArray.length() % 4 != 0) {
572  int pad = sourceArray.length() / 4;
573  ++pad;
574  pad = pad * 4;
575  pad = pad - sourceArray.length();
576  sourceArray.append(QByteArray(pad, 255));
577  }
578 
579  if (threadJob.partition_size < (quint32)sourceArray.length()) {
580  TL_DFU_QXTLOG_DEBUG("ERROR array too big for device");
581  return tl_dfu::abort;
582  }
583 
584  quint32 crc = DFUObject::CRCFromQBArray(sourceArray, threadJob.partition_size);
585  TL_DFU_QXTLOG_DEBUG(QString("NEW FIRMWARE CRC=%0").arg(crc));
586 
587  if (!StartUpload(sourceArray.length(), partition, crc)) {
588  ret = StatusRequest();
589  qDebug() << QString("[tl_dfu] StartUpload failed, status: %1, additional: 0x%2")
590  .arg(StatusToString(ret.status))
591  .arg(ret.additional, 8, 16, QChar('0'));
592  return ret.status;
593  }
594  emit operationProgress(QString("Erasing, please wait..."), -1);
595 
596  TL_DFU_QXTLOG_DEBUG("Erasing memory");
597  if (StatusRequest().status == tl_dfu::abort) {
598  TL_DFU_QXTLOG_DEBUG("returning TL_DFU::abort");
599  return tl_dfu::abort;
600  }
601 
602  ret = StatusRequest();
603 
604  TL_DFU_QXTLOG_DEBUG(QString("Erase returned:%0").arg(StatusToString(ret.status)));
605 
606  if (ret.status != tl_dfu::uploading) {
607  qDebug() << QString(
608  "[tl_dfu] Couldn't start partition upload, status: %1, additional: 0x%2")
609  .arg(StatusToString(ret.status))
610  .arg(ret.additional, 8, 16, QChar('0'));
611  return ret.status;
612  }
613 
614  emit operationProgress(
615  QString(tr("Uploading %0 partition...")).arg(partitionStringFromLabel(partition)), -1);
616 
617  if (!UploadData(sourceArray.length(), sourceArray)) {
618  ret = StatusRequest();
619  qDebug() << QString("[tl_dfu] UploadData failed, status: %1, additional: 0x%2")
620  .arg(StatusToString(ret.status))
621  .arg(ret.additional, 8, 16, QChar('0'));
622 
623  return ret.status;
624  }
625  if (!EndOperation()) {
626  ret = StatusRequest();
627  qDebug() << QString("[tl_dfu] EndOperation failed, status: %1, additional: 0x%2")
628  .arg(StatusToString(ret.status))
629  .arg(ret.additional, 8, 16, QChar('0'));
630 
631  return ret.status;
632  }
633  ret = StatusRequest();
634  if (ret.status != tl_dfu::Last_operation_Success) {
635  qDebug() << QString("[tl_dfu] Upload failed, status: %1, additional: 0x%2")
636  .arg(StatusToString(ret.status))
637  .arg(ret.additional, 8, 16, QChar('0'));
638  return ret.status;
639  }
640 
641  TL_DFU_QXTLOG_DEBUG(QString("Status=%0").arg(StatusToString(ret.status)));
642  TL_DFU_QXTLOG_DEBUG("Firmware Uploading succeeded");
643  return ret.status;
644 }
645 
652 void DFUObject::CopyWords(char *source, char *destination, int count)
653 {
654  for (int x = 0; x < count; x = x + 4) {
655  *(destination + x) = source[x + 3];
656  *(destination + x + 1) = source[x + 2];
657  *(destination + x + 2) = source[x + 1];
658  *(destination + x + 3) = source[x + 0];
659  }
660 }
661 
666 quint32 DFUObject::CRC32WideFast(quint32 Crc, quint32 Size, quint32 *Buffer)
667 {
668  while (Size--) {
669  static const quint32 CrcTable[16] = { // Nibble lookup table for 0x04C11DB7 polynomial
670  0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9,
671  0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005,
672  0x2608EDB8, 0x22C9F00F, 0x2F8AD6D6, 0x2B4BCB61,
673  0x350C9B64, 0x31CD86D3, 0x3C8EA00A, 0x384FBDBD
674  };
675 
676  Crc = Crc ^ *(reinterpret_cast<quint32 *>(Buffer)); // Apply all 32-bits
677 
678  Buffer += 1;
679 
680  // Process 32-bits, 4 at a time, or 8 rounds
681 
682  Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // Assumes 32-bit reg, masking index to 4-bits
683  Crc = (Crc << 4) ^ CrcTable[Crc >> 28]; // 0x04C11DB7 Polynomial used in STM32
684  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
685  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
686  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
687  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
688  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
689  Crc = (Crc << 4) ^ CrcTable[Crc >> 28];
690  }
691  return (Crc);
692 }
693 
698 quint32 DFUObject::CRCFromQBArray(QByteArray array, quint32 Size)
699 {
700  // If array is not an 32-bit word aligned file then
701  // pad out the end to make it so like the firmware
702  // expects
703  if (array.length() % 4 != 0) {
704  int pad = array.length() / 4;
705  ++pad;
706  pad = pad * 4;
707  pad = pad - array.length();
708  array.append(QByteArray(pad, 255));
709  }
710 
711  // If the size is greater than the provided code then
712  // pad the end with 0xFF
713  if ((int)Size > array.length()) {
714  TL_DFU_QXTLOG_DEBUG("Padding");
715  quint32 pad = Size - array.length();
716  array.append(QByteArray(pad, 255));
717  }
718 
719  int maxSize = ((quint32)array.length() > Size) ? Size : array.length();
720 
721  // Large firmwares require defining super large arrays,
722  // so better to malloc them.
723  quint32 *t = reinterpret_cast<quint32 *>(malloc(Size));
724  for (int x = 0; x < maxSize / 4; x++) {
725  quint32 aux = 0;
726  aux = (char)array[x * 4 + 3] & 0xFF;
727  aux = aux << 8;
728  aux += (char)array[x * 4 + 2] & 0xFF;
729  aux = aux << 8;
730  aux += (char)array[x * 4 + 1] & 0xFF;
731  aux = aux << 8;
732  aux += (char)array[x * 4 + 0] & 0xFF;
733  t[x] = aux;
734  }
735  quint32 crc = DFUObject::CRC32WideFast(0xFFFFFFFF, Size / 4, reinterpret_cast<quint32 *>(t));
736  free(t);
737  return crc;
738 }
739 
745 int DFUObject::SendData(bl_messages data)
746 {
747  if (!m_hidHandle) {
748  return -1;
749  }
750 
751  char array[sizeof(bl_messages) + 1];
752  array[0] = 0x02;
753  memcpy(array + 1, &data, sizeof(bl_messages));
754 
755  int ret;
756 
757  for (int i = 0; i < 10; i++) {
758  ret = hid_write(m_hidHandle, reinterpret_cast<unsigned char *>(array), BUF_LEN);
759 
760  if (ret < 0) {
761  qDebug() << "hid_write returned error" << ret;
762  QThread::usleep(2000);
763  } else {
764  break;
765  }
766  }
767 
768  return ret;
769 }
770 
776 int DFUObject::ReceiveData(bl_messages &data, int timeoutMS)
777 {
778  if (!m_hidHandle) {
779  return -1;
780  }
781 
782  char array[sizeof(bl_messages) + 1];
783  int received =
784  hid_read_timeout(m_hidHandle, reinterpret_cast<unsigned char *>(array), BUF_LEN, timeoutMS);
785  memcpy(&data, array + 1, sizeof(bl_messages));
786  return received;
787 }
788 
795 {
796  switch (label) {
797  case DFU_PARTITION_BL:
798  return QString(tr("bootloader"));
799  break;
800  case DFU_PARTITION_DESC:
801  return QString(tr("description"));
802  break;
803  case DFU_PARTITION_FW:
804  return QString(tr("firmware"));
805  break;
807  return QString(tr("settings"));
808  break;
810  return QString(tr("autotune"));
811  break;
812  case DFU_PARTITION_LOG:
813  return QString(tr("log"));
814  break;
816  return QString(tr("extension"));
817  break;
818  default:
819  return QString::number(label);
820  break;
821  }
822 }
823 
829 QString DFUObject::StatusToString(tl_dfu::Status const &status)
830 {
831  switch (status) {
832  case DFUidle:
833  return "DFU Idle";
834  case uploading:
835  return "Uploading";
837  return "Wrong packet received";
838  case too_many_packets:
839  return "Too many packets received";
840  case too_few_packets:
841  return "Too few packets received";
843  return "Last operation success";
844  case downloading:
845  return "Downloading";
846  case idle:
847  return "Idle";
849  return "Last operation failed";
851  return "Outside Device Capabilities";
852  case CRC_Fail:
853  return "CRC check FAILED";
854  case failed_jump:
855  return "Jump to user FW failed";
856  case abort:
857  return "Abort";
858  case uploadingStarting:
859  return "Upload Starting";
860  default:
861  return "unknown";
862  }
863 }
bool DownloadPartitionThreaded(QByteArray *firmwareArray, dfu_partition_label partition, int size)
Definition: tl_dfu.cpp:159
device findCapabilities()
Definition: tl_dfu.cpp:400
quint8 BL_Version
Definition: tl_dfu.h:66
void CloseBootloaderComs()
Definition: tl_dfu.cpp:512
void operationProgress(QString status, int progress)
int SizeOfDesc
Definition: tl_dfu.h:67
quint32 SizeOfCode
Definition: tl_dfu.h:68
bool WipePartition(dfu_partition_label partition)
Definition: tl_dfu.cpp:179
QString partitionStringFromLabel(dfu_partition_label label)
Definition: tl_dfu.cpp:794
const char t[]
Definition: coreconstants.h:40
quint32 FW_CRC
Definition: tl_dfu.h:65
bool CapExt
Definition: tl_dfu.h:73
int JumpToApp(bool)
Definition: tl_dfu.cpp:353
for i
Definition: OPPlots.m:140
QByteArray DownloadDescriptionAsByteArray(int const &numberOfChars)
Definition: tl_dfu.cpp:146
DataFields data
bool UploadPartitionThreaded(QByteArray &sourceArray, dfu_partition_label partition, int size)
Definition: tl_dfu.cpp:542
dfu_partition_label
Definition: bl_messages.h:96
Status
Definition: tl_dfu.h:44
int HW_Rev
Definition: tl_dfu.h:72
bool OpenBootloaderComs(USBPortInfo port)
Definition: tl_dfu.cpp:459
int ResetDevice(void)
Definition: tl_dfu.cpp:309
void downloadFinished(bool)
static quint32 CRCFromQBArray(QByteArray array, quint32 Size)
Definition: tl_dfu.cpp:698
QVector< quint32 > PartitionSizes
Definition: tl_dfu.h:71
x
Definition: OPPlots.m:100
QString path
Opaque OS-specific path.
Definition: usbmonitor.h:48
void uploadFinished(tl_dfu::Status)
quint16 ID
Definition: tl_dfu.h:64
function crc