mirror of
https://github.com/radiomanV/TL866.git
synced 2026-03-11 10:47:13 +01:00
Update TL866 Updater
This commit is contained in:
@@ -1,63 +0,0 @@
|
||||
#-------------------------------------------------
|
||||
#
|
||||
# Project created by QtCreator 2014-01-28T20:16:00
|
||||
#
|
||||
#-------------------------------------------------
|
||||
|
||||
QT += core gui
|
||||
|
||||
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
|
||||
|
||||
equals(QT_MAJOR_VERSION, 5) {
|
||||
LIBS += -lQt5Concurrent
|
||||
}
|
||||
|
||||
TARGET = TL866_Updater
|
||||
TEMPLATE = app
|
||||
|
||||
|
||||
SOURCES += main.cpp\
|
||||
mainwindow.cpp \
|
||||
advdialog.cpp \
|
||||
firmware.cpp \
|
||||
editdialog.cpp \
|
||||
hexwriter.cpp \
|
||||
crc16.cpp \
|
||||
crc32.cpp
|
||||
|
||||
|
||||
HEADERS += mainwindow.h \
|
||||
advdialog.h \
|
||||
firmware.h \
|
||||
crc16.h \
|
||||
editdialog.h \
|
||||
hexwriter.h \
|
||||
tl866_global.h \
|
||||
crc32.h
|
||||
|
||||
FORMS += mainwindow.ui \
|
||||
editdialog.ui \
|
||||
advdialog.ui
|
||||
|
||||
RESOURCES += \
|
||||
resources.qrc
|
||||
|
||||
unix:!macx{
|
||||
HEADERS += usb_linux.h \
|
||||
notifier_linux.h
|
||||
SOURCES += usb_linux.cpp \
|
||||
notifier_linux.cpp
|
||||
LIBS += -ludev \
|
||||
-lusb-1.0
|
||||
}
|
||||
|
||||
win32:{
|
||||
HEADERS += usb_win.h \
|
||||
notifier_win.h
|
||||
SOURCES += usb_win.cpp \
|
||||
notifier_win.cpp
|
||||
LIBS += user32.lib \
|
||||
Setupapi.lib
|
||||
RC_FILE = win_resources.rc
|
||||
}
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
/* Advanced Dialog window class
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "advdialog.h"
|
||||
#include "ui_advdialog.h"
|
||||
#include "editdialog.h"
|
||||
#include "mainwindow.h"
|
||||
#include "tl866_global.h"
|
||||
|
||||
|
||||
AdvDialog::AdvDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::AdvDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
setFixedSize(size());
|
||||
}
|
||||
|
||||
AdvDialog::~AdvDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void AdvDialog::SetSerial(QString devcode, QString serial)
|
||||
{
|
||||
ui->txtDevcode->clear();
|
||||
ui->txtSerial->clear();
|
||||
ui->txtDevcode->setText(devcode);
|
||||
ui->txtSerial->setText(serial);
|
||||
device_code = devcode;
|
||||
serial_number = serial;
|
||||
}
|
||||
|
||||
void AdvDialog::SetInfo(QString info)
|
||||
{
|
||||
ui->txtInfo->clear();
|
||||
ui->txtInfo->setText(info);
|
||||
}
|
||||
|
||||
void AdvDialog::SetUi(bool cp, int type)
|
||||
{
|
||||
if(type == VERSION_TL866A)
|
||||
ui->radioA->setChecked(true);
|
||||
if(type == VERSION_TL866CS)
|
||||
ui->radioCS->setChecked(true);
|
||||
ui->optionCP->setChecked(cp);
|
||||
}
|
||||
|
||||
void AdvDialog::on_btnEdit_clicked()
|
||||
{
|
||||
EditDialog dlg(this);
|
||||
QString devcode =ui->txtDevcode->text();
|
||||
QString serial =ui->txtSerial->text();
|
||||
dlg.SetText(devcode,serial);
|
||||
if(dlg.exec()==QDialog::Accepted)
|
||||
{
|
||||
dlg.GetResult(&devcode, &serial);
|
||||
ui->txtDevcode->setText(devcode);
|
||||
ui->txtSerial->setText(serial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void AdvDialog::on_btnDefault_clicked()
|
||||
{
|
||||
emit set_default(ui->txtDevcode, ui->txtSerial);
|
||||
}
|
||||
|
||||
void AdvDialog::on_btnClone_clicked()
|
||||
{
|
||||
emit Refresh();
|
||||
ui->txtDevcode->setText(device_code);
|
||||
ui->txtSerial->setText(serial_number);
|
||||
}
|
||||
|
||||
void AdvDialog::on_btnWriteBootloader_clicked()
|
||||
{
|
||||
emit WriteBootloader(ui->radioA->isChecked() ? A_BOOTLOADER : CS_BOOTLOADER);
|
||||
}
|
||||
|
||||
void AdvDialog::on_btnWriteConfig_clicked()
|
||||
{
|
||||
emit WriteConfig(ui->optionCP->isChecked());
|
||||
}
|
||||
|
||||
void AdvDialog::on_btnWriteInfo_clicked()
|
||||
{
|
||||
emit WriteInfo(ui->txtDevcode->text(), ui->txtSerial->text());;
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
#ifndef ADVDIALOG_H
|
||||
#define ADVDIALOG_H
|
||||
|
||||
|
||||
#include <QLineEdit>
|
||||
#include <QDialog>
|
||||
#include "tl866_global.h"
|
||||
|
||||
namespace Ui {
|
||||
class AdvDialog;
|
||||
}
|
||||
|
||||
class AdvDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit AdvDialog(QWidget *parent = 0);
|
||||
~AdvDialog();
|
||||
void SetSerial(QString devcode, QString serial);
|
||||
void SetInfo(QString info);
|
||||
void SetUi(bool cp, int type);
|
||||
|
||||
|
||||
signals:
|
||||
void set_default(QLineEdit *devcode, QLineEdit *serial);
|
||||
void Refresh();
|
||||
void WriteBootloader(BootloaderType type);
|
||||
void WriteConfig(bool copy_protect);
|
||||
void WriteInfo(QString device_code, QString serial_number);
|
||||
|
||||
|
||||
private slots:
|
||||
void on_btnEdit_clicked();
|
||||
void on_btnDefault_clicked();
|
||||
void on_btnClone_clicked();
|
||||
void on_btnWriteBootloader_clicked();
|
||||
void on_btnWriteConfig_clicked();
|
||||
void on_btnWriteInfo_clicked();
|
||||
|
||||
private:
|
||||
Ui::AdvDialog *ui;
|
||||
QString device_code;
|
||||
QString serial_number;
|
||||
|
||||
};
|
||||
|
||||
#endif // DIALOG2_H
|
||||
@@ -1,444 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>AdvDialog</class>
|
||||
<widget class="QDialog" name="AdvDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>610</width>
|
||||
<height>322</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="btnOK">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>518</x>
|
||||
<y>288</y>
|
||||
<width>80</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="txtInfo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>12</x>
|
||||
<y>12</y>
|
||||
<width>585</width>
|
||||
<height>79</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTextEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>12</x>
|
||||
<y>97</y>
|
||||
<width>331</width>
|
||||
<height>67</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Bootloader</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="btnWriteBootloader">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>31</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="radioA">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>91</x>
|
||||
<y>34</y>
|
||||
<width>101</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>A Bootloader</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QRadioButton" name="radioCS">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>202</x>
|
||||
<y>34</y>
|
||||
<width>120</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>CS Bootloader</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>352</x>
|
||||
<y>97</y>
|
||||
<width>241</width>
|
||||
<height>67</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Copy protection</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="btnWriteConfig">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>16</x>
|
||||
<y>31</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QCheckBox" name="optionCP">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>98</x>
|
||||
<y>34</y>
|
||||
<width>138</width>
|
||||
<height>17</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Code protection bit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>12</x>
|
||||
<y>170</y>
|
||||
<width>591</width>
|
||||
<height>108</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Device Serial number</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>16</x>
|
||||
<y>27</y>
|
||||
<width>85</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device code</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>131</x>
|
||||
<y>27</y>
|
||||
<width>91</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Serial number</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>316</x>
|
||||
<y>42</y>
|
||||
<width>269</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnEdit">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnClone">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clone</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDefault">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnWriteInfo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>75</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtSerial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>97</x>
|
||||
<y>46</y>
|
||||
<width>202</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtDevcode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>10</x>
|
||||
<y>46</y>
|
||||
<width>81</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>25</x>
|
||||
<y>293</y>
|
||||
<width>381</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel{color: rgb(255, 0, 0)};</string>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Warning! You can brick your device here.</string>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>btnOK</sender>
|
||||
<signal>accepted()</signal>
|
||||
<receiver>AdvDialog</receiver>
|
||||
<slot>accept()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>248</x>
|
||||
<y>254</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>157</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,49 +0,0 @@
|
||||
/* Class CRC16
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "crc16.h"
|
||||
|
||||
CRC16::CRC16()
|
||||
{
|
||||
const ushort poly = 0xA001;
|
||||
for (ushort i = 0; i < 256; i++)
|
||||
{
|
||||
ushort temp = i;
|
||||
for (uchar j = 0; j < 8; j++)
|
||||
if ((temp & 1) == 1)
|
||||
temp = (ushort)((temp >> 1) ^ poly);
|
||||
else
|
||||
temp >>= 1;
|
||||
table[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ushort CRC16::crc16(const uchar *data, uint length, ushort initial)
|
||||
{
|
||||
while(length--)
|
||||
{
|
||||
initial=((initial>>8)^table[(initial^*data++)&0xFF]);
|
||||
}
|
||||
return initial;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef CRC16_H
|
||||
#define CRC16_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class CRC16
|
||||
{
|
||||
public:
|
||||
CRC16();
|
||||
ushort crc16(const uchar *data, unsigned int length, ushort initial);
|
||||
|
||||
private:
|
||||
ushort table[256];
|
||||
};
|
||||
|
||||
#endif // CRC16_H
|
||||
@@ -1,49 +0,0 @@
|
||||
/* Class CRC32
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "crc32.h"
|
||||
|
||||
CRC32::CRC32()
|
||||
{
|
||||
const uint poly=0xEDB88320;
|
||||
for (uint i = 0; i < 256; i++)
|
||||
{
|
||||
uint temp = i;
|
||||
for (uint j = 0; j < 8; j++)
|
||||
if ((temp & 1) == 1)
|
||||
temp = (temp >> 1) ^ poly;
|
||||
else
|
||||
temp >>= 1;
|
||||
table[i] = temp;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint CRC32::crc32(const uchar *data, uint length, uint initial)
|
||||
{
|
||||
while(length--)
|
||||
{
|
||||
initial = ((initial>>8)^table[(initial^*data++)&0xFF]);
|
||||
}
|
||||
return initial;
|
||||
}
|
||||
@@ -1,16 +0,0 @@
|
||||
#ifndef CRC32_H
|
||||
#define CRC32_H
|
||||
|
||||
#include <QtGlobal>
|
||||
|
||||
class CRC32
|
||||
{
|
||||
public:
|
||||
CRC32();
|
||||
uint crc32(const uchar *data, uint length, uint initial);
|
||||
|
||||
private:
|
||||
uint table[256];
|
||||
};
|
||||
|
||||
#endif // CRC32_H
|
||||
Binary file not shown.
@@ -1,92 +0,0 @@
|
||||
/* Edit Dialog window class
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "editdialog.h"
|
||||
#include "ui_editdialog.h"
|
||||
#include "firmware.h"
|
||||
#include <QMessageBox>
|
||||
|
||||
EditDialog::EditDialog(QWidget *parent) :
|
||||
QDialog(parent),
|
||||
ui(new Ui::EditDialog)
|
||||
{
|
||||
ui->setupUi(this);
|
||||
connect(ui->buttonBox,SIGNAL(accepted()),this,SLOT(okButton_clicked()));
|
||||
setFixedSize(size());
|
||||
}
|
||||
|
||||
EditDialog::~EditDialog()
|
||||
{
|
||||
delete ui;
|
||||
}
|
||||
|
||||
void EditDialog::GetResult(QString* devcode, QString* serial)
|
||||
{
|
||||
*devcode = ui->txtDevcode->text();
|
||||
*serial = ui->txtSerial->text();
|
||||
}
|
||||
|
||||
void EditDialog::SetText(QString devcode, QString serial)
|
||||
{
|
||||
ui->txtDevcode->setText(devcode);
|
||||
ui->txtSerial->setText(serial);
|
||||
}
|
||||
|
||||
void EditDialog::on_btnRndDev_clicked()
|
||||
{
|
||||
int i;
|
||||
QString s;
|
||||
for(i=0;i<8;i++)
|
||||
{
|
||||
s.append(QString::number( qrand() % 10));
|
||||
}
|
||||
ui->txtDevcode->setText(s);
|
||||
}
|
||||
|
||||
void EditDialog::on_btnRndSer_clicked()
|
||||
{
|
||||
int i;
|
||||
QString s;
|
||||
for(i=0;i<24;i++)
|
||||
{
|
||||
s.append(QString::number(qrand()%16,16).toUpper());
|
||||
}
|
||||
ui->txtSerial->setText(s);
|
||||
}
|
||||
|
||||
void EditDialog::okButton_clicked()
|
||||
{
|
||||
if(ui->txtDevcode->text()=="codedump" && ui->txtSerial->text()=="000000000000000000000000")
|
||||
{
|
||||
QMessageBox::warning(this, "TL866", "Please enter another device and serial code!\nThese two are reserved.");
|
||||
return;
|
||||
}
|
||||
if(Firmware::IsBadCrc((uchar*)ui->txtDevcode->text().toLatin1().data(), (uchar*)ui->txtSerial->text().toLatin1().data()))
|
||||
{
|
||||
QMessageBox::warning(this, "TL866", "Bad Device and serial code!\nPlease try again.");
|
||||
return;
|
||||
}
|
||||
accept();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef EDITDIALOG_H
|
||||
#define EDITDIALOG_H
|
||||
|
||||
#include <QDialog>
|
||||
|
||||
namespace Ui {
|
||||
class EditDialog;
|
||||
}
|
||||
|
||||
class EditDialog : public QDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit EditDialog(QWidget *parent = 0);
|
||||
~EditDialog();
|
||||
void GetResult(QString* devcode, QString* serial);
|
||||
void SetText(QString devcode, QString serial);
|
||||
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void on_btnRndDev_clicked();
|
||||
void on_btnRndSer_clicked();
|
||||
void okButton_clicked();
|
||||
|
||||
private:
|
||||
Ui::EditDialog *ui;
|
||||
};
|
||||
|
||||
#endif // EDITDIALOG_H
|
||||
@@ -1,185 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>EditDialog</class>
|
||||
<widget class="QDialog" name="EditDialog">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>471</width>
|
||||
<height>153</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<widget class="QDialogButtonBox" name="buttonBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>307</x>
|
||||
<y>117</y>
|
||||
<width>161</width>
|
||||
<height>32</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="standardButtons">
|
||||
<set>QDialogButtonBox::Cancel|QDialogButtonBox::Ok</set>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnRndDev">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>35</x>
|
||||
<y>63</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Random</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnRndSer">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>238</x>
|
||||
<y>63</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Random</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>41</x>
|
||||
<y>9</y>
|
||||
<width>85</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device code</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>237</x>
|
||||
<y>9</y>
|
||||
<width>91</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Serial number</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtDevcode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>12</x>
|
||||
<y>28</y>
|
||||
<width>117</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>8</number>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtSerial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>135</x>
|
||||
<y>28</y>
|
||||
<width>324</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>24</number>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<resources/>
|
||||
<connections>
|
||||
<connection>
|
||||
<sender>buttonBox</sender>
|
||||
<signal>rejected()</signal>
|
||||
<receiver>EditDialog</receiver>
|
||||
<slot>reject()</slot>
|
||||
<hints>
|
||||
<hint type="sourcelabel">
|
||||
<x>316</x>
|
||||
<y>260</y>
|
||||
</hint>
|
||||
<hint type="destinationlabel">
|
||||
<x>286</x>
|
||||
<y>274</y>
|
||||
</hint>
|
||||
</hints>
|
||||
</connection>
|
||||
</connections>
|
||||
</ui>
|
||||
@@ -1,319 +0,0 @@
|
||||
/* Class Firmware
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "firmware.h"
|
||||
#include "crc16.h"
|
||||
#include "crc32.h"
|
||||
#include <QFile>
|
||||
#include<QTime>
|
||||
#include <QDebug>
|
||||
|
||||
|
||||
Firmware::Firmware()
|
||||
{
|
||||
m_isValid=false;
|
||||
m_eraseA=0;
|
||||
m_eraseCS=0;
|
||||
qsrand(QDateTime::currentDateTime().toTime_t());
|
||||
|
||||
}
|
||||
|
||||
//Open update.dat file and decrypt it.
|
||||
int Firmware::open(const QString &filename)
|
||||
{
|
||||
m_isValid=false;
|
||||
QFile file(filename);
|
||||
if (!file.open(QFile::ReadOnly))
|
||||
return OpenError;
|
||||
|
||||
if (file.size()!=UPDATE_DAT_SIZE)
|
||||
{
|
||||
file.close();
|
||||
return FilesizeError;
|
||||
}
|
||||
|
||||
UpdateDat upd;
|
||||
if(file.read((char*)&upd,sizeof(upd))!=UPDATE_DAT_SIZE)
|
||||
{
|
||||
file.close();
|
||||
return OpenError;
|
||||
}
|
||||
file.close();
|
||||
m_eraseA = upd.A_erase;
|
||||
m_eraseCS = upd.CS_erase;
|
||||
m_version = upd.header[0];
|
||||
|
||||
unsigned int i;
|
||||
//Decrypt firmwares (first step).
|
||||
for(i=0;i<sizeof(m_firmwareA);i++)
|
||||
{
|
||||
//Try to understand these ;)
|
||||
m_firmwareA[i] = upd.A_Firmware[i] ^ upd.A_Xortable2[(i+upd.A_Index)&0x3FF] ^ upd.A_Xortable1[(i/80)&0xFF];
|
||||
m_firmwareCS[i] = upd.CS_Firmware[i] ^ upd.CS_Xortable2[(i+upd.CS_Index)&0x3FF] ^ upd.CS_Xortable1[(i/80)&0xFF];
|
||||
}
|
||||
CRC32 crc32;
|
||||
//Check if decryption is ok
|
||||
if((upd.A_CRC32!=~crc32.crc32(m_firmwareA,sizeof(m_firmwareA), 0xFFFFFFFF))||(upd.CS_CRC32!=~crc32.crc32(m_firmwareCS,sizeof(m_firmwareCS), 0xFFFFFFFF)))
|
||||
return CRCError;
|
||||
|
||||
m_isValid=true;
|
||||
return NoError;
|
||||
}
|
||||
|
||||
|
||||
//Get a magic number used in erase command
|
||||
unsigned char Firmware::GetEraseParammeter(int type)
|
||||
{
|
||||
return (type == VERSION_TL866A ? m_eraseA : m_eraseCS);
|
||||
}
|
||||
|
||||
unsigned char Firmware::GetFirmwareVersion()
|
||||
{
|
||||
return m_version;
|
||||
}
|
||||
|
||||
//Get the status of the firmware
|
||||
bool Firmware::isValid()
|
||||
{
|
||||
return m_isValid;
|
||||
}
|
||||
|
||||
|
||||
//Get encrypted firmware
|
||||
void Firmware::get_firmware(unsigned char *data_out, int type, int key)
|
||||
{
|
||||
if(type == key)
|
||||
{
|
||||
memcpy(data_out, type == VERSION_TL866A ? m_firmwareA : m_firmwareCS, ENCRYPTED_FIRMWARE_SIZE);
|
||||
return;
|
||||
}
|
||||
unsigned char data[UNENCRYPTED_FIRMWARE_SIZE];
|
||||
decrypt_firmware(data,key);
|
||||
encrypt_firmware(data,data_out,type);
|
||||
}
|
||||
|
||||
|
||||
//Encrypt firmware
|
||||
void Firmware::encrypt_firmware(const unsigned char *data_in, unsigned char *data_out, int key)
|
||||
{
|
||||
unsigned char xortable[256], data[80];
|
||||
int i,j,index=0x15;
|
||||
unsigned char* pEnc = key == A_KEY ? m_firmwareA : m_firmwareCS;
|
||||
|
||||
//extracting the xortable right from the encrypted firmware ;)
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
for(j=0;j<16;j++)
|
||||
{
|
||||
xortable[16 * i + j] = ~(pEnc[320 * i + j + XOR_TABLE_START]);//try to understand this ;)
|
||||
}
|
||||
}
|
||||
//encrypt firmware
|
||||
|
||||
for(i=0;i<UNENCRYPTED_FIRMWARE_SIZE;i+=BLOCK_SIZE-16)
|
||||
{
|
||||
memcpy(data,data_in+i,BLOCK_SIZE-16);
|
||||
encrypt_block(data,xortable,index);
|
||||
memcpy(data_out,data,BLOCK_SIZE);
|
||||
data_out+=BLOCK_SIZE;
|
||||
index+=4;
|
||||
index&=0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//decrypt firmware
|
||||
void Firmware::decrypt_firmware(unsigned char *data_out, int type)
|
||||
{
|
||||
unsigned char xortable[XOR_TABLE_SIZE], data[BLOCK_SIZE];
|
||||
int i,j,index=0x15;
|
||||
unsigned char* pEnc = type == VERSION_TL866A ? m_firmwareA : m_firmwareCS;
|
||||
|
||||
//extracting xortable right from the encrypted firmware ;)
|
||||
for(i=0;i<16;i++)
|
||||
{
|
||||
for(j=0;j<16;j++)
|
||||
{
|
||||
xortable[16 * i + j] = ~(pEnc[320 * i + j + XOR_TABLE_START]);
|
||||
}
|
||||
}
|
||||
//decrypt firmware
|
||||
|
||||
for(i=0;i<ENCRYPTED_FIRMWARE_SIZE;i+=BLOCK_SIZE)
|
||||
{
|
||||
memcpy(data,pEnc+i,BLOCK_SIZE);
|
||||
decrypt_block(data,xortable,index);
|
||||
memcpy(data_out,data,BLOCK_SIZE-16);
|
||||
data_out+=BLOCK_SIZE-16;
|
||||
index+=4;
|
||||
index&=0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//encrypt a block of 80 bytes
|
||||
void Firmware::encrypt_block(unsigned char *data, unsigned char *xortable, int index)
|
||||
{
|
||||
int i;
|
||||
unsigned char o1,o2;
|
||||
//First step, fill the last 16 bytes of data buffer with random generated values.
|
||||
for(i=0;i<16;i++){
|
||||
data[i+64]=(unsigned char) qrand() % 0x100;
|
||||
}
|
||||
|
||||
/* Second step, data scrambling. We swap the first byte with the last, the fourth from the beginning with the fourth from the end and so on.
|
||||
So, we have the following 10 swaps:(0-79),(4-75),(8-71),(12-67),(16-63),(20-59),(24-55),(28-51),(32-47),(36-43).
|
||||
*/
|
||||
for(i=0;i<BLOCK_SIZE/2;i+=4){
|
||||
o1=data[i];
|
||||
data[i]=data[BLOCK_SIZE-i-1];
|
||||
data[BLOCK_SIZE-i-1]=o1;
|
||||
}
|
||||
//Next step, left shifting whole array by 3 bits.
|
||||
for(i=0;i<BLOCK_SIZE-1;i++){
|
||||
o1=(data[i]<<3) & 0xF8;
|
||||
o2=data[i+1]>>5;
|
||||
data[i]=o2 | o1;
|
||||
}
|
||||
data[BLOCK_SIZE-1]<<=3;
|
||||
data[BLOCK_SIZE-1]&=0xF8;
|
||||
|
||||
//Last step, xoring each data value with a random number from xortable. Index is incremented modulo 256
|
||||
for(i=0;i<BLOCK_SIZE;i++){
|
||||
data[i]^=xortable[index++];
|
||||
index&=0xFF;
|
||||
}
|
||||
}
|
||||
|
||||
//decrypt a block of 80 bytes
|
||||
void Firmware::decrypt_block(unsigned char *data, unsigned char *xortable, int index)
|
||||
{
|
||||
int i;
|
||||
unsigned char o1,o2;
|
||||
//first step, xoring each element with a random value from xortable. Index is incremented modulo 256
|
||||
for(i=0;i<BLOCK_SIZE;i++){
|
||||
data[i]^=xortable[index++];
|
||||
index&=0xFF;
|
||||
}
|
||||
|
||||
//next step, right shifting whole array by 3 bits.
|
||||
for(i=0;i<BLOCK_SIZE-1;i++){
|
||||
o1=(data[BLOCK_SIZE-i-1]>>3) & 0x1F;
|
||||
o2=data[BLOCK_SIZE-i-2]<<5;
|
||||
data[BLOCK_SIZE-i-1]=o1 | o2;
|
||||
}
|
||||
data[0]>>=3;
|
||||
data[0]&=0x1F;
|
||||
|
||||
//Last step, descrambling data; put each element in the right position. At the end we have the decrypted data block ;)
|
||||
for(i=0;i<BLOCK_SIZE/2;i+=4){
|
||||
o1=data[i];
|
||||
data[i]=data[BLOCK_SIZE-i-1];
|
||||
data[BLOCK_SIZE-i-1]=o1;
|
||||
}
|
||||
}
|
||||
|
||||
//Encrypt 80 bytes data block containing dev code and serial
|
||||
void Firmware::encrypt_serial(unsigned char *key, const unsigned char *firmware)
|
||||
{
|
||||
int i,index=0x0A;
|
||||
unsigned char o1,o2;
|
||||
|
||||
CRC16 crc16;
|
||||
//compute the right crc16. The last two bytes in the info table is the crc16 in little-endian order and must be max. 0x1FFF, otherwise the decryption will be wrong.
|
||||
while(crc16.crc16(key,BLOCK_SIZE-2, 0) >0x1FFF)//a little brute-force method to match the required CRC;
|
||||
{
|
||||
for(i=32;i<BLOCK_SIZE-2;i++)
|
||||
{
|
||||
key[i] = (unsigned char) (qrand() % 0x100);
|
||||
}
|
||||
}
|
||||
ushort crc = crc16.crc16(key,BLOCK_SIZE-2, 0);
|
||||
key[BLOCK_SIZE-2]=(crc & 0xff);
|
||||
key[BLOCK_SIZE-1]=(crc >> 8);
|
||||
|
||||
|
||||
/*Data scrambling. We swap the first byte with the last, the fourth from the beginning with the fourth from the end and so on.
|
||||
So we have the following 10 swaps:(0-79),(4-75),(8-71),(12-67),(16-63),(20-59),(24-55),(28-51),(32-47),(36-43).
|
||||
*/
|
||||
for(i=0;i<BLOCK_SIZE/2;i+=4){
|
||||
o1=key[i];
|
||||
key[i]=key[BLOCK_SIZE-i-1];
|
||||
key[BLOCK_SIZE-i-1]=o1;
|
||||
}
|
||||
//Next step, left shift whole array by 3 bits .
|
||||
for(i=0;i<BLOCK_SIZE-1;i++){
|
||||
o1=(key[i]<<3) & 0xF8;
|
||||
o2=key[i+1]>>5;
|
||||
key[i]=o2 | o1;
|
||||
}
|
||||
key[BLOCK_SIZE-1]<<=3;
|
||||
key[BLOCK_SIZE-1]&=0xF8;
|
||||
|
||||
//Last step, xoring each info table value with a random number from xortable. The start index in this table is 0x0A. Index is incremented modulo 256
|
||||
for(i=0;i<BLOCK_SIZE;i++){
|
||||
key[i]^=firmware[XOR_TABLE_OFFSET+index];
|
||||
index++;
|
||||
index&=0xFF;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
//Decrypt 80 bytes data block containing dev code and serial
|
||||
void Firmware::decrypt_serial(unsigned char *key, const unsigned char *firmware)
|
||||
{
|
||||
int i,index=0x0A;
|
||||
unsigned char o1,o2;
|
||||
|
||||
//first step, xoring each element from table with a random value from xortable. Starting index is 0x0A. Index is incremented modulo 256
|
||||
for(i=0;i<BLOCK_SIZE;i++){
|
||||
key[i]^=firmware[XOR_TABLE_OFFSET+index];
|
||||
index++;
|
||||
index&=0xFF;
|
||||
}
|
||||
|
||||
/*next step, right shift whole array by 3 bits. Because anding with 0x1F, the last byte from info table must be always <0x20 in the encryption step, greater values will be trimmed at decryption step;
|
||||
this is why the crc16 must be 0x1FFF max., the last byte from info table is MSB of crc16.
|
||||
*/
|
||||
for(i=0;i<BLOCK_SIZE-1;i++){
|
||||
o1=(key[BLOCK_SIZE-i-1]>>3) & 0x1F;
|
||||
o2=key[BLOCK_SIZE-i-2]<<5;
|
||||
key[BLOCK_SIZE-i-1]=o1 | o2;
|
||||
}
|
||||
key[0]>>=3;
|
||||
key[0]&=0x1F;
|
||||
|
||||
//Last step, descrambling data; we put each element in the right position. At the end we have the decrypted serial and devcode ;)
|
||||
for(i=0;i<BLOCK_SIZE/2;i+=4){
|
||||
o1=key[i];
|
||||
key[i]=key[BLOCK_SIZE-i-1];
|
||||
key[BLOCK_SIZE-i-1]=o1;
|
||||
}
|
||||
}
|
||||
|
||||
bool Firmware::IsBadCrc(uchar *devcode, uchar *serial)
|
||||
{
|
||||
CRC32 crc32;
|
||||
unsigned int crc = crc32.crc32(serial,24,crc32.crc32(devcode, 8, 0xFFFFFFFF));
|
||||
return (crc == BAD_CRC);
|
||||
|
||||
}
|
||||
@@ -1,85 +0,0 @@
|
||||
#ifndef FIRMWARE_H
|
||||
#define FIRMWARE_H
|
||||
|
||||
#include <QString>
|
||||
#include "tl866_global.h"
|
||||
|
||||
#define UPDATE_DAT_SIZE 312348
|
||||
#define BLOCK_SIZE 80
|
||||
#define XOR_TABLE_SIZE 0x100
|
||||
#define XOR_TABLE_START 0x1EEDF
|
||||
#define XOR_TABLE_OFFSET 0x1FC00
|
||||
|
||||
|
||||
class Firmware
|
||||
{
|
||||
public:
|
||||
|
||||
Firmware();
|
||||
int open(const QString &filename);
|
||||
bool isValid();
|
||||
unsigned char GetEraseParammeter(int type);
|
||||
unsigned char GetFirmwareVersion();
|
||||
void decrypt_firmware(unsigned char *data_out, int type);
|
||||
void encrypt_firmware(const unsigned char *data_in, unsigned char *data_out, int key);
|
||||
void get_firmware(unsigned char *data_out, int type, int key);
|
||||
void encrypt_serial(unsigned char *key, const unsigned char *firmware);
|
||||
void decrypt_serial(unsigned char *key, const unsigned char *firmware);
|
||||
static bool IsBadCrc(uchar *devcode, uchar *serial);
|
||||
|
||||
|
||||
enum
|
||||
{
|
||||
NoError,
|
||||
OpenError,
|
||||
FilesizeError,
|
||||
CRCError,
|
||||
DecryptionError
|
||||
};
|
||||
|
||||
|
||||
enum ENCRYPTION_KEY
|
||||
{
|
||||
A_KEY = VERSION_TL866A,
|
||||
CS_KEY = VERSION_TL866CS
|
||||
};
|
||||
|
||||
private:
|
||||
|
||||
typedef struct {
|
||||
unsigned char header[4];//file header
|
||||
unsigned int A_CRC32;//4 bytes
|
||||
unsigned char pad1;
|
||||
unsigned char A_erase;
|
||||
unsigned char pad2;
|
||||
unsigned char pad3;
|
||||
unsigned int CS_CRC32;//4 bytes
|
||||
unsigned char pad4;
|
||||
unsigned char CS_erase;
|
||||
unsigned char pad5;
|
||||
unsigned char pad6;
|
||||
unsigned int A_Index;//index used in A firmware decryption
|
||||
unsigned char A_Xortable1[256];//First xortable used in A firmware decryption
|
||||
unsigned char A_Xortable2[1024];//Second xortable used in A firmware decryption
|
||||
unsigned int CS_Index;//index used in CS firmware decryption
|
||||
unsigned char CS_Xortable1[256];//First xortable used in CS firmware decryption
|
||||
unsigned char CS_Xortable2[1024];//Second xortable used in CS firmware decryption
|
||||
unsigned char A_Firmware[ENCRYPTED_FIRMWARE_SIZE];//Encrypted A firmware
|
||||
unsigned char CS_Firmware[ENCRYPTED_FIRMWARE_SIZE];//Encrypted CS firmware
|
||||
}UpdateDat;
|
||||
|
||||
unsigned int crc32(unsigned char *buffer, unsigned int length);
|
||||
void encrypt_block(unsigned char *data, unsigned char *xortable, int index);
|
||||
void decrypt_block(unsigned char *data, unsigned char *xortable, int index);
|
||||
|
||||
|
||||
unsigned int crc32Table[256];
|
||||
unsigned char m_firmwareA[ENCRYPTED_FIRMWARE_SIZE ];
|
||||
unsigned char m_firmwareCS[ENCRYPTED_FIRMWARE_SIZE ];
|
||||
unsigned char m_eraseA;
|
||||
unsigned char m_eraseCS;
|
||||
unsigned char m_version;
|
||||
bool m_isValid;
|
||||
};
|
||||
|
||||
#endif // FIRMWARE_H
|
||||
Binary file not shown.
Binary file not shown.
@@ -1,74 +0,0 @@
|
||||
/* Class HexWriter
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "hexwriter.h"
|
||||
|
||||
|
||||
void HexWriter::WriteHex(QTextStream &outStream, const uchar *data, uint size)
|
||||
{
|
||||
uchar temp[2];
|
||||
ushort segment=0;
|
||||
ushort address=0;
|
||||
|
||||
while(size>16)
|
||||
{
|
||||
if(!address)//address is zero, insert extended linear address record
|
||||
{
|
||||
temp[0]=(segment>>8);
|
||||
temp[1]=(segment&0xff);
|
||||
segment++;
|
||||
outStream << GetHexLine(temp,2,0,SEGMENT_RECORD) << endl;
|
||||
}
|
||||
outStream << GetHexLine(&data[(segment-1)*0x10000+address],16,address,DATA_RECORD) << endl;
|
||||
address+=16;
|
||||
size-=16;
|
||||
}
|
||||
outStream << GetHexLine(&data[(segment-1)*0x10000+address],size/2,address,DATA_RECORD) << endl;
|
||||
size/=2;
|
||||
address+=size;
|
||||
outStream << GetHexLine(&data[(segment-1)*0x10000+address],size,address,DATA_RECORD) << endl;
|
||||
outStream << GetHexLine(NULL,0,0,EOF_RECORD) << endl;
|
||||
}
|
||||
|
||||
|
||||
QString HexWriter::GetHexLine(const uchar *data, ushort size, ushort address ,uchar recordtype)
|
||||
{
|
||||
QString s=(QString(":%1%2%3").arg(size & 0xff, 2, 16, QChar('0')).arg(address, 4, 16, QChar('0')).arg(recordtype, 2, 16, QChar('0')).toUpper()).toLocal8Bit();
|
||||
ushort checksum=size;
|
||||
checksum += recordtype;
|
||||
checksum += (address >> 8);
|
||||
checksum += (address & 0xff);
|
||||
if(data!=NULL)
|
||||
{
|
||||
for(int i=0;i<size;i++)
|
||||
{
|
||||
s.append(QString("%1").arg(data[i], 2, 16, QChar('0')).toUpper());
|
||||
checksum += data[i];
|
||||
}
|
||||
}
|
||||
checksum &=0xff;
|
||||
checksum ^=0xff;
|
||||
checksum ++;
|
||||
checksum &=0xff;
|
||||
s.append(QString("%1").arg(checksum, 2, 16, QChar('0')).toUpper());
|
||||
return s;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
#ifndef HEXWRITER_H
|
||||
#define HEXWRITER_H
|
||||
#include <QTextStream>
|
||||
|
||||
class HexWriter
|
||||
{
|
||||
public:
|
||||
void WriteHex(QTextStream &outStream, const uchar *data, uint size);
|
||||
|
||||
private:
|
||||
QString GetHexLine(const uchar *data, ushort size, ushort address ,uchar recordtype);
|
||||
|
||||
enum RECORD_TYPE
|
||||
{
|
||||
DATA_RECORD = 0,
|
||||
SEGMENT_RECORD = 4,// Extended Linear Address Record
|
||||
EOF_RECORD = 1
|
||||
};
|
||||
};
|
||||
|
||||
#endif // HEXWRITER_H
|
||||
@@ -1,37 +0,0 @@
|
||||
/* Main.cpp
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include <QApplication>
|
||||
#include <QDebug>
|
||||
//#include <QStyleFactory>
|
||||
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
//qDebug()<<QStyleFactory::keys();
|
||||
QApplication a(argc, argv);
|
||||
MainWindow w;
|
||||
w.show();
|
||||
|
||||
return a.exec();
|
||||
}
|
||||
@@ -1,876 +0,0 @@
|
||||
/* Class MainWindow
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2014
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "mainwindow.h"
|
||||
#include "ui_mainwindow.h"
|
||||
#include "editdialog.h"
|
||||
#include "hexwriter.h"
|
||||
#include "crc16.h"
|
||||
#include "crc32.h"
|
||||
#include <QWidget>
|
||||
#include <QFileDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QResource>
|
||||
#include <QFuture>
|
||||
|
||||
|
||||
MainWindow::MainWindow(QWidget *parent) :
|
||||
QMainWindow(parent),
|
||||
ui(new Ui::MainWindow)
|
||||
{
|
||||
//setup UI
|
||||
ui->setupUi(this);
|
||||
setFixedSize(size());
|
||||
|
||||
//initialise object pointers
|
||||
advdlg = new AdvDialog(this);
|
||||
usbNotifier = new Notifier();
|
||||
usb_device = new USB();
|
||||
|
||||
//initialise used signals
|
||||
connect(usbNotifier,SIGNAL(deviceChange(bool)),this,SLOT(DeviceChanged(bool)));
|
||||
connect(this, SIGNAL(update_gui(QString, bool, bool)),this,SLOT(gui_updated(QString, bool, bool)));
|
||||
connect(this, SIGNAL(reflash_status(bool)), this, SLOT(reflash_finished(bool)));
|
||||
connect(this, SIGNAL(dump_status(QString)), this, SLOT(dump_finished(QString)));
|
||||
connect(this, SIGNAL(update_progress(int)),ui->progressBar,SLOT(setValue(int)));
|
||||
|
||||
connect(advdlg,SIGNAL(Refresh()),this,SLOT(Refresh()));
|
||||
connect(advdlg,SIGNAL(set_default(QLineEdit*,QLineEdit*)),this,SLOT(set_default(QLineEdit*,QLineEdit*)));
|
||||
connect(advdlg,SIGNAL(WriteBootloader(BootloaderType)),SLOT(WriteBootloader(BootloaderType)));
|
||||
connect(advdlg,SIGNAL(WriteConfig(bool)),this,SLOT(WriteConfig(bool)));
|
||||
connect(advdlg,SIGNAL(WriteInfo(QString,QString)),this,SLOT(WriteInfo(QString,QString)));
|
||||
|
||||
//set used properties
|
||||
this->setProperty("device_code", "");
|
||||
this->setProperty("serial_number", "");
|
||||
this->setProperty("device_type", 0);
|
||||
|
||||
//initialise main ui
|
||||
ui->btnAdvanced->setEnabled(false);
|
||||
ui->btnDump->setEnabled(false);
|
||||
leds_off();
|
||||
reset_flag=false;
|
||||
DeviceChanged(true);
|
||||
}
|
||||
|
||||
|
||||
MainWindow::~MainWindow()
|
||||
{
|
||||
if(watcher.isRunning())
|
||||
{
|
||||
watcher.cancel();
|
||||
watcher.waitForFinished();
|
||||
}
|
||||
delete usb_device;
|
||||
delete usbNotifier;
|
||||
delete advdlg;
|
||||
delete ui;
|
||||
}
|
||||
|
||||
|
||||
//Turn off all leds
|
||||
void MainWindow::leds_off()
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Background, QColor::fromRgb(0,64,0));
|
||||
ui->LedNorm->setPalette(pal);
|
||||
ui->LedBoot->setPalette(pal);
|
||||
pal.setColor(QPalette::Background, QColor::fromRgb(64,64,0));
|
||||
ui->LedErase->setPalette(pal);
|
||||
pal.setColor(QPalette::Background, QColor::fromRgb(64,0,0));
|
||||
ui->LedWrite->setPalette(pal);
|
||||
}
|
||||
|
||||
/* LEDs on/off toggle routines */
|
||||
void MainWindow::setNled(bool state)
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Background,state ? QColor::fromRgb(0,255,0) : QColor::fromRgb(0,64,0));
|
||||
ui->LedNorm->setPalette(pal);
|
||||
}
|
||||
|
||||
void MainWindow::setBled(bool state)
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Background,state ? QColor::fromRgb(0,255,0) : QColor::fromRgb(0,64,0));
|
||||
ui->LedBoot->setPalette(pal);
|
||||
}
|
||||
|
||||
void MainWindow::setEled(bool state)
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Background,state ? QColor::fromRgb(255,255,0) : QColor::fromRgb(64,64,0));
|
||||
ui->LedErase->setPalette(pal);
|
||||
}
|
||||
|
||||
void MainWindow::setWled(bool state)
|
||||
{
|
||||
QPalette pal;
|
||||
pal.setColor(QPalette::Background,state ? QColor::fromRgb(255,0,0) : QColor::fromRgb(64,0,0));
|
||||
ui->LedWrite->setPalette(pal);
|
||||
}
|
||||
|
||||
|
||||
//simple wait routine
|
||||
void MainWindow::wait_ms(unsigned long time)
|
||||
{
|
||||
QWaitCondition wc;
|
||||
QMutex mutex;
|
||||
QMutexLocker locker(&mutex);
|
||||
wc.wait(&mutex, time);
|
||||
}
|
||||
|
||||
|
||||
//browse for update.dat file
|
||||
void MainWindow::on_btnInput_clicked()
|
||||
{
|
||||
QString fileName = QFileDialog::getOpenFileName(this, "Update.dat" ,NULL, "dat files (*.dat);;All files (*.*)");
|
||||
if(fileName.isEmpty())
|
||||
return;
|
||||
|
||||
int ret=firmware.open(fileName);
|
||||
if(ret == Firmware::NoError)
|
||||
{
|
||||
ui->txtInput->setText(fileName);
|
||||
ui->lblVersion->setText(QString("[V:%1]").arg(firmware.GetFirmwareVersion()));
|
||||
return;
|
||||
}
|
||||
|
||||
switch(ret)
|
||||
{
|
||||
case Firmware::OpenError:
|
||||
QMessageBox::warning(this,"TL866",QString("Cannot read file %1").arg(fileName));
|
||||
break;
|
||||
case Firmware::FilesizeError:
|
||||
QMessageBox::warning(this,"TL866",QString("%1\n\nFilesize error!").arg(fileName));
|
||||
break;
|
||||
case Firmware::CRCError:
|
||||
QMessageBox::warning(this,"TL866",QString("%1\n\nData CRC error!").arg(fileName));
|
||||
break;
|
||||
case Firmware::DecryptionError:
|
||||
QMessageBox::warning(this,"TL866","Firmware decryption error!");
|
||||
break;
|
||||
}
|
||||
ui->lblVersion->clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
//show advanced dialog
|
||||
void MainWindow::on_btnAdvanced_clicked()
|
||||
{
|
||||
Refresh();
|
||||
advdlg->show();
|
||||
}
|
||||
|
||||
|
||||
//show edit device code and serial number dialog
|
||||
void MainWindow::on_btnEdit_clicked()
|
||||
{
|
||||
EditDialog dlg(this);
|
||||
QString devcode =ui->txtDevcode->text();
|
||||
QString serial =ui->txtSerial->text();
|
||||
dlg.SetText(devcode,serial);
|
||||
if(dlg.exec()==QDialog::Accepted)
|
||||
{
|
||||
dlg.GetResult(&devcode, &serial);
|
||||
ui->txtDevcode->setText(devcode);
|
||||
ui->txtSerial->setText(serial);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//set default device code and serial number
|
||||
void MainWindow::on_btnDefault_clicked()
|
||||
{
|
||||
set_default(ui->txtDevcode, ui->txtSerial);
|
||||
}
|
||||
|
||||
//public helper function to set default serial and device code
|
||||
void MainWindow::set_default(QLineEdit *devcode, QLineEdit *serial)
|
||||
{
|
||||
unsigned char key[BLOCK_SIZE];
|
||||
QByteArray res = get_resource(ui->radiofA->isChecked() ? A_FIRMWARE_RESOURCE : CS_FIRMWARE_RESOURCE, FLASH_SIZE);
|
||||
memcpy(key,res.data()+SERIAL_OFFSET,BLOCK_SIZE);
|
||||
firmware.decrypt_serial(key, (uchar*)res.data());
|
||||
devcode->setText(QString::fromLatin1((const char*)&key[0],8));
|
||||
serial->setText(QString::fromLatin1((const char*)&key[8],24));
|
||||
}
|
||||
|
||||
|
||||
//Read device info
|
||||
void MainWindow::Refresh()
|
||||
{
|
||||
reset_flag=false;
|
||||
DeviceChanged(true);
|
||||
}
|
||||
|
||||
|
||||
//clone serial and device code from connected device
|
||||
void MainWindow::on_btnClone_clicked()
|
||||
{
|
||||
Refresh();
|
||||
ui->txtDevcode->setText(this->property("device_code").toString());
|
||||
ui->txtSerial->setText(this->property("serial_number").toString());
|
||||
}
|
||||
|
||||
|
||||
//reset device button
|
||||
void MainWindow::on_btnReset_clicked()
|
||||
{
|
||||
|
||||
if(watcher.isRunning())
|
||||
return;
|
||||
if(!CheckDevices(this))
|
||||
return;
|
||||
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
reset();
|
||||
usb_device->close_device();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//reflash device button
|
||||
void MainWindow::on_btnReflash_clicked()
|
||||
{
|
||||
if(watcher.isRunning())
|
||||
return;
|
||||
|
||||
if(!CheckDevices(this))
|
||||
return;
|
||||
|
||||
if(!firmware.isValid())
|
||||
{
|
||||
QMessageBox::warning(this, "TL866", "No firmware file loaded!\nPlease load the update.dat file.");
|
||||
return;
|
||||
}
|
||||
|
||||
if(QMessageBox::warning(this, "TL866", "Warning! this operation will reflash the device.\nDo you want to continue?",
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::No)
|
||||
return;
|
||||
|
||||
int index = -1;
|
||||
if(ui->radioA->isChecked())
|
||||
index = FIRMWARE_A;
|
||||
if(ui->radioCS->isChecked())
|
||||
index = FIRMWARE_CS;
|
||||
if(ui->radioDump->isChecked())
|
||||
index = FIRMWARE_CUSTOM;
|
||||
if(index == -1)
|
||||
return;
|
||||
job_list.clear();
|
||||
job_list.append(REFLASH);
|
||||
watcher.setProperty("firmware_version", index);
|
||||
ui->progressBar->setMaximum(ENCRYPTED_FIRMWARE_SIZE/BLOCK_SIZE-1);
|
||||
watcher.setFuture(QtConcurrent::map(job_list, WorkerWrapper(this)));
|
||||
}
|
||||
|
||||
|
||||
//dump device button
|
||||
void MainWindow::on_btnDump_clicked()
|
||||
{
|
||||
if(!watcher.isRunning())
|
||||
{
|
||||
if(!firmware.isValid())
|
||||
{
|
||||
QMessageBox::warning(this, "TL866", "No firmware file loaded!\nPlease load the update.dat file.");
|
||||
return;
|
||||
}
|
||||
|
||||
QString fileName=QFileDialog::getSaveFileName(this,"Save firmware hex file",NULL,"hex files (*.hex);;All files (*.*)");
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
job_list.clear();
|
||||
job_list.append(DUMP);
|
||||
watcher.setProperty("hex_path", fileName);
|
||||
ui->progressBar->setMaximum(FLASH_SIZE - 1);
|
||||
watcher.setFuture(QtConcurrent::map(job_list, WorkerWrapper(this)));
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//save hex button
|
||||
void MainWindow::on_btnSave_clicked()
|
||||
{
|
||||
QString fileName=QFileDialog::getSaveFileName(this,"Save firmware hex file",NULL,"hex files (*.hex);;All files (*.*)");
|
||||
if(!fileName.isEmpty())
|
||||
{
|
||||
if(!fileName.endsWith(".hex", Qt::CaseInsensitive))
|
||||
fileName += ".hex";
|
||||
QFile file(fileName);
|
||||
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
{
|
||||
QMessageBox::critical(this,"TL866",QString("Error creating file %1\n%2.").arg(fileName).arg(file.errorString()));
|
||||
return;
|
||||
}
|
||||
QTextStream fileStream(&file);
|
||||
|
||||
QByteArray b =get_resource(ui->radiofA->isChecked() ? A_FIRMWARE_RESOURCE : CS_FIRMWARE_RESOURCE, FLASH_SIZE);
|
||||
|
||||
uchar *temp = new uchar[FLASH_SIZE];//128K byte array
|
||||
memcpy(temp,b.data(),FLASH_SIZE);//copy entire firmware to array
|
||||
|
||||
if(ui->optionBoot->isChecked())
|
||||
memset(temp+BOOTLOADER_SIZE, 0xFF, UNENCRYPTED_FIRMWARE_SIZE);//if the option bootloader only is selected then clear the main firmware area(0x1800-0x1FBFF)
|
||||
|
||||
uchar *key = new uchar[BLOCK_SIZE];//for holding serial and dev code
|
||||
firmware.decrypt_serial(key, temp);//decrypt the serial key from temp array to key array
|
||||
memset(key,' ',32);//add trailing spaces
|
||||
|
||||
memcpy(key, ui->txtDevcode->text().toLatin1().data(), ui->txtDevcode->text().size());//copy devcode to key array
|
||||
memcpy(key+8, ui->txtSerial->text().toLatin1().data(), ui->txtSerial->text().size());//copy serial to key array
|
||||
|
||||
firmware.encrypt_serial(key, temp);//encrypt the devcode and serial
|
||||
memcpy(temp + SERIAL_OFFSET ,key,BLOCK_SIZE);//copy the new devcode and serial to temp array
|
||||
|
||||
HexWriter *hexwriter = new HexWriter;
|
||||
hexwriter->WriteHex(fileStream,temp,FLASH_SIZE);//write temp array to fileStream in Intel hex format
|
||||
delete hexwriter;
|
||||
delete[] key;
|
||||
delete[] temp;
|
||||
file.close();//done!
|
||||
}
|
||||
}
|
||||
|
||||
//Helper function to get a binary resource
|
||||
QByteArray MainWindow::get_resource(QString resource_path, int size)
|
||||
{
|
||||
QResource res(resource_path);
|
||||
QByteArray ba;
|
||||
ba = (res.isCompressed() ? qUncompress(res.data(), size) : QByteArray((const char*)res.data(), size));
|
||||
return ba;
|
||||
}
|
||||
|
||||
|
||||
//Background worker dispatch routine. Notice that this function is executed in a separate thread.
|
||||
void MainWindow::DoWork(WorkerJob job)
|
||||
{
|
||||
switch(job)
|
||||
{
|
||||
case REFLASH:
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
bool success =reflash();
|
||||
usb_device->close_device();
|
||||
emit reflash_status(success);
|
||||
}
|
||||
break;
|
||||
|
||||
case DUMP:
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
QString result = dump();
|
||||
usb_device->close_device();
|
||||
emit dump_status(result);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//Send the Reset command to the TL866.
|
||||
void MainWindow::reset()
|
||||
{
|
||||
|
||||
uchar data[4] = {RESET_COMMAND, 0, 0, 0};
|
||||
reset_flag=true;
|
||||
usb_device->usb_write(data, 4);
|
||||
}
|
||||
|
||||
|
||||
//wait for device to reset
|
||||
bool MainWindow::wait_for_device()
|
||||
{
|
||||
int cnt = 50;//5 seconds
|
||||
while(usb_device->get_devices_count())//wait for device to leave
|
||||
{
|
||||
wait_ms(100);
|
||||
if(! --cnt)
|
||||
return false;//reset error
|
||||
}
|
||||
|
||||
cnt = 50;//5 seconds
|
||||
while(! usb_device->get_devices_count())//wait for device to arrive
|
||||
{
|
||||
wait_ms(100);
|
||||
if(! --cnt)
|
||||
return false;//reset error
|
||||
}
|
||||
return true;//device reset ok
|
||||
}
|
||||
|
||||
|
||||
//Reflash function. This routine is executed in a separate thread.
|
||||
bool MainWindow::reflash()
|
||||
{
|
||||
uchar buffer[BLOCK_SIZE+7];
|
||||
uchar data[ENCRYPTED_FIRMWARE_SIZE];
|
||||
|
||||
TL866_REPORT report;
|
||||
|
||||
//read the device to determine his satus
|
||||
memset((uchar*)&report,0, sizeof(TL866_REPORT));
|
||||
report.echo = REPORT_COMMAND;//0 anyway
|
||||
usb_device->usb_write((uchar *)&report, 5);
|
||||
usb_device->usb_read((uchar*)&report, sizeof(TL866_REPORT));
|
||||
if(report.device_status == NORMAL_MODE)//if the device is not in bootloader mode reset it.
|
||||
{
|
||||
reset();
|
||||
emit update_gui(QString("<resetting...>"), false, false);
|
||||
if(!wait_for_device())
|
||||
return false;//reset failed
|
||||
}
|
||||
wait_ms(500);
|
||||
|
||||
//read the device again to see the true device version as reported by the bootloader
|
||||
memset((uchar*)&report,0, sizeof(TL866_REPORT));
|
||||
report.echo = REPORT_COMMAND;//0 anyway
|
||||
usb_device->usb_write((uchar *)&report, 5);
|
||||
usb_device->usb_read((uchar*)&report, sizeof(TL866_REPORT));
|
||||
int device_version = report.device_version;
|
||||
|
||||
|
||||
//Erase device first
|
||||
memset(buffer,0,sizeof(buffer));
|
||||
buffer[0]=ERASE_COMMAND;
|
||||
buffer[7]=firmware.GetEraseParammeter(device_version);
|
||||
emit update_gui(QString("<erasing...>"), true, false);
|
||||
usb_device->usb_write(buffer, 20);
|
||||
usb_device->usb_read(data, 32);
|
||||
if(data[0] != ERASE_COMMAND)
|
||||
return false;//erase failed
|
||||
|
||||
//Write device.
|
||||
emit update_gui(QString("<erasing...>"), false, false);
|
||||
wait_ms(500);
|
||||
emit update_gui(QString("<writing...>"), false, true);
|
||||
|
||||
|
||||
//Get the encrypted firmware.
|
||||
switch(watcher.property("firmware_version").toInt())
|
||||
{
|
||||
case FIRMWARE_A:
|
||||
default:
|
||||
firmware.get_firmware(data, device_version, Firmware::A_KEY);
|
||||
break;
|
||||
case FIRMWARE_CS:
|
||||
firmware.get_firmware(data, device_version, Firmware::CS_KEY);
|
||||
break;
|
||||
case FIRMWARE_CUSTOM:
|
||||
QByteArray b = get_resource(DUMPER_RESOURCE, UNENCRYPTED_FIRMWARE_SIZE);
|
||||
firmware.encrypt_firmware((const uchar*)b.data(), data, device_version);
|
||||
}
|
||||
|
||||
|
||||
/* prepare data by adding 7 bytes header on each 80 bytes data block and send it over the usb.
|
||||
*
|
||||
* 7 bytes header+80 bytes data like this: | Command | lenght | address | data |
|
||||
* 2bytes 2bytes 3bytes 80bytes
|
||||
*
|
||||
*/
|
||||
|
||||
quint32 address = BOOTLOADER_SIZE;
|
||||
for (int i = 0; i<ENCRYPTED_FIRMWARE_SIZE; i += BLOCK_SIZE)
|
||||
{
|
||||
buffer[0] = WRITE_COMMAND;//command LSB
|
||||
buffer[1] = 0x00;//command MSB
|
||||
buffer[2] = BLOCK_SIZE;//Block size without header(LSB)
|
||||
buffer[3] = 0x00;//Block size MSB
|
||||
buffer[4] = address & 0xff;//24 bit address which will be written (3 bytes in little endian order)
|
||||
buffer[5] = (address & 0xff00)>>8;
|
||||
buffer[6] = (address & 0xff0000)>>16;
|
||||
memcpy(&buffer[7], &data[i], BLOCK_SIZE);
|
||||
|
||||
if (usb_device->usb_write(buffer, sizeof(buffer)) != sizeof(buffer))
|
||||
return false;//write failed
|
||||
address+=64;//next data block
|
||||
emit update_progress(i/BLOCK_SIZE);
|
||||
}
|
||||
|
||||
//Reset the device back in normal working mode
|
||||
emit update_gui(QString("<writing...>"), false, false);
|
||||
wait_ms(500);
|
||||
emit update_gui(QString("<resetting...>"), false, false);
|
||||
reset();
|
||||
if (! wait_for_device())
|
||||
return false;//reset failed
|
||||
|
||||
//read the device to determine his satus
|
||||
memset((uchar*)&report,0, sizeof(TL866_REPORT));
|
||||
report.echo = REPORT_COMMAND;//0 anyway
|
||||
usb_device->usb_write((uchar *)&report, 5);
|
||||
usb_device->usb_read((uchar*)&report, sizeof(TL866_REPORT));
|
||||
|
||||
if(report.device_status != NORMAL_MODE)//reflash failed
|
||||
return false;
|
||||
|
||||
return true;//reflash ok
|
||||
|
||||
}
|
||||
|
||||
//Dump function. This function is executed in separate thread.
|
||||
QString MainWindow::dump()
|
||||
{
|
||||
uchar temp[FLASH_SIZE];//128Kbyte buffer
|
||||
uchar w[5];
|
||||
QFile file(watcher.property("hex_path").toString());
|
||||
|
||||
if(!file.open(QIODevice::WriteOnly | QIODevice::Text))
|
||||
return file.errorString();
|
||||
|
||||
QTextStream fileStream(&file);
|
||||
|
||||
for(int i = 0; i < FLASH_SIZE; i += 64)
|
||||
{
|
||||
w[0] = DUMPER_READ_FLASH;
|
||||
w[1] = 64;//packet size
|
||||
w[2] = i & 0xff;//24bit address in little endian order
|
||||
w[3] = (i & 0xff00)>>8;
|
||||
w[4] = (i & 0xff0000)>>16;
|
||||
|
||||
usb_device->usb_write(w, sizeof(w));
|
||||
if(usb_device->usb_read(&temp[i],64) != 64)
|
||||
return QString("USB read error.");
|
||||
emit update_progress(i);
|
||||
}
|
||||
|
||||
firmware.decrypt_firmware(&temp[BOOTLOADER_SIZE], this->property("device_type").toInt());
|
||||
|
||||
HexWriter *hexwriter = new HexWriter;
|
||||
hexwriter->WriteHex(fileStream,temp,sizeof(temp));//write temp array to fileStream in Intel hex format.
|
||||
delete hexwriter;
|
||||
file.close();
|
||||
return QString("");
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Reflash finished SLOT
|
||||
void MainWindow::reflash_finished(bool success)
|
||||
{
|
||||
Refresh();
|
||||
if(success)
|
||||
QMessageBox::information(this, "TL866", "Reflash OK!");
|
||||
else
|
||||
QMessageBox::critical(this, "TL866", "Reflash Failed!");
|
||||
emit update_progress(0);
|
||||
}
|
||||
|
||||
|
||||
//Dump finished SLOT
|
||||
void MainWindow::dump_finished(QString result)
|
||||
{
|
||||
Refresh();
|
||||
if(result.isEmpty())
|
||||
QMessageBox::information(this, "TL866", "Firmware dump complete!");
|
||||
else
|
||||
QMessageBox::critical(this, "TL866", QString("Error creating dump.hex file\n%1.").arg(result));
|
||||
emit update_progress(0);
|
||||
}
|
||||
|
||||
|
||||
//Gui update SLOT
|
||||
void MainWindow::gui_updated(QString message, bool eraseLed, bool writeLed)
|
||||
{
|
||||
setEled(eraseLed);
|
||||
setWled(writeLed);
|
||||
QStringList list(ui->txtInfo->toPlainText().split("\n"));
|
||||
list.removeAt(1);
|
||||
list.insert(1,"Device status: Bootloader mode " + message);
|
||||
ui->txtInfo->clear();
|
||||
ui->txtInfo->append(list.join("\n"));
|
||||
}
|
||||
|
||||
//This procedure is called automatically by the usb device change. Call this function to refresh the info.
|
||||
void MainWindow::DeviceChanged(bool arrived)
|
||||
{
|
||||
if(!arrived && reset_flag)//ignore unplug event if the device was resetted by us.
|
||||
return;
|
||||
|
||||
reset_flag=false;
|
||||
ui->txtInfo->clear();
|
||||
int devtype = 0;
|
||||
int count=usb_device->get_devices_count();
|
||||
this->setWindowTitle(QString("TL866 firmware updater (%1 %2 connected)").arg(count).arg(count == 1 ? "device" : "devices"));
|
||||
|
||||
if(count)
|
||||
{
|
||||
TL866_REPORT report;
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
memset((uchar*)&report,0, sizeof(TL866_REPORT));
|
||||
report.echo = REPORT_COMMAND;//0 anyway
|
||||
usb_device->usb_write((uchar *)&report, 5);
|
||||
usb_device->usb_read((uchar*)&report, sizeof(TL866_REPORT));
|
||||
|
||||
switch(report.device_version)
|
||||
{
|
||||
case VERSION_TL866A:
|
||||
ui->txtInfo->append("Device version: TL866A");
|
||||
devtype = VERSION_TL866A;
|
||||
break;
|
||||
case VERSION_TL866CS:
|
||||
ui->txtInfo->append("Device version: TL866CS");
|
||||
devtype = VERSION_TL866CS;
|
||||
break;
|
||||
default:
|
||||
ui->txtInfo->append("Device version: Unknown");
|
||||
devtype = 0;
|
||||
}
|
||||
|
||||
|
||||
switch(report.device_status)
|
||||
{
|
||||
case NORMAL_MODE:
|
||||
setNled(true);
|
||||
setBled(false);
|
||||
ui->txtInfo->append("Device status: Normal working mode.");
|
||||
break;
|
||||
case BOOTLOADER_MODE:
|
||||
setNled(false);
|
||||
setBled(true);
|
||||
ui->txtInfo->append("Device status: Bootloader mode <waiting for update.>");
|
||||
break;
|
||||
default:
|
||||
setNled(false);
|
||||
setBled(false);
|
||||
ui->txtInfo->append("Device status: Unknown.");
|
||||
}
|
||||
QString s_devcode = (QString::fromLatin1((const char*)&report.device_code,8));
|
||||
QString s_serial = (QString::fromLatin1((const char*)&report.serial_number,24));
|
||||
bool isDumperActive = (s_devcode.toLower() == "codedump" && s_serial == "000000000000000000000000");
|
||||
|
||||
|
||||
if(isDumperActive)
|
||||
{
|
||||
|
||||
DUMPER_REPORT dumper_report;
|
||||
uchar b[] = {DUMPER_INFO};
|
||||
usb_device->usb_write(b, 1);
|
||||
usb_device->usb_read((uchar*)&dumper_report, sizeof(DUMPER_REPORT));
|
||||
devtype = dumper_report.bootloader_version;
|
||||
|
||||
s_devcode = (QString::fromLatin1((const char*)&dumper_report.device_code,8));
|
||||
s_serial = (QString::fromLatin1((const char*)&dumper_report.serial_number,24));
|
||||
|
||||
advdlg->SetSerial(s_devcode, s_serial);
|
||||
|
||||
QString info;
|
||||
info.append(QString("Device code: %1\n").arg(s_devcode.trimmed() + (Firmware::IsBadCrc((uchar*)s_devcode.toLatin1().data(), (uchar*)s_serial.toLatin1().data()) ? " (Bad device code)" : "")));
|
||||
info.append(QString("Serial number: %1\n").arg(s_serial.trimmed() + (Firmware::IsBadCrc((uchar*)s_devcode.toLatin1().data(), (uchar*)s_serial.toLatin1().data()) ? " (Bad serial code)" : "")));
|
||||
info.append(QString("Bootloader version: %1\n").arg((devtype == VERSION_TL866A) ? "A" : "CS"));
|
||||
info.append(QString("Code Protection bit: %1\n").arg(dumper_report.cp_bit ? "No" : "Yes"));
|
||||
|
||||
advdlg->SetInfo(info);
|
||||
advdlg->SetUi(dumper_report.cp_bit == 0, devtype);
|
||||
|
||||
ui->btnAdvanced->setEnabled(true);
|
||||
ui->btnDump->setEnabled(true);
|
||||
}
|
||||
else//dumper is not active
|
||||
{
|
||||
ui->btnAdvanced->setEnabled(false);
|
||||
ui->btnDump->setEnabled(false);
|
||||
advdlg->SetSerial("", "");
|
||||
advdlg->SetInfo("");
|
||||
advdlg->hide();
|
||||
}
|
||||
|
||||
ui->txtInfo->append("Device code: " + s_devcode.trimmed() + (Firmware::IsBadCrc((uchar*)s_devcode.toLatin1().data(), (uchar*)s_serial.toLatin1().data()) ? " (Bad device code)" : ""));
|
||||
ui->txtInfo->append("Serial number: " + s_serial.trimmed() + (Firmware::IsBadCrc((uchar*)s_devcode.toLatin1().data(), (uchar*)s_serial.toLatin1().data()) ? " (Bad serial code)" : ""));
|
||||
this->setProperty("device_code", s_devcode);
|
||||
this->setProperty("serial_number", s_serial);
|
||||
ui->txtInfo->append(isDumperActive ? "Firmware version: Firmware dumper" :
|
||||
report.device_status == NORMAL_MODE ? QString("Firmware version: %1.%2.%3")
|
||||
.arg(report.hardware_version)
|
||||
.arg(report.firmware_version_major)
|
||||
.arg(report.firmware_version_minor):
|
||||
"Firmware version: Bootloader");
|
||||
|
||||
if(!watcher.isRunning())
|
||||
usb_device->close_device();//do not close device if an upgrade is in progress.
|
||||
}
|
||||
else//error oppening device
|
||||
SetBlank();
|
||||
|
||||
}
|
||||
else//no device connected
|
||||
SetBlank();
|
||||
|
||||
this->setProperty("device_type", devtype);//save global property for later usage.
|
||||
}
|
||||
|
||||
|
||||
//Helper function
|
||||
void MainWindow::SetBlank()
|
||||
{
|
||||
leds_off();
|
||||
ui->btnAdvanced->setEnabled(false);
|
||||
ui->btnDump->setEnabled(false);
|
||||
//ui->txtDevcode->setText("");
|
||||
//ui->txtSerial->setText("");
|
||||
this->setProperty("device_code", "");
|
||||
this->setProperty("serial_number", "");
|
||||
advdlg->SetSerial("", "");
|
||||
advdlg->SetInfo("");
|
||||
advdlg->hide();
|
||||
}
|
||||
|
||||
//Helper function
|
||||
bool MainWindow::CheckDevices(QWidget *parent)
|
||||
{
|
||||
if (usb_device->get_devices_count() == 0)
|
||||
{
|
||||
QMessageBox::warning(parent, "TL866", "No device detected!\nPlease connect one and try again.");
|
||||
return false;
|
||||
}
|
||||
if (usb_device->get_devices_count() > 1)
|
||||
{
|
||||
QMessageBox::warning(parent, "TL866", "Multiple devices detected!\nPlease connect only one device.");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/*Advanced functions*/
|
||||
|
||||
|
||||
//Write bootloader
|
||||
void MainWindow::WriteBootloader(BootloaderType type)
|
||||
{
|
||||
if(!CheckDevices(advdlg))
|
||||
return;
|
||||
if(!AdvQuestion())
|
||||
return;
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
uint crc = BootloaderCRC();
|
||||
if(!((crc == A_BOOTLOADER_CRC) || (crc == CS_BOOTLOADER_CRC)))
|
||||
{
|
||||
usb_device->close_device();
|
||||
QMessageBox::warning(advdlg, "TL866",
|
||||
"The bootloader CRC of your device version doesn't match!\nAs a safety measure, nothing will be written.");
|
||||
return;
|
||||
}
|
||||
uchar b[2]={DUMPER_WRITE_BOOTLOADER, (uchar) (type == A_BOOTLOADER ? VERSION_TL866A : VERSION_TL866CS)};
|
||||
usb_device->usb_write(b, 2);
|
||||
b[0] = 0;
|
||||
usb_device->usb_read(b, 1);
|
||||
usb_device->close_device();
|
||||
Refresh();
|
||||
if(b[0] == DUMPER_WRITE_BOOTLOADER)
|
||||
QMessageBox::information(advdlg, "TL866", "Bootloader was successfully written.");
|
||||
else
|
||||
QMessageBox::critical(advdlg, "TL866", "Bootloader writing failed.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//write copy protect bit
|
||||
void MainWindow::WriteConfig(bool copy_protect)
|
||||
{
|
||||
if(!CheckDevices(advdlg))
|
||||
return;
|
||||
if(!AdvQuestion())
|
||||
return;
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
uchar b[2]={DUMPER_WRITE_CONFIG, (uchar)(copy_protect ? 1 : 0)};
|
||||
usb_device->usb_write(b, 2);
|
||||
b[0] = 0;
|
||||
usb_device->usb_read(b, 1);
|
||||
usb_device->close_device();
|
||||
Refresh();
|
||||
if(b[0] == DUMPER_WRITE_CONFIG)
|
||||
QMessageBox::information(advdlg, "TL866", "Code protection bit was successfully written.");
|
||||
else
|
||||
QMessageBox::critical(advdlg, "TL866", "Writing code protect bit failed.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//write serial number and device code
|
||||
void MainWindow::WriteInfo(QString device_code, QString serial_number)
|
||||
{
|
||||
if(!CheckDevices(advdlg))
|
||||
return;
|
||||
if(!AdvQuestion())
|
||||
return;
|
||||
if(usb_device->open_device(0))
|
||||
{
|
||||
uchar b[34];
|
||||
memset(b,' ',34);//add trailing spaces
|
||||
b[0] = DUMPER_WRITE_INFO;
|
||||
memcpy(b+1, device_code.toLatin1().data(), device_code.size());//copy devcode to b array
|
||||
memcpy(b+9, serial_number.toLatin1().data(), serial_number.size());//copy serial to key array
|
||||
usb_device->usb_write(b, 34);
|
||||
b[0] = 0;
|
||||
usb_device->usb_read(b, 1);
|
||||
usb_device->close_device();
|
||||
Refresh();
|
||||
if(b[0] == DUMPER_WRITE_INFO)
|
||||
QMessageBox::information(advdlg, "TL866", "Device info was successfully written.");
|
||||
else
|
||||
QMessageBox::critical(advdlg, "TL866", "Writing device info failed.");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//read bootloader and compute crc16
|
||||
uint MainWindow::BootloaderCRC()
|
||||
{
|
||||
uchar buffer[BOOTLOADER_SIZE];//6Kbyte
|
||||
uchar w[5];
|
||||
|
||||
for(int i=0;i<BOOTLOADER_SIZE;i+=64)
|
||||
{
|
||||
w[0]=DUMPER_READ_FLASH;
|
||||
w[1]=64;//packet size
|
||||
w[2]=i & 0xff;//24bit address in little endian order
|
||||
w[3]=(i & 0xff00)>>8;
|
||||
w[4]=(i & 0xff0000)>>16;
|
||||
usb_device->usb_write(w, sizeof(w));
|
||||
if(usb_device->usb_read(&buffer[i],64) != 64)
|
||||
{
|
||||
QMessageBox::warning(advdlg, "TL866", "USB read error!");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
CRC32 crc;
|
||||
return ~crc.crc32(buffer, sizeof(buffer), 0xFFFFFFFF);
|
||||
}
|
||||
|
||||
|
||||
//helper function
|
||||
bool MainWindow::AdvQuestion()
|
||||
{
|
||||
return(QMessageBox::warning(advdlg, "TL866", "Warning! this operation may brick your device.\nDo you want to continue?",
|
||||
QMessageBox::Yes | QMessageBox::No) == QMessageBox::Yes);
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
#ifndef MAINWINDOW_H
|
||||
#define MAINWINDOW_H
|
||||
|
||||
#include <QMainWindow>
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
#include <QtConcurrent/QtConcurrentMap>
|
||||
#else
|
||||
#include <QtConcurrentMap>
|
||||
#endif
|
||||
#include <QFutureWatcher>
|
||||
#include <QDebug>
|
||||
#include <QLineEdit>
|
||||
#include "advdialog.h"
|
||||
#include "firmware.h"
|
||||
#include "tl866_global.h"
|
||||
|
||||
#ifdef Q_OS_WIN32
|
||||
#include "usb_win.h"
|
||||
#include "notifier_win.h"
|
||||
#endif
|
||||
|
||||
#ifdef Q_OS_LINUX
|
||||
#include "usb_linux.h"
|
||||
#include "notifier_linux.h"
|
||||
#endif
|
||||
|
||||
|
||||
namespace Ui {
|
||||
class MainWindow;
|
||||
}
|
||||
|
||||
class MainWindow : public QMainWindow
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit MainWindow(QWidget *parent = 0);
|
||||
~MainWindow();
|
||||
USB *usb_device;
|
||||
|
||||
|
||||
private slots:
|
||||
void on_btnInput_clicked();
|
||||
void on_btnAdvanced_clicked();
|
||||
void on_btnEdit_clicked();
|
||||
void on_btnDefault_clicked();
|
||||
void on_btnClone_clicked();
|
||||
void on_btnReflash_clicked();
|
||||
void on_btnReset_clicked();
|
||||
void on_btnSave_clicked();
|
||||
void on_btnDump_clicked();
|
||||
void reflash_finished(bool success);
|
||||
void dump_finished(QString succes);
|
||||
void DeviceChanged(bool arrived);
|
||||
void gui_updated(QString message, bool eraseLed, bool writeLed);
|
||||
|
||||
void set_default(QLineEdit *devcode, QLineEdit *serial);
|
||||
void Refresh();
|
||||
void WriteBootloader(BootloaderType type);
|
||||
void WriteConfig(bool copy_protect);
|
||||
void WriteInfo(QString device_code, QString serial_number);
|
||||
|
||||
|
||||
signals:
|
||||
void reflash_status(bool success);
|
||||
void dump_status(QString result);
|
||||
void update_gui(QString message, bool eraseLed, bool writeLed);
|
||||
void update_progress(int value);
|
||||
|
||||
|
||||
private:
|
||||
enum WorkerJob{REFLASH, DUMP};
|
||||
Ui::MainWindow *ui;
|
||||
AdvDialog* advdlg;
|
||||
Firmware firmware;
|
||||
Notifier *usbNotifier;
|
||||
QList<WorkerJob> job_list;
|
||||
QFutureWatcher<void> watcher;
|
||||
QByteArray get_resource(QString resource_path, int size);
|
||||
bool reset_flag;
|
||||
|
||||
void leds_off();
|
||||
void setNled(bool state);
|
||||
void setBled(bool state);
|
||||
void setEled(bool state);
|
||||
void setWled(bool state);
|
||||
void wait_ms(unsigned long time);
|
||||
void SetBlank();
|
||||
bool CheckDevices(QWidget *parent);
|
||||
bool AdvQuestion();
|
||||
uint BootloaderCRC();
|
||||
bool reflash();
|
||||
QString dump();
|
||||
void reset();
|
||||
bool wait_for_device();
|
||||
void DoWork(WorkerJob job);
|
||||
bool IsBadCrc(const uchar *devcode, const uchar *serial);
|
||||
|
||||
#define A_FIRMWARE_RESOURCE ":/firmware/firmwareA.bin"
|
||||
#define CS_FIRMWARE_RESOURCE ":/firmware/firmwareCS.bin"
|
||||
#define DUMPER_RESOURCE ":/firmware/dumper.bin"
|
||||
|
||||
struct WorkerWrapper
|
||||
{
|
||||
MainWindow *instance;
|
||||
WorkerWrapper(MainWindow *w): instance(w) {}
|
||||
void operator()(WorkerJob job) {
|
||||
instance->DoWork(job);
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
#endif // MAINWINDOW_H
|
||||
@@ -1,820 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>MainWindow</class>
|
||||
<widget class="QMainWindow" name="MainWindow">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<height>361</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>0</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>16777215</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="windowIcon">
|
||||
<iconset>
|
||||
<normaloff>penDrive4.ico</normaloff>penDrive4.ico</iconset>
|
||||
</property>
|
||||
<property name="locale">
|
||||
<locale language="English" country="UnitedStates"/>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<widget class="QTabWidget" name="tabWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>750</width>
|
||||
<height>370</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
|
||||
<horstretch>1</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<widget class="QWidget" name="tab_1">
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="title">
|
||||
<string>Hardware</string>
|
||||
</attribute>
|
||||
<widget class="QProgressBar" name="progressBar">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>157</x>
|
||||
<y>305</y>
|
||||
<width>568</width>
|
||||
<height>12</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="value">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="textVisible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="invertedAppearance">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>58</y>
|
||||
<width>715</width>
|
||||
<height>110</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Firmware to write</string>
|
||||
</property>
|
||||
<widget class="QWidget" name="layoutWidget">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>255</x>
|
||||
<y>40</y>
|
||||
<width>375</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>6</number>
|
||||
</property>
|
||||
<property name="sizeConstraint">
|
||||
<enum>QLayout::SetDefaultConstraint</enum>
|
||||
</property>
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReflash">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reflash</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnReset">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Reset</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnDump">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Dump</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="btnAdvanced">
|
||||
<property name="enabled">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Advanced</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget1">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>23</y>
|
||||
<width>201</width>
|
||||
<height>77</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioA">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TL866A firmware</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioCS">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>TL866CS firmware</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radioDump">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Firmware dumper</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>30</x>
|
||||
<y>9</y>
|
||||
<width>95</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Update.dat file</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QTextEdit" name="txtInfo">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>174</y>
|
||||
<width>717</width>
|
||||
<height>115</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>11</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QTextEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="verticalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="horizontalScrollBarPolicy">
|
||||
<enum>Qt::ScrollBarAlwaysOff</enum>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnInput">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>697</x>
|
||||
<y>30</y>
|
||||
<width>26</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>...</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="LedNorm">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>14</x>
|
||||
<y>305</y>
|
||||
<width>29</width>
|
||||
<height>12</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="LedBoot">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>49</x>
|
||||
<y>305</y>
|
||||
<width>29</width>
|
||||
<height>12</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="LedErase">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>84</x>
|
||||
<y>305</y>
|
||||
<width>29</width>
|
||||
<height>12</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="LedWrite">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>119</x>
|
||||
<y>305</y>
|
||||
<width>29</width>
|
||||
<height>12</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::Box</enum>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="scaledContents">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>292</y>
|
||||
<width>32</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Norm</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>51</x>
|
||||
<y>292</y>
|
||||
<width>30</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Boot</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>85</x>
|
||||
<y>292</y>
|
||||
<width>32</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Erase</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_5">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>121</x>
|
||||
<y>292</y>
|
||||
<width>32</width>
|
||||
<height>13</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Write</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtInput">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>30</y>
|
||||
<width>680</width>
|
||||
<height>22</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="autoFillBackground">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="cursorMoveStyle">
|
||||
<enum>Qt::VisualMoveStyle</enum>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="lblVersion">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>119</x>
|
||||
<y>9</y>
|
||||
<width>111</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLabel{color: green};</string>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><br/></p></body></html></string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QWidget" name="tab_2">
|
||||
<attribute name="title">
|
||||
<string>Firmware</string>
|
||||
</attribute>
|
||||
<widget class="QGroupBox" name="groupBox_2">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>16</y>
|
||||
<width>720</width>
|
||||
<height>101</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Device Serial number</string>
|
||||
</property>
|
||||
<widget class="QLabel" name="label_6">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>24</x>
|
||||
<y>30</y>
|
||||
<width>85</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Device code</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLabel" name="label_7">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>220</x>
|
||||
<y>30</y>
|
||||
<width>91</width>
|
||||
<height>16</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Serial number</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtSerial">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>135</x>
|
||||
<y>49</y>
|
||||
<width>324</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>24</number>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QLineEdit" name="txtDevcode">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>9</x>
|
||||
<y>49</y>
|
||||
<width>117</width>
|
||||
<height>29</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Courier New</family>
|
||||
<pointsize>16</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="styleSheet">
|
||||
<string notr="true">QLineEdit{color: black; background-color: rgb(255, 255, 225)};</string>
|
||||
</property>
|
||||
<property name="maxLength">
|
||||
<number>8</number>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter</set>
|
||||
</property>
|
||||
<property name="readOnly">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnClone">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>550</x>
|
||||
<y>50</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Clone</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnEdit">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>470</x>
|
||||
<y>50</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Edit</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QPushButton" name="btnDefault">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>630</x>
|
||||
<y>50</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Default</string>
|
||||
</property>
|
||||
</widget>
|
||||
</widget>
|
||||
<widget class="QGroupBox" name="groupBox_3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>8</x>
|
||||
<y>152</y>
|
||||
<width>720</width>
|
||||
<height>132</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>11</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="title">
|
||||
<string>Hex file generator</string>
|
||||
</property>
|
||||
<widget class="QPushButton" name="btnSave">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>27</x>
|
||||
<y>92</y>
|
||||
<width>71</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Save</string>
|
||||
</property>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget3">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>15</x>
|
||||
<y>26</y>
|
||||
<width>141</width>
|
||||
<height>54</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_2">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="optionFull">
|
||||
<property name="font">
|
||||
<font>
|
||||
<family>Arial</family>
|
||||
<pointsize>10</pointsize>
|
||||
<weight>50</weight>
|
||||
<bold>false</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Full firmware</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="optionBoot">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Bootloader only</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="layoutWidget4">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>272</x>
|
||||
<y>28</y>
|
||||
<width>231</width>
|
||||
<height>54</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout_3">
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radiofA">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate TL866A firmware</string>
|
||||
</property>
|
||||
<property name="checked">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QRadioButton" name="radiofCS">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>10</pointsize>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string>Generate TL866CS firmware</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
</widget>
|
||||
<layoutdefault spacing="6" margin="11"/>
|
||||
<resources/>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -1,129 +0,0 @@
|
||||
/* Class Notifier
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "notifier_linux.h"
|
||||
#include "tl866_global.h"
|
||||
#include <QDebug>
|
||||
#include <libudev.h>
|
||||
|
||||
Notifier::Notifier()
|
||||
{
|
||||
socket_notifier=NULL;
|
||||
RegisterUsbNotifications();
|
||||
}
|
||||
|
||||
Notifier::~Notifier()
|
||||
{
|
||||
if(socket_notifier !=NULL)
|
||||
delete socket_notifier;
|
||||
}
|
||||
|
||||
|
||||
udev_monitor *mon;//Global variable
|
||||
QStringList nodes;
|
||||
|
||||
|
||||
void Notifier::udev_event()
|
||||
{
|
||||
udev_device *dev = udev_monitor_receive_device(mon);
|
||||
if(dev)
|
||||
{
|
||||
QString devnode(udev_device_get_devnode(dev));
|
||||
QString vid(udev_device_get_sysattr_value(dev,"idVendor"));
|
||||
QString pid(udev_device_get_sysattr_value(dev,"idProduct"));
|
||||
QString action(udev_device_get_action(dev));
|
||||
if(action.toLower() == "add" && vid.toUShort(0,16) == TL866_VID && pid.toUShort(0,16) == TL866_PID)
|
||||
{
|
||||
if(!nodes.contains(devnode,Qt::CaseInsensitive))
|
||||
{
|
||||
nodes.append(devnode);
|
||||
//qDebug() << devnode <<" added";
|
||||
}
|
||||
emit deviceChange(true);
|
||||
}
|
||||
if(action.toLower() == "remove")
|
||||
{
|
||||
if(nodes.contains(devnode,Qt::CaseInsensitive))
|
||||
{
|
||||
|
||||
//qDebug() << devnode << " removed";
|
||||
nodes.removeOne(devnode);
|
||||
emit deviceChange(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
|
||||
|
||||
void Notifier::RegisterUsbNotifications()
|
||||
{
|
||||
udev *udev = udev_new();
|
||||
if (!udev)
|
||||
{
|
||||
qDebug() << "udev error!" << endl;
|
||||
return;
|
||||
}
|
||||
|
||||
udev_enumerate *enumerate;
|
||||
udev_list_entry *devices, *dev_list_entry;
|
||||
udev_device *dev;
|
||||
|
||||
enumerate = udev_enumerate_new(udev);
|
||||
udev_enumerate_add_match_subsystem(enumerate, "usb");
|
||||
udev_enumerate_scan_devices(enumerate);
|
||||
devices = udev_enumerate_get_list_entry(enumerate);
|
||||
nodes.clear();
|
||||
const char *path;
|
||||
udev_list_entry_foreach(dev_list_entry, devices)
|
||||
{
|
||||
|
||||
path = udev_list_entry_get_name(dev_list_entry);
|
||||
dev = udev_device_new_from_syspath(udev, path);
|
||||
QString devnode(udev_device_get_devnode(dev));
|
||||
QString vid(udev_device_get_sysattr_value(dev,"idVendor"));
|
||||
QString pid(udev_device_get_sysattr_value(dev,"idProduct"));
|
||||
//QString product(udev_device_get_sysattr_value(dev,"product"));
|
||||
if((vid.toUShort(0,16) == TL866_VID) && (pid.toUShort(0,16) == TL866_PID))
|
||||
{
|
||||
nodes.append(devnode);
|
||||
//qDebug()<< "Found" << devnode << vid << pid << product;
|
||||
}
|
||||
udev_device_unref(dev);
|
||||
}
|
||||
udev_enumerate_unref(enumerate);
|
||||
|
||||
mon = udev_monitor_new_from_netlink(udev, "udev");
|
||||
if(!mon)
|
||||
{
|
||||
qDebug() << "Netlink not available!" << endl;
|
||||
return;
|
||||
}
|
||||
udev_monitor_filter_add_match_subsystem_devtype(mon, "usb", "usb_device");
|
||||
udev_monitor_enable_receiving(mon);
|
||||
int fd = udev_monitor_get_fd(mon);
|
||||
socket_notifier=new QSocketNotifier(fd,QSocketNotifier::Read);
|
||||
connect(socket_notifier,SIGNAL(activated(int)),this,SLOT(udev_event()));
|
||||
qDebug() << "Register device notification O.K.";
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
#ifndef NOTIFIER_H
|
||||
#define NOTIFIER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
class Notifier : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Notifier();
|
||||
|
||||
~Notifier();
|
||||
signals:
|
||||
void deviceChange(bool arrived);
|
||||
|
||||
public slots:
|
||||
|
||||
private slots:
|
||||
void udev_event();
|
||||
|
||||
private:
|
||||
QSocketNotifier *socket_notifier;
|
||||
void RegisterUsbNotifications();
|
||||
};
|
||||
|
||||
#endif // NOTIFIER_H
|
||||
@@ -1,106 +0,0 @@
|
||||
/* Class Notifier
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "notifier_win.h"
|
||||
#include "tl866_global.h"
|
||||
#include <Windows.h>
|
||||
#include <Dbt.h>
|
||||
#include <QDebug>
|
||||
|
||||
Notifier::Notifier(QWidget *parent) :
|
||||
QWidget(parent)
|
||||
{
|
||||
this->hide();
|
||||
socket_notifier=NULL;
|
||||
RegisterUsbNotifications();
|
||||
}
|
||||
|
||||
Notifier::~Notifier()
|
||||
{
|
||||
if(socket_notifier !=NULL)
|
||||
delete socket_notifier;
|
||||
}
|
||||
|
||||
/*
|
||||
* We use a hidden widget class because we need the winId (hwnd) for Windows implementation.
|
||||
*/
|
||||
|
||||
|
||||
|
||||
|
||||
const GUID MINIPRO_GUID={0x85980D83,0x32B9,0x4BA1,{0x8F,0xDF,0x12,0xA7,0x11,0xB9,0x9C,0xA2}};
|
||||
|
||||
void Notifier::RegisterUsbNotifications()
|
||||
{
|
||||
DEV_BROADCAST_DEVICEINTERFACE deviceInterface;
|
||||
ZeroMemory(&deviceInterface, sizeof(deviceInterface));
|
||||
deviceInterface.dbcc_size = sizeof(DEV_BROADCAST_DEVICEINTERFACE);
|
||||
deviceInterface.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE;
|
||||
deviceInterface.dbcc_classguid = MINIPRO_GUID;
|
||||
HDEVNOTIFY m_notify_handle = RegisterDeviceNotification((HANDLE)this->winId(),&deviceInterface, DEVICE_NOTIFY_WINDOW_HANDLE);
|
||||
if(m_notify_handle==NULL)
|
||||
{
|
||||
qDebug() << "Failed to register device notification!";
|
||||
return;
|
||||
}
|
||||
|
||||
qDebug() << "Register device notification O.K.";
|
||||
}
|
||||
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool Notifier::nativeEvent(const QByteArray& eventType, void* message, long* result)
|
||||
{
|
||||
Q_UNUSED( result );
|
||||
Q_UNUSED( eventType );
|
||||
|
||||
MSG* msg = reinterpret_cast<MSG*>(message);
|
||||
if(msg->message == WM_DEVICECHANGE)
|
||||
{
|
||||
switch(msg->wParam)
|
||||
{
|
||||
case DBT_DEVICEARRIVAL:
|
||||
emit deviceChange(true);
|
||||
break;
|
||||
|
||||
case DBT_DEVICEREMOVECOMPLETE:
|
||||
emit deviceChange(false);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
bool Notifier::winEvent(MSG *message, long *result)
|
||||
{
|
||||
Q_UNUSED(result);
|
||||
if (message->message==WM_DEVICECHANGE)
|
||||
{
|
||||
if (message->wParam==DBT_DEVICEARRIVAL)
|
||||
emit deviceChange(true);
|
||||
if (message->wParam==DBT_DEVICEREMOVECOMPLETE)
|
||||
emit deviceChange(false);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
@@ -1,31 +0,0 @@
|
||||
#ifndef NOTIFIER_H
|
||||
#define NOTIFIER_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QSocketNotifier>
|
||||
|
||||
|
||||
class Notifier : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
public:
|
||||
explicit Notifier(QWidget *parent = 0);
|
||||
|
||||
~Notifier();
|
||||
signals:
|
||||
void deviceChange(bool arrived);
|
||||
|
||||
private:
|
||||
QSocketNotifier *socket_notifier;
|
||||
void RegisterUsbNotifications();
|
||||
|
||||
|
||||
private:
|
||||
bool winEvent(MSG *message, long *result);
|
||||
#if QT_VERSION >= 0x050000
|
||||
bool nativeEvent(const QByteArray& eventType, void* message, long* result);
|
||||
#endif
|
||||
|
||||
};
|
||||
|
||||
#endif // NOTIFIER_H
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 22 KiB |
@@ -1,7 +0,0 @@
|
||||
<RCC>
|
||||
<qresource prefix="/firmware">
|
||||
<file>firmwareA.bin</file>
|
||||
<file>firmwareCS.bin</file>
|
||||
<file>dumper.bin</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
@@ -1,56 +0,0 @@
|
||||
#ifndef TL866_GLOBAL_H
|
||||
#define TL866_GLOBAL_H
|
||||
|
||||
|
||||
#define SERIAL_OFFSET 0x1FD00
|
||||
#define FLASH_SIZE 0x20000
|
||||
#define BOOTLOADER_SIZE 0x1800
|
||||
#define ENCRYPTED_FIRMWARE_SIZE 0x25D00
|
||||
#define UNENCRYPTED_FIRMWARE_SIZE 0x1E400
|
||||
|
||||
#define WRITE_COMMAND 0xAA
|
||||
#define ERASE_COMMAND 0xCC
|
||||
#define RESET_COMMAND 0xFF
|
||||
#define REPORT_COMMAND 0x00
|
||||
|
||||
#define DUMPER_READ_FLASH 0x01
|
||||
#define DUMPER_WRITE_BOOTLOADER 0x02
|
||||
#define DUMPER_WRITE_CONFIG 0x03
|
||||
#define DUMPER_WRITE_INFO 0x04
|
||||
#define DUMPER_INFO 0x05
|
||||
|
||||
#define A_BOOTLOADER_CRC 0x1B8960EF
|
||||
#define CS_BOOTLOADER_CRC 0xFB3DED05
|
||||
#define BAD_CRC 0xC8C2F013
|
||||
|
||||
|
||||
#define TL866_VID 0x04D8
|
||||
#define TL866_PID 0xE11C
|
||||
|
||||
enum BootloaderType{A_BOOTLOADER, CS_BOOTLOADER};
|
||||
enum FirmwareType{FIRMWARE_A, FIRMWARE_CS, FIRMWARE_CUSTOM};
|
||||
enum DEVICE_VERSION{VERSION_TL866A = 1, VERSION_TL866CS = 2};
|
||||
enum DEVICE_STATUS{NORMAL_MODE = 1, BOOTLOADER_MODE = 2};
|
||||
|
||||
typedef struct {
|
||||
uchar echo;
|
||||
uchar device_status;
|
||||
ushort report_size;
|
||||
uchar firmware_version_minor;
|
||||
uchar firmware_version_major;
|
||||
uchar device_version;
|
||||
uchar device_code[8];
|
||||
uchar serial_number[24];
|
||||
uchar hardware_version;
|
||||
}TL866_REPORT;
|
||||
|
||||
|
||||
typedef struct{
|
||||
uchar device_code[8];
|
||||
uchar serial_number[24];
|
||||
uchar bootloader_version;
|
||||
uchar cp_bit;
|
||||
}DUMPER_REPORT;
|
||||
|
||||
|
||||
#endif // TL866_GLOBAL_H
|
||||
@@ -1,121 +0,0 @@
|
||||
/* Class USB, Linux version
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
#include "usb_linux.h"
|
||||
#include "tl866_global.h"
|
||||
#include <QDebug>
|
||||
|
||||
USB::USB()
|
||||
{
|
||||
device_handle = NULL;
|
||||
devs = NULL;
|
||||
libusb_init(&ctx);//initialize a new session
|
||||
libusb_set_debug(ctx, 3);//set verbosity level
|
||||
}
|
||||
|
||||
USB::~USB()
|
||||
{
|
||||
if(isOpen())
|
||||
close_device();
|
||||
|
||||
if(devs != NULL)
|
||||
libusb_free_device_list(devs, 1);
|
||||
libusb_exit(ctx); //close session
|
||||
}
|
||||
|
||||
|
||||
int USB::get_devices_count()
|
||||
{
|
||||
if(devs != NULL)
|
||||
libusb_free_device_list(devs, 1);
|
||||
devices.clear();
|
||||
|
||||
int count = libusb_get_device_list(ctx, &devs);
|
||||
if(count < 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for(int i = 0; i < count; i++) {
|
||||
libusb_device_descriptor desc;
|
||||
int ret = libusb_get_device_descriptor(devs[i], &desc);
|
||||
if (ret < 0) {
|
||||
return 0;
|
||||
}
|
||||
if(desc.idProduct == TL866_PID && desc.idVendor == TL866_VID)
|
||||
{
|
||||
devices.append(devs[i]);
|
||||
}
|
||||
|
||||
}
|
||||
return devices.size();
|
||||
}
|
||||
|
||||
|
||||
bool USB::open_device(int index)
|
||||
{
|
||||
if(isOpen())
|
||||
close_device();
|
||||
|
||||
return (libusb_open(devices[index], &device_handle) == 0);
|
||||
|
||||
}
|
||||
|
||||
|
||||
bool USB::isOpen()
|
||||
{
|
||||
return (device_handle !=NULL);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void USB::close_device()
|
||||
{
|
||||
if(isOpen())
|
||||
libusb_close(device_handle);
|
||||
device_handle = NULL;
|
||||
}
|
||||
|
||||
|
||||
size_t USB::usb_read(unsigned char *data, size_t size)
|
||||
{
|
||||
int bytes_read;
|
||||
if(libusb_claim_interface(device_handle, 0) < 0)
|
||||
return 0;
|
||||
int ret = libusb_bulk_transfer(device_handle, LIBUSB_ENDPOINT_IN | 1, data, size, &bytes_read, 0);
|
||||
libusb_release_interface(device_handle, 0);
|
||||
if(ret !=0)
|
||||
return 0;
|
||||
return bytes_read;
|
||||
}
|
||||
|
||||
|
||||
size_t USB::usb_write(unsigned char *data, size_t size)
|
||||
{
|
||||
int bytes_writen;
|
||||
if(libusb_claim_interface(device_handle, 0) < 0)
|
||||
return 0;
|
||||
int ret = libusb_bulk_transfer(device_handle, LIBUSB_ENDPOINT_OUT | 1, data, size, &bytes_writen, 0);
|
||||
libusb_release_interface(device_handle, 0);
|
||||
if(ret !=0)
|
||||
return 0;
|
||||
return bytes_writen;
|
||||
}
|
||||
@@ -1,29 +0,0 @@
|
||||
#ifndef USB_LINUX_H
|
||||
#define USB_LINUX_H
|
||||
|
||||
#include <glob.h>
|
||||
#include <QList>
|
||||
#include <libusb-1.0/libusb.h>
|
||||
|
||||
class USB
|
||||
{
|
||||
public:
|
||||
USB();
|
||||
~USB();
|
||||
|
||||
int get_devices_count();
|
||||
bool open_device(int index);
|
||||
bool isOpen();
|
||||
void close_device();
|
||||
size_t usb_read(unsigned char *data, size_t size);
|
||||
size_t usb_write(unsigned char *data, size_t size);
|
||||
|
||||
|
||||
private:
|
||||
libusb_context *ctx;
|
||||
libusb_device_handle *device_handle;
|
||||
QList<libusb_device*> devices;
|
||||
libusb_device **devs;
|
||||
};
|
||||
|
||||
#endif // USB_LINUX_H
|
||||
@@ -1,135 +0,0 @@
|
||||
/* Class USB, windows version
|
||||
*
|
||||
* This file is part of the TL866 updater project.
|
||||
*
|
||||
* Copyright (C) radioman 2013
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
|
||||
* USA.
|
||||
*/
|
||||
|
||||
|
||||
#include "usb_win.h"
|
||||
#include "tl866_global.h"
|
||||
#include <QDebug>
|
||||
#include <Windows.h>
|
||||
#include <SetupAPI.h>
|
||||
|
||||
#define TL866_IOCTL_READ 0x222004
|
||||
#define TL866_IOCTL_WRITE 0x222000
|
||||
|
||||
USB::USB()
|
||||
{
|
||||
hDriver=INVALID_HANDLE_VALUE;
|
||||
InitializeCriticalSection(&lock);
|
||||
}
|
||||
|
||||
USB::~USB()
|
||||
{
|
||||
if(hDriver !=INVALID_HANDLE_VALUE)
|
||||
close_device();
|
||||
DeleteCriticalSection(&lock);
|
||||
}
|
||||
const GUID MINIPRO_GUID={0x85980D83,0x32B9,0x4BA1,{0x8F,0xDF,0x12,0xA7,0x11,0xB9,0x9C,0xA2}};
|
||||
|
||||
int USB::get_devices_count()
|
||||
{
|
||||
DWORD idx = 0;
|
||||
devices.clear();
|
||||
HDEVINFO handle = SetupDiGetClassDevs(&MINIPRO_GUID, 0, 0, DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
|
||||
if (INVALID_HANDLE_VALUE == handle)
|
||||
{
|
||||
qDebug() << "SetupDi failed";
|
||||
return 0;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
SP_DEVINFO_DATA deviceinfodata;
|
||||
deviceinfodata.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
|
||||
if (SetupDiEnumDeviceInfo(handle, idx, &deviceinfodata))
|
||||
{
|
||||
SP_DEVICE_INTERFACE_DATA deviceinterfacedata;
|
||||
deviceinterfacedata.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA);
|
||||
|
||||
if (SetupDiEnumDeviceInterfaces(handle, 0, &MINIPRO_GUID, idx, &deviceinterfacedata))
|
||||
{
|
||||
idx++;
|
||||
DWORD size = 0;
|
||||
|
||||
SetupDiGetDeviceInterfaceDetail(handle, &deviceinterfacedata, NULL, 0, &size, NULL);
|
||||
PSP_DEVICE_INTERFACE_DETAIL_DATA deviceinterfacedetaildata = (PSP_DEVICE_INTERFACE_DETAIL_DATA)malloc(size * sizeof(TCHAR));
|
||||
deviceinterfacedetaildata->cbSize = sizeof(SP_INTERFACE_DEVICE_DETAIL_DATA);
|
||||
DWORD datasize = size;
|
||||
|
||||
if (SetupDiGetDeviceInterfaceDetail(handle, &deviceinterfacedata, deviceinterfacedetaildata, datasize , &size, NULL))
|
||||
#ifdef UNICODE
|
||||
devices.append(QString::fromWCharArray(deviceinterfacedetaildata->DevicePath));
|
||||
#else
|
||||
devices.append(deviceinterfacedetaildata->DevicePath);
|
||||
#endif free(deviceinterfacedetaildata);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return devices.count();
|
||||
}
|
||||
|
||||
bool USB::open_device(int index)
|
||||
{
|
||||
hDriver = CreateFileA(devices.at(index).toLatin1().data(), GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, NULL);
|
||||
return (hDriver != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
void USB::close_device()
|
||||
{
|
||||
CloseHandle(hDriver);
|
||||
hDriver=NULL;
|
||||
}
|
||||
|
||||
|
||||
bool USB::isOpen()
|
||||
{
|
||||
return (hDriver != INVALID_HANDLE_VALUE);
|
||||
}
|
||||
|
||||
size_t USB::usb_read(unsigned char *data, DWORD size)
|
||||
{
|
||||
DWORD bytes_read;
|
||||
uchar buffer[4];
|
||||
if (hDriver == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
EnterCriticalSection(&lock);
|
||||
bool ret = DeviceIoControl(hDriver, TL866_IOCTL_READ, buffer, sizeof(buffer), data, size, &bytes_read, NULL);
|
||||
LeaveCriticalSection(&lock);
|
||||
return (ret ? bytes_read : 0);
|
||||
}
|
||||
|
||||
size_t USB::usb_write(unsigned char *data, DWORD size)
|
||||
{
|
||||
DWORD bytes_written;
|
||||
uchar buffer[4096];
|
||||
if (hDriver == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
EnterCriticalSection(&lock);
|
||||
bool ret = DeviceIoControl(hDriver, TL866_IOCTL_WRITE, data, size, buffer, sizeof(buffer), &bytes_written, NULL);
|
||||
LeaveCriticalSection(&lock);
|
||||
return (ret ? bytes_written : 0);
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
#ifndef USB_WIN_H
|
||||
#define USB_WIN_H
|
||||
#include <QStringList>
|
||||
#include <Windows.h>
|
||||
|
||||
class USB
|
||||
{
|
||||
public:
|
||||
USB();
|
||||
~USB();
|
||||
|
||||
int get_devices_count();
|
||||
bool open_device(int index);
|
||||
bool isOpen();
|
||||
void close_device();
|
||||
size_t usb_read(unsigned char *data, DWORD size);
|
||||
size_t usb_write(unsigned char *data, DWORD size);
|
||||
|
||||
private:
|
||||
QStringList devices;
|
||||
HANDLE hDriver;
|
||||
CRITICAL_SECTION lock;
|
||||
};
|
||||
|
||||
#endif // USB_WIN_H
|
||||
@@ -1 +0,0 @@
|
||||
IDI_ICON1 ICON DISCARDABLE "penDrive4.ico"
|
||||
Reference in New Issue
Block a user