Update TL866 Updater

This commit is contained in:
radioman
2018-01-21 16:17:39 +02:00
parent 687012ea8b
commit 41561cdc8d
34 changed files with 0 additions and 4116 deletions

View File

@@ -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
}

View File

@@ -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());;
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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.

View File

@@ -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();
}

View File

@@ -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

View File

@@ -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>

View File

@@ -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);
}

View File

@@ -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.

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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);
}

View File

@@ -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

View File

@@ -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>&lt;html&gt;&lt;head/&gt;&lt;body&gt;&lt;p&gt;&lt;br/&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</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>

View File

@@ -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.";
}

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1,7 +0,0 @@
<RCC>
<qresource prefix="/firmware">
<file>firmwareA.bin</file>
<file>firmwareCS.bin</file>
<file>dumper.bin</file>
</qresource>
</RCC>

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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

View File

@@ -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);
}

View File

@@ -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

View File

@@ -1 +0,0 @@
IDI_ICON1 ICON DISCARDABLE "penDrive4.ico"