From 41561cdc8d7b99a85ca3e7b462f363464bda9c2c Mon Sep 17 00:00:00 2001 From: radioman Date: Sun, 21 Jan 2018 16:17:39 +0200 Subject: [PATCH] Update TL866 Updater --- TL866_Updater/TL866_Updater.pro | 63 --- TL866_Updater/advdialog.cpp | 109 ---- TL866_Updater/advdialog.h | 48 -- TL866_Updater/advdialog.ui | 444 ---------------- TL866_Updater/crc16.cpp | 49 -- TL866_Updater/crc16.h | 16 - TL866_Updater/crc32.cpp | 49 -- TL866_Updater/crc32.h | 16 - TL866_Updater/dumper.bin | Bin 123904 -> 0 bytes TL866_Updater/editdialog.cpp | 92 ---- TL866_Updater/editdialog.h | 31 -- TL866_Updater/editdialog.ui | 185 ------- TL866_Updater/firmware.cpp | 319 ----------- TL866_Updater/firmware.h | 85 --- TL866_Updater/firmwareA.bin | Bin 131072 -> 0 bytes TL866_Updater/firmwareCS.bin | Bin 131072 -> 0 bytes TL866_Updater/hexwriter.cpp | 74 --- TL866_Updater/hexwriter.h | 21 - TL866_Updater/main.cpp | 37 -- TL866_Updater/mainwindow.cpp | 876 ------------------------------- TL866_Updater/mainwindow.h | 115 ---- TL866_Updater/mainwindow.ui | 820 ----------------------------- TL866_Updater/notifier_linux.cpp | 129 ----- TL866_Updater/notifier_linux.h | 27 - TL866_Updater/notifier_win.cpp | 106 ---- TL866_Updater/notifier_win.h | 31 -- TL866_Updater/penDrive4.ico | Bin 22534 -> 0 bytes TL866_Updater/resources.qrc | 7 - TL866_Updater/tl866_global.h | 56 -- TL866_Updater/usb_linux.cpp | 121 ----- TL866_Updater/usb_linux.h | 29 - TL866_Updater/usb_win.cpp | 135 ----- TL866_Updater/usb_win.h | 25 - TL866_Updater/win_resources.rc | 1 - 34 files changed, 4116 deletions(-) delete mode 100644 TL866_Updater/TL866_Updater.pro delete mode 100644 TL866_Updater/advdialog.cpp delete mode 100644 TL866_Updater/advdialog.h delete mode 100644 TL866_Updater/advdialog.ui delete mode 100644 TL866_Updater/crc16.cpp delete mode 100644 TL866_Updater/crc16.h delete mode 100644 TL866_Updater/crc32.cpp delete mode 100644 TL866_Updater/crc32.h delete mode 100644 TL866_Updater/dumper.bin delete mode 100644 TL866_Updater/editdialog.cpp delete mode 100644 TL866_Updater/editdialog.h delete mode 100644 TL866_Updater/editdialog.ui delete mode 100644 TL866_Updater/firmware.cpp delete mode 100644 TL866_Updater/firmware.h delete mode 100644 TL866_Updater/firmwareA.bin delete mode 100644 TL866_Updater/firmwareCS.bin delete mode 100644 TL866_Updater/hexwriter.cpp delete mode 100644 TL866_Updater/hexwriter.h delete mode 100644 TL866_Updater/main.cpp delete mode 100644 TL866_Updater/mainwindow.cpp delete mode 100644 TL866_Updater/mainwindow.h delete mode 100644 TL866_Updater/mainwindow.ui delete mode 100644 TL866_Updater/notifier_linux.cpp delete mode 100644 TL866_Updater/notifier_linux.h delete mode 100644 TL866_Updater/notifier_win.cpp delete mode 100644 TL866_Updater/notifier_win.h delete mode 100644 TL866_Updater/penDrive4.ico delete mode 100644 TL866_Updater/resources.qrc delete mode 100644 TL866_Updater/tl866_global.h delete mode 100644 TL866_Updater/usb_linux.cpp delete mode 100644 TL866_Updater/usb_linux.h delete mode 100644 TL866_Updater/usb_win.cpp delete mode 100644 TL866_Updater/usb_win.h delete mode 100644 TL866_Updater/win_resources.rc diff --git a/TL866_Updater/TL866_Updater.pro b/TL866_Updater/TL866_Updater.pro deleted file mode 100644 index 43adca5..0000000 --- a/TL866_Updater/TL866_Updater.pro +++ /dev/null @@ -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 -} - diff --git a/TL866_Updater/advdialog.cpp b/TL866_Updater/advdialog.cpp deleted file mode 100644 index f885894..0000000 --- a/TL866_Updater/advdialog.cpp +++ /dev/null @@ -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());; -} diff --git a/TL866_Updater/advdialog.h b/TL866_Updater/advdialog.h deleted file mode 100644 index 4e37839..0000000 --- a/TL866_Updater/advdialog.h +++ /dev/null @@ -1,48 +0,0 @@ -#ifndef ADVDIALOG_H -#define ADVDIALOG_H - - -#include -#include -#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 diff --git a/TL866_Updater/advdialog.ui b/TL866_Updater/advdialog.ui deleted file mode 100644 index 5b22b90..0000000 --- a/TL866_Updater/advdialog.ui +++ /dev/null @@ -1,444 +0,0 @@ - - - AdvDialog - - - - 0 - 0 - 610 - 322 - - - - - 0 - 0 - - - - Advanced - - - - - - - - 518 - 288 - 80 - 27 - - - - Qt::Horizontal - - - QDialogButtonBox::Ok - - - - - - 12 - 12 - 585 - 79 - - - - - Courier New - 11 - - - - true - - - QTextEdit{color: black; background-color: rgb(255, 255, 225)}; - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - true - - - - - - 12 - 97 - 331 - 67 - - - - - Arial - 11 - 50 - false - - - - Bootloader - - - - - 10 - 31 - 71 - 27 - - - - - 10 - - - - Write - - - - - - 91 - 34 - 101 - 17 - - - - - 10 - - - - A Bootloader - - - - - - 202 - 34 - 120 - 17 - - - - - 10 - - - - CS Bootloader - - - - - - - 352 - 97 - 241 - 67 - - - - - Arial - 11 - - - - Copy protection - - - - - 16 - 31 - 71 - 27 - - - - - 10 - - - - Write - - - - - - 98 - 34 - 138 - 17 - - - - - 10 - - - - Code protection bit - - - - - - - 12 - 170 - 591 - 108 - - - - - Arial - 11 - 50 - false - - - - Device Serial number - - - - - 16 - 27 - 85 - 16 - - - - - 10 - - - - Device code - - - - - - 131 - 27 - 91 - 16 - - - - - 10 - - - - Serial number - - - - - - 316 - 42 - 269 - 29 - - - - - 0 - - - - - - 10 - - - - Edit - - - - - - - - 10 - - - - Clone - - - - - - - - 10 - - - - Default - - - - - - - - - 10 - 75 - 71 - 27 - - - - - 10 - - - - Write - - - - - - 97 - 46 - 202 - 22 - - - - - Courier New - 10 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 24 - - - true - - - - - - 10 - 46 - 81 - 22 - - - - - Courier New - 10 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 8 - - - true - - - - - - - 25 - 293 - 381 - 16 - - - - - 0 - 0 - - - - - Courier New - 10 - 75 - true - - - - false - - - QLabel{color: rgb(255, 0, 0)}; - - - QFrame::NoFrame - - - Warning! You can brick your device here. - - - false - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - - - - - btnOK - accepted() - AdvDialog - accept() - - - 248 - 254 - - - 157 - 274 - - - - - diff --git a/TL866_Updater/crc16.cpp b/TL866_Updater/crc16.cpp deleted file mode 100644 index dc5cb90..0000000 --- a/TL866_Updater/crc16.cpp +++ /dev/null @@ -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; -} diff --git a/TL866_Updater/crc16.h b/TL866_Updater/crc16.h deleted file mode 100644 index 752a0be..0000000 --- a/TL866_Updater/crc16.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CRC16_H -#define CRC16_H - -#include - -class CRC16 -{ -public: - CRC16(); - ushort crc16(const uchar *data, unsigned int length, ushort initial); - -private: - ushort table[256]; -}; - -#endif // CRC16_H diff --git a/TL866_Updater/crc32.cpp b/TL866_Updater/crc32.cpp deleted file mode 100644 index 0f47fb2..0000000 --- a/TL866_Updater/crc32.cpp +++ /dev/null @@ -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; -} diff --git a/TL866_Updater/crc32.h b/TL866_Updater/crc32.h deleted file mode 100644 index a8a9180..0000000 --- a/TL866_Updater/crc32.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef CRC32_H -#define CRC32_H - -#include - -class CRC32 -{ -public: - CRC32(); - uint crc32(const uchar *data, uint length, uint initial); - -private: - uint table[256]; -}; - -#endif // CRC32_H diff --git a/TL866_Updater/dumper.bin b/TL866_Updater/dumper.bin deleted file mode 100644 index 1f8f266ecaaf559127eb459e2dab2b0ac6289e16..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 123904 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 - -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(); -} - - diff --git a/TL866_Updater/editdialog.h b/TL866_Updater/editdialog.h deleted file mode 100644 index 5fee158..0000000 --- a/TL866_Updater/editdialog.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef EDITDIALOG_H -#define EDITDIALOG_H - -#include - -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 diff --git a/TL866_Updater/editdialog.ui b/TL866_Updater/editdialog.ui deleted file mode 100644 index 35e8434..0000000 --- a/TL866_Updater/editdialog.ui +++ /dev/null @@ -1,185 +0,0 @@ - - - EditDialog - - - - 0 - 0 - 471 - 153 - - - - Edit - - - - - - - - 307 - 117 - 161 - 32 - - - - - Arial - 10 - 50 - false - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - - - - - 35 - 63 - 71 - 27 - - - - - Arial - 10 - - - - Random - - - - - - 238 - 63 - 71 - 27 - - - - - Arial - 10 - - - - Random - - - - - - 41 - 9 - 85 - 16 - - - - - 10 - - - - Device code - - - - - - 237 - 9 - 91 - 16 - - - - - 10 - - - - Serial number - - - - - - 12 - 28 - 117 - 29 - - - - - Courier New - 16 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 8 - - - - - - 135 - 28 - 324 - 29 - - - - - Courier New - 16 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 24 - - - - - - - buttonBox - rejected() - EditDialog - reject() - - - 316 - 260 - - - 286 - 274 - - - - - diff --git a/TL866_Updater/firmware.cpp b/TL866_Updater/firmware.cpp deleted file mode 100644 index ea7437f..0000000 --- a/TL866_Updater/firmware.cpp +++ /dev/null @@ -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 -#include -#include - - -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>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>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;i0x1FFF)//a little brute-force method to match the required CRC; - { - for(i=32;i> 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>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>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 -#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 diff --git a/TL866_Updater/firmwareA.bin b/TL866_Updater/firmwareA.bin deleted file mode 100644 index 4053aaf838a8b2ba941d4d6923d4f6635ccc7b99..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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%0DMtd#eo_B+5=n85y_ufupG_aN-8?aMI= zjQ921Png3qdSS$gI=Sqx`g8gV(3H3fzB~K$AL`E{{Vjcm-lYpURG7}xl+$Aw;%+#h zdtv8m*so_rR_T-Z8d}*P@aTb(5Bm4&c7;~>4Lv8K>Z`z^8}jatwJ7vllE*oxZB-;J%u;# z(EfX+_gAn@JWo#xU!kWVO3S5sM$V9Tss8icpQ7~zdY(QF&%UC6o@G(a*FVV`@~%hU zX7=<6x)Q{d$oC3;1+%Rfo&kKFOJEZjTwVa(1a4!%BN69|G>^J^sV3q~YoYBwwVWVM|h#z_Jii%vY)ub{QDvDN~JUmWNVtu-K4Yob(Yn+N)nTaYcyMoeTM z&dL+p74edjM=48+B%%9?>DK)g?qp22T2*XAio=}W9*V)c^C%Rc`R z>vMG3ldbIhl$8~&k^Jc7y^GaOyou!UqkA7+_GIgy>h1We;AI6pwEkpsDs~j)P>`%; zDC=IfV*hX8-d!P)R}$|_K-u&NdEkbo5wv3yZx#DL#?vC6i{vaOA`>KQ$rI1%bCeeL zZQ!wj3z)#25*#P`a+0ICK*}EXTtdA_I}1c|fP{F!O%h_#`=fU0xs+F@=tGziS`Wn8 zB?*A!pArX9@RCXYfozBg>bXo&;4%)*DN9g~B)69usY}({*s|e!qSvdH?4jVd*bBpV z!&391;Ggh2Gt4`U^?m-s&s`#GOp$Px)O5h zyQ6nOqm@h6Jy)^s;r<%%?`RFhoq!CKpRaz4KmRSa9Xy?R(a!16dZivS)Q9=AUj*O7 z-AwohCyrffC-LkA#}1skjxXcb`RWOyZLd60?{ze$R*us*6=Q+!&5;M9TkuCR3s|xN zO49mT;B#EW=1F6dft65R5Vk`R)oeo)XKqK7p_y$C@)3l5cnr27iV9B;A#FuG0QhiW zAxPd5kkr1{$@Q$7fD1LXIU%#Qgqm?wfrHqhmSb`xS`4d}sWpIiHx}E$43P5)&(Blw#Txj3d=HTs%6Tl(bhrMN>8CEn@7i9t{L($|L zkZwS_7-FH5oWe#EzK=lu}H(Eu;8|2Jm~ z@4P*rb?Dv4s8B(J(s_bsHNH;7F7Oa7+tf^0H~3rC?UlZIL}@o&M)=M2tDvd*jJ_GL zbP1r86O^^#-fSBac6v^S2F4S}Jq=IcMTdz|(nndO8~i zj!6a^k838IfUAv7#FaQ^`M?=Yk0gAIAtvwGF|hH@!Cw~sGI^9L84d3gWfewwj`v)T z^gEKy&f;y);cd_5ZO;>J&*~)$dg95!7HE7Vs4Zd7!|OTj@J6Qr7c;a+w9ENC#cVd) z(rLHi6oGdTXoVQF!qCGc+k4VJqjo;i&W)I2Eu^7^9oi?FVWsvy*ZvjWrJbv5?kq?Y z?$LH=KhZX`d-SW&>s|WITAsd4J3A=pWLiO+TtUbwX^myy-_}SY#hCRvkHCTTi))^i zx*zEMjwZbCnjw+a!P`ye+DaKr#|VF`k#^hL-UV7tqzIlD{sh~tb2#1>bbk{5T#NQ^ ziIte6Lv%K!!_!%&LilOW9felxK|YFP9%!liyxuut6gacR z7&P=Q#;^qTS{pRN`2VHmM&5$-&hXR?{%+7Y3#nNK#_=k~aX&Bdu9_eDJuh+3;E$8W zV1*xnF&KlW@m}~D?NI+_<^o@8GgD47o}F7LR9us|aiG2PL*E;abQkeYB;Ti; zEFm-C9~C}eh@nIw8#fH552sLuN2>GeS0O1ImVg6%92JJNuo{(t>O`D z11*v>gC6jl_VD2ml2_m!wiU#?3DiVV`nz6vMLoweqVB*oUDM!|A_pAkh-wGNI;c9l zQy@RK^uDSdRbNp*fDd(o&)K-nkLKW77R|+#c&brFj3$+9>M~L8Xf8KF!D1GMjFU9* z-hyug36sOB)ARYh9}Wb$XPb}q?Th0v3H(CHJ_Z3L<(?;P!A#DRwQ-)T%ap~xhHS1! zn8Tms#-2#68LE@UpIBp0N_P>AqkId`Pm}qOI|&Xgv`xv&YD^MOxCCkS5a*Y)Ed>rz zc3wH8wOl_iMH=8TeMjBQR)AtlNOLHTIPv;PIx`26SIN@?`FtZ!3!B-^sxLSRD{)qE znL_J+7GL){eBI~rbtjpKXhTYPsEsn-MmgFz=v^3JTf#lMg5q456?6lw_!p zg zBeVgF^1*+B-`Chs+fa89=YWMRH|RXbU`zRLCcEC~^0a#>auE5OBhNUeLXOtu>8gpv zZ)*$G2C9XBy@pz{{b}o=(yd)oo;XB^f@XZg+dk7Ed<)U0jcVS<(= z=HSJgPZ4<@CK7hz^v9veV$ph-vZ@HUO)7)4wQQ#!2L`;`_TcNWQc(B8Bh;mv8LQ zhbnE#WTTlegX|%;>QRjB51K_C5XN zk}{{~r`imw6_)pRBA$z?7qf5ccd(~*YDZEXB)ysgK7VfH1Mm;N!AEKaXM#?7VI{Om z$LS3&)6u2CWtP&f^8^oP!s@13mtM^>_g}7)e>5R0O;^fshyOgrK}Y{kWv@xN*{E0K}-OQ@w=*RGO-s_*8@^+5L zxhjNF2H_1X;mzz*oQ4~{uMA4xE$_pB%|`Dp2c`eA!zy_%dwww4b6H3wpJlW^pB|(u zaMDV`ODT?;6%Tr$_Eo^LCP~F8U>&+cK=B@GC&p`?j3)aL6Vzn}K)zD9U$^V_#JG&;67)j3{j zs&#Dh`5arDsvVn3l%^W!r!i-Ksn>A<^%4LF%Z|G!<)KGviP|A)lw&9Azl{1jPI^-~{k9pwZk4=P z;)IRKkLcSJ-X4?Bx9gP6Y<1kf(Mm)kxh3Z3Y0vP((dE1i@{M^Ta4CU9QLBVseLVa~ z)RQE)8|{~=YTrfsvSBOoX!Kloo7#iY1XZMW5E?Pt(Vjg0|94L5UknnFQVs_jTy>9vQ4e-GuzjWqLU%amdjUEh%3~=0wS}z-8KL zkl!GRM_^{H-Znt*4gtSgz(Mi&ybWHzXQPL|`xfBXp5Gdv4XhbqU(I_x6hW}gk9e>x z?={wS)%DbMZ!*5Wx7~Qs@U;*RE-g&9y^u7+V^Y)J4aReZj6E@yZ8HvSX|F!CslB-f zQXHgfkZu{ro~3jx(rx3}50LIeerL-B){S%r%6BwRWF3@lM7n1ZYo;{HceG7rK1w4l zZAV8jtEDue+jewLVUJQ8(RDkzO4$9BhHZ35_f&QlrO|#z%QW^aq}x%qz2j7NJEc*# zy>mKSNomw=@0!7GqBQEZchB5gVk|Ud#Eh}*YCQ2{bbid{a!R9BKW4Ll(ioi|v$+WA zCge9^Hs>O}5#={xHfK>9v)PE*oJMJs--y{vr8Gvg5wn>{X^dziW^)RqF`|u_jg!(C z(MHTBhtg<&BW9D1v>$c-n9YceH0t^>n@=c>x_->&7^P9y-~HRZ-*A}}WSrfNjl#DT zc0~G;(1!Y^`q!{O5T~)_FkmL<9lC9>0iei@m%=K7U`25G8Srg)a?fWZElQ3%Loyin z4dHs4lFxb2T?UCwc?p#*;}L4gxmDB!z!mlY8l3@72JhLLL;NyC(z1j%bY?)JLH?R3 z-PD=T)(?A^^<4)^&b~Ors{v<%`Hf{B(9bO3Awnb~Wx~xlDGyPIf0$&IVpaaV(w1zM|K~`^jc!<4*RI1I)+_ z2}~|9BTKCO7@goJfu)pUsVrrhv_k z&!&)_8t?TK^d#$!1%@Q+7BNS>?l_hmuRESu<71e>{-{y>)FJOg_Mt|sTK4 z)&o3mCGxEB+Cq_8Eo_-)L%DBh=_q%%Ms!IUsEsPvSAy@O(l@bQvxJ(#>uiR{MB>jj zgRk1$q!FWP#Hh$hp|LSnX@t)OiZx@Qt1n%n zzM(Az5q1FBW3-N?C7{czS#)q7#r`7~REZ}3w58G9~^UhcU9`~bE2vhyxK?+S1TJ`KZ` z6q?wJ+?PWW`%?E6Nt)PXTW}iunh=JXA8G1rR;$qREOim!xjFoz+Eo9zdOLEas28cj zR&)3nNPXU>kITCA5;0ON%6#ksGdC5a>XI*D)XH92yS0(XI%Fm++0mL~; zV6p<%C+sJM-3#?dvZ4T@o~?^Ea;eIJAdO&%bG(K|s<^G_GkBWHt++opY=t*{A9P(B zgS5L@Bg)W8DSj>d7c+I=8YHa>m+3FTdhkvD6kLz%>%m%FcL&$u3eN}d6?q6}0nJ^n5U-&C-xZyw^9(`vpJ@c4B>^r&7yKi_>xY@08l%&l`0|L$Fwv-DJqGb3z=!B2 z3CXVv^3+J@?N;N%;o9gngM5Si5}v?_61~nKn~L&zWn81-+lDhzVthkeX50#$iP;9> zf!7%;kUrIT6mpwG;QbAy$mryJieT<}EljGk^RH<)%rCmLm3xWJvi z{1oDUdvaLNaxBHtB`e}Yjk(4m}PZ$p&TT%%9jqBrY%)UEpW`T}}L`&d7$(>mE%K|ZbXL(qF5+2RjK zH=(auzY$)rgq9EOBe@T6i&;M$SbTS%7m#=nyh@N(MGpK_5R6~S+oaTW`fm|I)y57i z{(9elekG5^d}vE6u#(np!XS|bX4DF=%9L&c=F-*`O9P{6>lEoOl<$g_Z$r9Grct*o zR<{e~yJUG_NnIR6J+!3@*j86ttQ}xXT^%CbT6<{Al}c;d6|m5tzW?h!FxIZvSUb^f zXRO^$^w$~dPvF0zeS!bR(x}@Wt1Ix$SU%>{-t(tk`g%&k35|lh7U6*)uO_ce;5vD= zc^v}J$*arjtmpVjUVUDdz+CctdEEkQ$@Ay+)I){`X?N$Q=P*c!W z&+(Rm+JX+!DVQHBsJmFnLrH?edDVF>u@-sH1dplbSc|;pV#-6$0{@|&1@1#VugB>i zdR`yzc|FI~sOR;(59(ROYcHsyU08rKhvxrP_{k*y7s5}bfN;XshJbJlfPCO=V)T$t za(SbR%PNJ;)0HF(b)lcQXJg=UQg)ip+Yi)0&e@XBA*hgf=5q)twNa>jUo9kw;G~KX z$sP#i3TbO>M8E{#JDHD2NM~as;!;~NA|cHcBN9?xq5I*7_Wg~Byb1Z{+kk`{>I<=QmVEFsajv#Od(@@1)n>pOtPgx$Ur&zK+PHoA zyU~eSHhq8K>OBRilFv5=dL2PvJtEHw{Kg00u)gjp_}R|U9#_)i<%4Xm3SCmAp<}2r zJ667m{Skh(((w+22i-FDJ@wnl8je*Yqyn1zGf3e^m=1h@v_84CMFQO776Syoq_+AX zc=!W=w(Hf*$WGAVB)b{L+4^n@bU#-~(7C`!hwI?Kcyt5>0UzeiE1f4jE0sahq8xwE z#ZNJk6WpGJB@n!+#M5MoT57Z692}+Fk!mGEka5WS4PJZ5b1DCo9Mfc764J*5KH|A5 zr3A@?sQx#(_lAT{M?&{Qayh8(4ZPH6!SmJI*n`1cc*jKLJcQp=sDB_x5kj^H$=5;v zaQ!y;fnFc|VUWCE+!7?|!p*_m!M9K^fgRNVpCInX1Hs=T|Dho5FoN{=;_j@$&v@zo ziRBd8O<7)mXL5YAMV*$OqGz#(d_MtSf5^L$^XsKn#vCpmAbpJ42CS)4bd+g+C)!6@ ztha_?m(=X@w>qhYKhrF*Nr@fN6_utiVCLkwf zO$2!lS@uajjj(@8JSYCsx4yK7d~2g?wj*lGkhcN-CR%H+T*0Ln30#%1qXZ4nRVU;R zXY0`W=h_WTor&6`c}mn{Q<9$T=;z5JBa5!0XYJ@c(Hp%N+L3Z+j7fQ#YVAeZ_VDqb zjK)gjwO8US0(}#EOi$*XcR@SxUfrX$SJD`$55mDRq3Ixa#A)E&8o;m)ES}sqPEU?( zlHkOhqmK>cbLbhXv2EJ@(neOYpjs05l`SZas>1t`JqdhuSKV(f01!s}< zM`mQGU;08K9p_^H;^*;Vtp_6H3-#E!0(H$aiTgYsP+uW6f5 z<2em_gs@2&;^kWXyR=t1_4=fi&J^wExZV)!2|8qCJM2zf2eH3jQ)xYdUW3c*EaC0J z3=VrN;WuGv@%`X~S{KG2sCh^e^J!|%X0tR}lSZwn`jDGeg}DFekszlGuh9k^i z+@#$Bo!`-Wbb9Zj@JH5OIpn!gyBaOSf;m2_Px;#kdMGcr9Pu5sahh41tc`#gb>hUW z!aKpZke#7Qd$)QHgqKuat0MA0%n;#=f)=7BiFB zSz4gxkd)da$!{`4+3Z#Br*l6bVK{}#cwPD3s5VJD2dgaDm1VQ1RI)8g`+|0DA>swn zYDrD<xmO|*Y!rQ+-Q->_35s}%Y!g?5;*OSw_ydLRB|Ta@p>7Uh>*hLF(q_}ag* zMLC}&U*rV`Z-(?;-iF-aF-4wfB6@=#a;!BmNkbiE4By~#hSP?9fT{ux5dR=qLI9cv z6x%`ilF{Pl>;`3dOlBa@rc^jA;m0r{M-iNlS@XLcxTCKina4t>UqZh{UcGDbfU;;8bSFyMp5gQ?QQNY*VnQ8rJEc<)N2sBFz}N zM-ykQ%Tx~?OZuAs6eNxlrJUZGxaPCxa3wro1|oD?@@IOBYAid8S~9HXhwJ=YhoGaK z45!;#eK;3jF5TYK-re5Sj+l9{rfvZfigXL={D{BM(AH5YGz`u#UPUifaK?-An+cu( z%@ENf`91Ljihghrhlk{`oYwzrrLK`$<5oG{ZJnLfu-hh!?NOH6ff~|8@YTZ_x|8&V z2sipr--F*Y$l6!pHhxl^NiZAmYyk@SY0{(xzwt9YA^n zZ$U3$T->6B_#`tR3wa3|0GWvH_Cx*Wy4|yh%l}K@g>ba||Mz_ot`UYc77!5roluTO zl8s-J=?$b3`)m-AMF+geyP+U7hU){6{uGT=?9QN;x0B+WCD;8&|9eS39Kv3?FYmz! zuSL&))UUz{`~hV|iTVp)RPy9n4PR9HMEhUb zi;IAjDflhNuL9VJq*}Fy_Srj zp$%BC%tYLg1Hh@!TCOSgFTuOGJYU?6)gDtnV>ctZUVgYpn-^LDzCSbz@g30Dkif}W zP=8#Qve$c>UMEpj)_y6D$7Lo(s~hUSmQMA!?&$#~1M<-ZUxnJxRl|Kt z`}|+S+50f)XP4;>j4oIEGvwSyIE>0yqg+NU`w+bfS~j`W9cVQxoRFRi$+-=@2`Oh6 z`pYg;5xm9HX~Z?efJX~WFRu3m>sfIJ|LZ2wWX`Y_g#)T{OQ71hHBbX9(pp%N);YKP z>zzCNKIhARSdsc+MH;Aw6{*khqauYML@jFkJG)cZnQm=>-6>g=W>^ctx2Ui`g|0xL z#<2r-s4v4Nb*I1H4r!!)tKVvR;*nvJ@M&CQ3T>y{P_N@Vw z3_y#4PFfLBX*0VoF8yBuKQba05u(`ISe(+E;yM6JPS64P$MD7!zZ#>Vs{9TDprZn9 zfewGCzsuk4??D7S=u|-KZWQhVOUMpHScy|6utovzJ{8I*pT90sFe7nt5X==+tIISn zI2(~=T^UGt0Ad8;2+{0am_vWEPmcowkM2@|rx<7#?m9T<1t{2w*XLNTmy-3iTPC$uU5jB0Y767f% z3V$RxQ}WI5UPlrCU}uXIPO1*M!{HIwJ9<6vhQNe>N-dU4*Fo9N)~@E z?-km^efL5R-=vQZcVRuqJIm#u=`!5eagRC2z+*p-KdFU6K1j~ho9Y8KT^+YV8V{VN zj%0zEO7Y-%y9JJpNyK*xo8 zwkEY)19b*s@DUv`2~?Lg@*F4>W7a@_Ylju1oT1a+8>jy<#e?)QP{S6Mp-<;lo&4el}_zf`5FC!`d2Ln)~mUQg(@@!%iL#-wT2O?daM~X2Sl^{1JqEYe}{I4`%K5= z&=zf?Qus^;V9by=|Hxn9?Ni8#?$Ml)Q`9!z>Yw9!d$EY7XywEc`NzG&K1EvH5WiPi z-H?n`THSCCGw^Rw>xHy1OBiN@d+qGS~?=bl;=31u||A4`nsT3%z58}hrU3gd*Xjf`y2Wy zeSXr)=i1s->)Ph8cD>~HxwiZLt{vb&zYJKh zGf*wRUJ1Jh3MRf(dYb2{dnvEFZd+c>`Yn02>v!bUt$#VMe*MloU)`2GfBlxc#z390 z%NgSKeXa?4UgBpgi_i$gT(BPCi~Ib8D(!f)(p5L0{I?&t)5=%@X}{0;-GP?x zsezimgO84V-|-@~4jFkidywNCV?&joo%7ju)c;@(HNjaw>UXPcUErc&^rTrywm=6K zS1S*q-&QpF5YQp#LCsZm(|lwfox}!Pf!2muEG>9!cpEOgp(9 zV%(?6@LyqFejdKf^WmX)F8KBHq94E`*BOXmd?u{U6HqcC{T3%O#xQEnk*8*Hs=;g8 zbohPEFSgNWXjXRqEk6%_G@V>7QyQCuGnZh_4}&*T%6mDNb`#75bZmsm1LFMwDs~fH z2-w)dVdE(J5D>rC=O4piBO>#`7silhzF}4_GsxP0v^-lv$3H?lTR_L%G3dA*P+*eL zGu#&a1)xBYu?0||kl%ll0tN2W1Qhs-7VSF>C@`W=LXYXjCcUdR0PbEkd+|Sj1y2$z zsP1Z8s|2b8wSWh>5`ICa-9vx}G!ydnIOJ9J@1SL}A!zFSjSgr~$O0(dK5ip!D5XoiB$BpQ}&nfwrgg(gb9vO@$25 z!;L`(x$^5^HMc<@M_OueJbQVZvLrg0_Tz~h|9^*hyrc$d3GWCrrud9ZkT?b`IHk)aSnhUN$Ge%O_&+vhEAuwq z!i!BOVoA67IL-`;q7F2O4>U-<^Cft(*$yu@JK)9U=bCMxAYOu3 zo9&=3cKCeNeE-ED8)zMRcNzPW;hNacBs(n>XpZ&TCcXe`7<#*+U;gX!*QtTFe9%>S zo`1h$!C77XVD)u=OHGA!>y(EulI9a&9nCE94O;oU0r%<&+D!$t3v*~U70_roFbkUP4Nj>A!_`qj!?aB)@cma@g7V)uW)?6G3rK5R~%+ zrqKD;6#Ofty#3ryd<@Eg25jvnDiAc_mr#J9u0R9QIdmiEM1B!mlP8a){p3B-e}AUv zHq-y93kF)d*W`+iJoH;r}R+?E#b7s9$-TEHW6dE5g2^CS!Ssd~Z!UQLOeqxSuO z8RwQ3?a8>eIEf@i{eN@xIN3UY;m{k6QOtSGF|8Zu>BO{dpr;elx`CdK(6u2AA)#wS zdOAYaM(F8q?HsNlB=mG777ngKcc5m-Q;IK9=)6e16{3Np-U`tuLT^Rrya-(tq4Oei zRfNuqA9^v+RpFFK6ZBkgf(k7h?rlKww}9Pams-&yaRhLJb17+7cr>PHQ%2*jJHdq{ z48iVcgoSxKY|U5TH`QYQZ-bk`Xw=Kn2jn?FM< zjMzQ1G0vr0q4rz#96pZ|E%Lw0t>T9u)l9a?w`mI_pFtbfuwHhg7q+xysc&P)aix)z z@sX61jV<>&0xMhYcO;YB3EQ~Uuif)5WMIUDUXK&DQ2QNXlI&9d5cg^KWw!cFs<74H z0S<4e7poV;<2EZl!(+9Ow~ z^9ENXwQFVPtJ$E+j)$kK!*PrHeWQA~N+B)|#YmzRBn#v3#Az$Cc^(HJTH_Jbb%MKW z=|p$=(u7AAjC49|rjz_FlfCyU@Fz*v=*ARXBkIHHS&!(g@Rn-28TQ|g4CD?9`|tY) zZh&2@90l1nm%_GrjuQ5kx)&x{hU2Zf>8+>px1Pb@`e<8i;>3M@xIOBeMc6kuQl?Y! zww+$e+sr1b!@*wIT4%8D1}7+pM#p1OiKnCanr-Kf|^P<5X}~L(3!C~3Td!tHpAZ6p3TDLTpK?VlwZ114c}G{P}0RXAJQSI zD*&F86&`{=mw$l5B57U-GAx@?hV{@O28J?R|1=Xm!jR_rr#AL;D#P_p zv)E55&2>Yw*^iMHx}iDjDN1wQ&|LTqft?Z8^&A5YUF5@3s1t_68(62<*_PCBfqsHAMu2d#&}vg3)roc#&}x03SohQ zG}pa71r{hsV+^f5U+cRJ=?0W(=rXgfQ5tpOzlB{&X|&mZ^(mt?`f9-XT!?f4bpu$R zvnh=>1Kk}LfVhI{+=<=NqzUWuPYrdE4q$ygqBPbg(Bfe4Q5tmvZBF(MrO_r}2s?nZ z5BWZ~{r&tE8w@%y?@VXspfWAOF-ruR(_i)O;Q_L~uhq5{8{ zW7n7B_iWsshTqBfDhlvR@i5GxoeFW1v7Wv|Ted^v@+Em+e`w1Vc-nbE-q#)4@+`D8 zpON>_aoz;aJw35|yt6Hx@B-8!@BN3iG{Zwsqb!g6dhjvpFs-4mg=^Z_Ks18lYY9M16}T1{0%~GHh{lg&=BJP&$V8yK+ge| zmJ2M+8riOW4DR`d{rT)I_`;MJYS{Z`uS5U7_9JK>yrYTLCTudK$(lKl%haLDW@twc zN1kL(@1dPxw6m2ck2uHjC%sRjezNRu7RmlFrn^wLv$sWiR$HSzuDz+1U`$i_n7pwu z{ah`@8IfqK)Lq?c-}OM$vFpL8bJs)BFmw}yy%Bg|)>&bn#%0mOVQT}24PJ?T-H`M9 zz+(>^y~}HYDx7MLW?8H9Q{w zuW9%Ry}qTea74sRe(l8j8mjyWt|YHG(YMpY(BoW_V#xD#l#zNAKc#3i(2&DwLys-h zlK{2-Rg_JQ=s8ok${$~*Ba@eNVw8<2BI1=h}^Lli}ZJbzIWa{GJKx4}abCv>t$ z4WTnBv@!pv9zt!zZCq;EFXTSS6eZ#7ol1*pvD#ubP{3UPYXU7?rxmbW;5c+KVUB(77kj&}rNXs@;2;VzK6h^E@Pz zBiS6u=(wzoWOk6S{9`bdwnO&(~4UGMAP!^Y}S16kY zm#E2JEXg|j2&6Ui9T62mUZXa#IqFxzGZcDaCzBc_ORP5zKN-E5_vgWt*;C z)&-xwG?p<6dESBk3FNS8O28MB=0kq7MmOoJ^?%{a`651Elw0}2!WVpS9s10dK-xZI zd0zM&{gB36BFQfAF$h~+ie(UJK2r}=lO+8kNM&X$cZDZG%G0Y+|NdrCDkIX=JYH|A z{s}J?s4iBl`V8yX@PG!XQrr3ZC9wY^PrjDOZ2hzTrs`I$srkZq-V~m{xEyAm8HdJCVj1=>H=YIVJq)tiR5RigPDUr~>%85)m}))Txe2-xv=tjmGLA1m*x zF3sO# zhGxJ&DC`K(m%M}S0rsu%Igbbk(8q#KR*MTXnTsM8Z1dH-Uh>tsw!e`S}wH8Snpc;A(=6lp4wBa)S zQsr+(=-==+6YyQ9`ca#9qZ4vkYX1tvp<1NcW4gNc4?hj=zLdL594dkTCd0X8S-rE; zQE9InH@qpjvAP)e&lLPoTeL@u`FWPCGb|%`$$nxp!0HSk&H|mJe6ElaV}4!!wq?*5 zzflFHj@Bpw$5oi$wU`NMqCXql*lb}x4sOJZ{f%UMG~~HhEeQS{WAQgG54J*s{6Vxy z_huGA={Hzo@DtoM;K^K^pZQG3ojC9QPkYxM-$a$~XZn7?G!3P|ihu<{L3va_MXM=q z5!Z;KETV#f)(GJ#;A=@r?Y2qUrlr)@5LJ&$pM!)`YT0t*Q}ns}OZgqZXqVadP3~6DY40 zh_u07Dc-tcZmLQ9s^uxDqmWJMe&!XK>Gz5V0k246z$+3H;uZ0Q-~x9F@ro=7@rqPp zTf+suA)v6(wnMAjM@4=r14BtZm%ju=;WWPUx`5s7KBHsh)qH2zC zfx3kpVKoz3%}yq5v`ewg9|2^`w^f$rhx#70Tv`@?h2EAT>z8~FnookBTJtf`Q)@m3 z7JtQj40`s|YNoH>_kgFPcu&$dpl7hLz_C>dv;8}Hd~I8w@SZbZJ+N6n7}*%heJF8ze%GTj|98`am*eZ&+Ng#kcAh3EZGL~1u!oF zc>@T2JdSw*;{9HLe?WSRMV8hx@B;AiMroh)mc+XWqAcfhLO zC&Y6QzPdD-+qdmM(EOsp!4Jf<5kN?&bXRSyB43#iSrHTQ8H3Ml$c~^|eQN#;$;VM< zHA_6mL(41d73I}-@Mb%(K!TAm;noIZx5Eytt&S8m9N31fI#e&fdt&wGKtYoQbkO`? z`;ghv0<d(VYn&2iQh3X5&87 zb-*`>XElVoqwm-QixBNk5JY$iX&%QyvfYSI6SFDxrl|sQ3c! z_Z8fcVk|;+)GS0yu$Ue$AMc+t!-6T11KF3pS381clyXV5!N^J<338?*zR%nf( z^KWL_E@G=Gz8YKx**idLyD4JO44UUABkitu~p>!r|tZVUrG6 zqbXYTBCF4?&S^$QN5^vO_&}6uHe^t$P!~hr-WiBcjS~L=*;0)d&HOhqJc!$B@^E|h z=_LXCbRf#hrbf4cZz4m1dVqQm4o;-euUUEjmCc&YYKsJUm-WD^glv6`9W9z(v;H4oTwbd}&^G6z zl3)^gWUe5|I>VUqBLO;r>qxPUOan42W-_T zn}F5B-WHB+rs%U7j2c0X4YX}YJwKYmGY-fDMr}kP5}GQ8u{db|d*LxVJFc&g*Cykh zINQb4S4a+t&kR=bq}u4(dkn4;;j2Svo&iaS6PsUC6v~h7zi6ksm88lf@7)cF!Vb9? zn~AC&V4OI)Arm@y8n`^L;_-bQbaT``X^3td*pLWYWMA+^I*RN&d?z&MkPV{46|c&1 zV$X(TY>jQ`4wR64;XCTz;08wgHQ<<(!G&iw{v_*Id;gT98>1S$@-OxMQ0a}1l7yaS z9_Q0515g1j*O!XbAT*ozxw`lULa#d{s~Jg4F{@LOLlNv=l2aQ0Ay>f@g-UtyN_n-s z7F+Y=Slsb^^t$$->;M_wP^9RH1 znB(gf?U!iXtD-Xok>!HO)Lz^BZ50LxIm&^Tt z-w^{}y9n8FBs=$Tzt2P$JpHZ60V2ELqtbMEvI*BNzA;n2n)PO&JYGHpKla<=8#wbQ z&dkG^cS+;?XT~+2l)B3sq;z?Ze463jRf`pDX8z|eu@GC0S~0}=+rz|~Eou_IhI921 ztZ3?gJ=Y7lIlUn@vgkEewsMJUw9?ZxM!D2A7V<qdMv6ylSEV=qRna}UC)`N7fF5#LC{tuqnk4f8LI=@b7)Rdds0}C8)*E2 zMoWs227E#_)3*Jrq)_QCh?W&Z(9)y^@)(6nktEruGB?TidX7dIaTi1)u-R;ou5Erp zX^SgH?O5HW=C05o>3AX#xOxdI-1jthSEz+aZVr3HwQDom_dvj^S?KpE5mMq%oE^nl z3hIuqGO{ZYgvmJb4z~cw^w0jQcQRXOIie!|;@-iwL%mNGN<_7Fi9I zWfhw3n)!iB%8HymRDM#m?#bXY^adw_2X^FP8r48JvZ{w^Xb1H%N^NK4A}84aJ0!Gy0}&C*G{cjvEyj~GUONzq$VU~% zc*HNOl`s-nrE22oW#H+~dZIy4ZuFXuF|GCo_I+5)goiK|)VPxA@W&;6;~mU%HXQxS zM1O|Ly^$>y1#VkpX@8ygOxz>g8Q@JH0m0~-z%O2SA1IVo79&L{l-7WS*{Y&h!oqB2 zQCDPP_E*D1bi0aXNzv^p!li0qrr0Od&!xuatJslheLWRBQnjP2S-GkmUCY*G8NG;L zFRfAS=vsC!v!na7epyZ}&awOJ>lI;i7Wp%Ji}3b~U|%PTbrH@lf_x>7xB|=@;Rb(>PyHL%&DT<)p$YLVO@p zpAUM|LpgYm(`w#GM>*A*2ww-No%XqQXXN{|)$dfSBRj@|p3^b=XQWYdocq^+aP{p7KcnKpK zNV^WTNve8O-wwGVu+%{>$dgR7ju(WB(yM`a4;qK+)hg9BeN@#Zp98{3QNA5Krv#Qz zRre&VnB#T@v=|LnilSiJQd8r)gaBE@s*H2o>*rm0p%$Y3e4APz{IsC0R?{!F9#=VI zE`a`5%q)~`^|bqByWGpuPnyTLCq|0j(>@2k(+EMq|NDuyIf!wnSB)3|PnZNdtFEZB zsH&*CsLT<>^6+DO*vjEkMx0bCDlMeGQ-n;!B1h`xqFkV%OkGXtyUE+s#gez9 zOKu*;%)Eox8Tj0hfoMYvjRP?>#Rc2CS_-yw&CT7>H7|F2*ZhL*T?-0!bhYJf>gved z+_ktUpK7N36v!G(>)DlM#LsLj$7t~DZ3VzetF$?Q^o0n4qVl4eB2;gI$GgnoEGZ9- zgrP_=J?c*A-zh5AZ-Uo$Gv?10_;R$q%rz2cjrE$-YLYT#6qO?@%;Yne7=q>K44D}^AK5mm}dwcON7Y_Cb=+)uRQG3vu-aUaqg70cZGKm2qR5vv{sclh^U5E}X(p$@HIR&# zE!WD#c@Vn-tuk1HM-i0sdpf&A z)5c65km_s>wFX)xi^w^KcN(s5zKgg@L_a!0QJya5y*R;l@@0Jpk69sya-8%4$4Lr7 zgQ9VDKHpgwsPjd&qk=WQ-jy6R6(*|lMRn%vHVuLH70FRtfm%P>ehr8A&+L4v`=y>A zij7qysa2`eigk7y>QLplja@-6cU;gfR@82!BJbtJBlT`X-0;F(VrUN^?4XBtchJL0 z7wF-Q?3y%G&bn|PZ}^veRFTJmJ`nZEiMOgPvn?P3aa=_XaY{!`im}vOVbZbcXeGIb z5-v+sw=LLqR^$+Vx0aDj*Qq0muGMB9@gE=*f^S{iybhh8gFHJJU!r#bYa+%d-GgS2 z7NMF49Nr*z0yIxConfoK&^cd*t!)}#cpb4r+BjP2b`(z)Zj?rdrR`Lc3YWq{pA)p8 z8Dr`Jja^&4!*Q&j%d|nD)b8IEF-%jT(LLGxj-of4@J-rc48?Z=EioGPNT|vXA$_FR z9Nw5-jMV~&D^cEbNWAG~8j^-~R~os5Xr%ov1S@8KkZK?|Qsi0H@fusMy$UNqMI5q` z;@(;1h+E$YtIllU5t(@0Y~dly|JlM!*`81DnDDu9tt}qjQClVI`QRw_U~8w02r?Xt z7AE1!IAH>g#0cLtZ&GZKt=_{gym@xcbKqqAOlnl44nDz5S=Aj?y)#BwOKlqU{ivqx zk9bQNxM~&J?S*z@g-Z}W5^7_JZM441YVQp^UQf>yj5Elpd!AY2>1v9g)HSND#t1(H zp*==8CF!9BQ9g*?0I zr~9`8_u#G2IMqPk$#bk-H%5$w))PAKRh@<;11&m_j<%;UH5(sbzHmMFkW_?9lSDhS z6qkGmIzGkb>@&WaxS#`D+jL0?IWN=#zi@x3bV2fr=JTh1XjMP-+>-rmtp|E;(*7;N zwc;oyy#;l|K7K!zo(pP-WA@u2Q{Y|T+vcWuLNo7DdSAeqf7z|#drfG5Pnqw&c0cY6 z$sdS$#;DG!&zdq;A9PQ~@$WE(ZpUAZqp7*3klU(4FkqeK`P~~zYrr{BB@uXjux6aE zyXfE%CC#lOepz28S731{8hkXd#?HYz@2H$AR2|oT#$^U-PK+dlx7H5N_)o? zJywMnTEx*7Af6VI8szQ3(G~6B+o_|Zl&u@IcEE>P6TIT#cCOH*G4;yxdlIzOUdZ=Z z>aaUh3i3h@tYtvo5@yS#)k(rEAa9=)?w8AfJGl@PnlIB6wxtg}8K_ZQ3gn_-e@h)S z&o!%Udp3oP#*Sx!9$91>=DNV_R^fEfxW?X)d3V0YscDKTEh9=4=!qmr`zw4f3!z$b zL`7j!t&W;Sk?c2`rIGAIngx;~4mHap*>7xq%OBZ?R1CHcB_nEz{~g`}_%s99db|Cz zCAraF^NnPc>=ctdBL+x%vxVK#(R%ttc&sX#n6?gUqo2lLd!vbsK+ybO(>eH7#=vIR z5!Krpe-}q*ihb6b**I|6i}mYbfdg7H?uI;?te9`YMRd*a~rPp_cuDDTa9Ybk-a8+sQm zIn?K;@y9e&QGQe23GbYf`NzoDNIs93q$`T}>47aZChle-nMDe!`x65Dsh9YLbE%i`I)>EN(t0@qvJlym=`50Z z?vfuv@7BpV_N|vmqF!0((97p`}6kKJUxkCVD_WJA7!wNghy9hJaBfUgSD+Jm`GVAi*{yhF^pd@bgIDu-NVI_0>=7@KX(S|hHwW$!gL~|s zax-Ey_D@NH)_VpR!6NRl7?KrPHwh_@Pe^H`>vRdpUMDgXny|t?Bz=h0a%RX`hY{ly zlq|f+GJ92gp7}x5@uy3O_AZ1>5-U<$eela9O@_yEfj?S}=DN1NH~90K4o=AzYbE%o zS>Mz?psKcH4{2qBbR{Bv=^4H=Pr`GNmo%xd9F-3a_tQxx_P3MtlGFkpXxkp%BOWp@ zZ`Xqu^nA7TVea<54zIKNzdf(v`QEuElj?!jo6=0o*EjP zrtw?yLqaQHvyyDos-=U)m9Ypg@^k7r^8Y6YtKG8$Yq=myYu?(%6Br`^ypQ<~EzEaU zLD|h_JI*V0e}(Ndv!2_^yo2OV+ye^{jf-z_T+1^9&Y?fkjBv`xuLm2IZ@&L|4bb3GwNw52p45J*bfNzeicB!(yaT;iGC7YXF0+K=y?e+Yqg%*)U%qWbq z|838s!_i4{RG-A>68UG}^@_tm>${3>{&yhmlsJzg*Cuq;)-p>I8o!rTZlr4MS_X3H z+%FTO0WaL6;-}17syEY` zt-h5a%bRXmv)M1ajSX)7diIO%>Rju-9gz{lRW!Q?jq505bduhW^CIAHC!ktDo=N(h zSHCVwd{)Xsi)rH1QmUw57cDNArUQdc56k*uM72LG>DR|$i!5aHEM|AFHc>VhW^;QyKwIUI0p-uuWYok{>N$g7!|6ym(sL?(+xlNrZ#aq2Vd zZ{DT^H33+!)R9fuRP^@BD6fha9LRD?5(-hXW45pmJrDAxpuDC>U4rHA^!$6#;>&KG zX(*dRuOZ7S4fKEor%tM~!NQut54E@97rOCUk!Pz2ZE{A#GkQ_pR$Mzby=xSK#U+ zfwT0UGfX#Ed-Ppkf1C#ySLmtQBSEeeu8^bZVgr;ArM8sVg%wSsL@i>mCi9BX|V=IS&N(#ds1zuB#Q^ke&s85{-Z; zZ=dE56?*?s-tpL?F%ab)jx8DiQQqm;(sQGPucTL~kFXA*GPcBbq9^Es`hYdkm3#Hd zTEsJ1C9c!`@J@Asjf|>i#WaqVx(sx~X7s2O)KqQ}C*vHQ(8a8t727yO!ms|6FEBOa zyb&VbiRNyWvM-MOC^w-O9na+g7WajD$m|1FiPmN9mp0zU3N}e^B1(g|nngTUF3T=j zC~EURIGgBgY59|HVw>K)o-<1H)KP-ayn~J45vT{0=DSy+v#%5Mhz@Ep-@)b>awGAV z&W>hh-{!xwfze#gsqcHZcm-(pN%M3?{Y~H0)=BU#;$Oim#&_J*7U@h^NOZ=A`bKvO zf8`xIogL4S0xT7sk+x7J9QW;p7DM^1dcQun_kjEK+$)%o%W&>I|6jeCdXVqPFAmLJ zN5vjEjqG_go84ArLdGxhCdn5@aYL15Z8LXL(c4h$6RKpad5!+r{84~Utu|Gd942}W zs!^hO1n6w-9Tc@AJCIi#h()p!c`xK$TE~1#IRW{h*+kJqt0ChAJxzar1f%|HMm@c! z!GGGyoaVZFfR_;~+y+U+B0MH%f)nJ(26&x%LxP<~UMJvDX__7L4cJt#)9?~~uM<%_=y#eZIok0$WnmT7JWHC#=^CkhZ_@xN z4YA&Ozc0sbqxVMsrWDVJ4!k!}sD0NAA5%1ZOt3Q}yOG0e)82I|{4=o4Bdgn9W3Q%Y zk&-gtkvLS$UwGGn2@K3%hi)6{f^0{9kR24`VT0E!_-`dNJ@wtR_1oCX|9ziLe}5G* z*wrt}XA?Th2q{P9Ikd{yY+tu)XL?;28SvDsa8DJ6FexV0d@E+j`Eo+IB|_s*WZk(~ z&kS;B7)MgaL8^HiYIlC5jCRj(e~rJMc4iw{Dm59$fr!1K!czgMo#K-}l4lBwFxNi7 z3~M{5>~-%4847=h5^G_rT3zmc6$4Kl{XZyaDZMO|Ex1NwVLHOf^li z{|+|0Jt0!Pn%Nqv8Eh6eVjWhkaQby|0ZHCr*#;1YzF%FTT~f=2~Sm zdI#z_NN%Qa=r)o4#62U8QHW|WhR$5A;vMNFZ@W_=vm8b|_vNChA*2b}em&{@`FUZD zL7T6^NIJS}dp;agaKc-i%A!855E7-Io1vG5=$@f|Aazv(4~6!x=f3dA3&YRhkMjsx zuI*J?4I?ei$yOaiU62QiP3nDw{T8b9h)%=Mvn>+@n8>%7eoWhv^Ga(q?$oc6vi1u`#>YSRtCgCbjC^WHPrf3Lwd67Y-GyV>HV`aVxdmH2Bv-NIM9QZ{_ zW2(_TCC=mC+tPYCb479s+R-p8PfEw?5%pW6$&N|H#r)ni-`K_2rC%2_;Yc%#21_~cOX$2u zS#%Z79C(y+V~t(leIQF=0;-uvmP2<@jkheK?f7%aS)fT5vyoi^M0sEjh0@_EQJWb} zQ-~UA!XHsf++L0mgZL%#E79{z#PiI;^Gw3?WWisnQD5I7^+({Dx`6uRT|*UZ@S5>r zGVn?grP8WGjJsGIi$**OZ6^tP@$ELANj^N9{ITo7{?WywS-b)E7;2B zV|sp+F~MI`;$_IN^wjaNSv8qzFh^A#Vois$6*Z=TZbvg3`LJx}uF5aP=u8skAV%VX z6{ui;yA$=8OY>I&8DpM2fK_T5EMJPe!3qA_6C>GbUnz~fK<$ZfEZ;}PN*n60J#j+^ zwI^C(x9Wx(^u(i|ZpV6ezTN7oI+7|&tKsiOtRrGYfQE+%m-19#(5AivB)m;P!rKfa zye&Y&+h)%PB3=Oy@oatx)P_2Cc~Pk9r*a?`B?9hdtB4i8K{bSeEnO@HKu|&zqdXv@ zbT8Y?G|5gB4u0 z*==Aev^I~m*{|pFZCHP+p&f^=!PQuQ!O!sSSsg*P23Knp`O0gm;9b_%-ztl(>O$*p zzmWA8t5FBG{8ToJZK(fPUSPxenj#;kwFvW@R^EQiyOhps<+a(=oCnn}?az7eV*yc4 zf|ln%KJ75SM(<8r z$&NLD7Ffw>J7}XoWyybQJ%fx^OfeWG`Hg5t8_nukwmW1kvmyG9*6<*%mZNy5yEpn2 zjIb!JAugrou1D+|%Q{2k4aMxyte~-8~2e*%x8{LrQ;vGPisy#c>}fJPF_B(=Y~ z4@&lGC-#Th)9j80XeGxW;~x^K`kS|Zse^2bYQ#>gd`h~+vz%ovVb#b#g>g#Sl)a!Y z+W8di?G_N_?$9g*s?L89I{$$%jeo27uG)4r%PT7n-r+N}|CKaBy#wZHlc`F2ALrW8 zc8u^R)YDbtMemi?g+z|o9pUX4ikpC>jA|<00;vmnb|s!XNyw2#xUqt>UOtFkCJ7Hn zgbunCXc&)Rj8BtLpSBtiztUB>dI3A*_t^g+@&@e4H)=B9g(pqL-^ZGFD=Q_vIfQ#L zL|Lq1xmd$c`ww_~sLBNFy?p&PtWMj33AV%L$O66~RzV9^!CYVp<^fwU9~grLz#6mx zbI<|oK^A*4RRZT{k?BE=1)RT43{<+P%?a{rkc6X2PkL@6xbamOh1$ps>REPBwbW6K zCulOK`&XfGS&qiT4#v$xV|K%>D!9V*7k18*m%YLCI+ffuIgR#aC`lhROy z$BD5|qdpf^Q!Jn?$+TgyW~yGL@^y8z|4Y8^V0_)C^7T@u#@BVte*<3!&I0(MpBpkO z$;ER+Eq{$-l~hgZKf%|rIv}PeoUfzTepJE^`Fb@yM}V*YkDugU@pUz#=>LqbJ77-- zUoQpvA&q5vcgcwDN|fw14b6MN*HMuRc#^dJKjZ79dzTh`iFUNv(GFinMZ|EvUTWFt zPDY;$0jw{-{gy^bBOSk?x>Hr+ovvNhqGj_w_ra)j6TE#-@ux^|1ekQLyJp!TxJ_ z9rT13!r^%1zlp=)HIEj1!q%T5_K+-yyGxh)2t5P3xk}k^?DC~|@2cPd@`})4Mi71Hu2aN~!dT@r+s^em%p}vQe z4Zd5IU+OhFkSsI}Gb;)+>(351Y?UO7koQ&d!T;oS71ZW@oa3rI?VF>l!PTKwW$jI3 z&IbMy5(}-iXMB$`KPvHo1^7^=sG93~mCvMPLEiJ;pJi;>tDHQ!_xMRYHz$wd6NIPd z#|zKQe>$EMp1JqwJDy2B>z#wFox*~Wg0h@dIp>6OGkKvd5uP(w=3FDJF<0fVToYvJ zJ8PWPn@z`y^Q-b}@~c;s*~-*x6g7t*(N1N+9kw~koX$dLVO3#yVVSeCu%fK85-W9K z!J4u)I8;_uR$f-N2BB1I%GaQFc)Yp0sizdfZ++~z<3z!UGO_qXaWGqmw9uy3$qaiI z@&dN!`f+IeRV#ATV^sGyS}28PQzEUBV&PAZgX|YC%xL~XnT3x*=ns9{SOa4W*dN(kPDc;1kGjX96OGu4MqAFBWO)49w!>MRD9*%o z4DBy2hSfopP=imRdIl0aao43JyUp%Oca^)^jXa(dAui30(E&M}<@O|sls{Gsv>=kV zSF+F6Tq%=6c?*45dEV>d{2vB zY|QK7u%<2R;3g?(;mHG|dx}bf;%? z(qzw0RP0%nG}`kZs`kVuU5E3o!Qa6i6RY0S&l80TKFLYH!?j&KnW%3She|&2NpaZE zdzOpW``%R^7jJ`?f04M|*I$`0-tNm%=86TrKP!)l&AuY#VX?dKZ^}dBKYX7kGsTs@ zx0L(DB;S+DbTQSpL%By>>YJk6B_8)}RPGS}=qpuzFIM^VRH12uIf|SBOUu zFLpWlu~o?sfAzhg^cLUq)hIp11HN%e58NXfz3!`|i9h*zD5>Il-)=<^H~KzRlF_4D zB|)_KUQlAOU9Lol3w@6(6bl(D%TMf_x_SN5b*COaGWFnJ`s_>ZG^h8SPx_{o%$<|f z^Tw~%_x_^dYQw_4cWg*%dO2gkoO@sIlF%usG5x)7A3NUq(iq<-OJBYJi)ZHi=ezeb0{>R!^{^5E2`l)B_Nrx65jJeG5#5WU)?mD<|wA+5P{y|IqvCqnT9ACS3 z$t$K0lsNsy6}N2L=pDUz+^0&zpN8FarmU}Z{k2cDj5;A)*0*Q>sdqluX?yz8pSO07 zxo*Yc!v*e_Yd*fe@$3io+k4D)-t?R??ym?6=~goB`B|O1bh{>fOP@uKvwuw(``SYX zfBp87F{`et9rDDN509JuS@{QJYuqn9S-9ijv1x18KAqS%X634*A1q&gb;Fw)2PQqE z{k2AdWlH0(9KS?ZI-e7k&F2Mu4)lYInuE1ZM{MM4~ClbW*4{PY}K}pC~`E{#fU zNXiJc%w-u9XWV2=n)bs1?K!lkR{2dgvol}KuM--(v3ihBV6-^Poxo&v=66FJaW}|s z&CuK1UQbkuPa1@|bvfb)d*g2p%q@5*k~-seJpS^YKB5yjpw6;OMW+RSojt@t{4I2L z6$_CyT3D4T7Utn^d1tW@=M|PEicVl7I4fhtLg2d=!aqc@3o0kq^IR09fdnb0rcjCo=gLfs;n*=QK9-L%aD05MmHxy;C&mnqUdGY?!Q3qFac&7WpPR$Y#pfYx zFXA4>-@*9I=jL&J0{^dzz70pr_!x1{eC)rAo6KF!UB`{Y|33b`kKouWTsIG`En?R` zxR%dd%jd7n}%hy7>8odFr0mD z@F+WynQ;T#ryf6S%FMWt{T_z%Gc&kOgH2bPt}+b*O7J1G$DZlfGkwUwLxaD^lkpe|d;-sLF;P61 z5Y2IY5;#tmh;ec$4)o%9OK*-d^uc(!3}dJ-$65Muyy0?=@6(^>bpyC_!U4#0t@u6) znYRTp@5$C*gafeH|BCNK54Pi?8nGSs8-5=%AICkZ?>g3R>NE8hy_!M&j6Hy@`>B7! z&_4y|8sIPGj&Vwgz)PrzFf&R#X8N_h#du^UkV~;O_4S9>On-T%`e)Ol9LKGsFT1*9 zR%&=+Vp}ef00|3zCK~`H^btV-s(J>`a^ZriL-0s zDyAgaw#V#F>ybU>#BEQ_cBSw7{KzNy%S^tpU&*sP#tk!nobY1uAEG|&J~=h*^E(>{ zUACiQ>FpCb_comz6P#*;bZTeQ~ve3FHWcJo4M(uC%+%3EPJB&e#@23o$q$_{dDpEzkJ+0DeCI= zg^zw-x^cLbanBD!|N6J?d8tSCZyQ;% z=gHQI^S}M_)@O!)RZ`F0_^IWEeAmv(l}pavQu^Ekj;nQ9YYjaAi7VO?mHjdQnJdl` zpS_EVt^L%x(-6b|-POs`Ir|GPrFO6NOM}2A)&9-;xgnX~<4Uw7WbfuBS9eQ~Y?-^H zcAvGu@H?(o?S8A<(3}6xb*ZIi_CL9_+J9KTF?8kYUEM6{+28VCx%8GU*j1E!Go;Om1ZDDeGy&wfs-65tiZEC%GGIf3^N*$l_aFH(PGXKF6PR zjk4U3{R?+}?a$UThU>U1Y7bkF7_Q`ha1F8y%s$E=a}Bl($!_MZuKm&KGhD@g@9Jl{ zJo_Lwp!Sfp$=(F)YG1OxXn2r&xORi}6~iO^ z%dR<=+1cy4xwU_>zG;}p|J60$V$Obxf8AxWJeK_i_h{{F)>jQV-16Ej)~$vo_zzr9 zS)R<^#_w?b(Xt}@Bkq~n53Sn`PxG5xODvCPzsD`Bec!s-u#{U=`;PTp!(#qz*FwvJ z?2VkU)@dy@+`+GM-D#PUUB*|q?zY^M{Tw&7cD1$Ka2H?gnqj#w`+4qx+O^gi!~NX! z+A8ax4fpbETz{}k%dX@LToWy~WEXO`*4nK$!zAwawZ+yF!|i;L>o&{eYzH^CHqZL3 uVI2P_*96P>?0i1gHQF*JdnK1$YqeSohN%Cqlf6y9UOgS#dgfGX>wf`!sY>Vo diff --git a/TL866_Updater/firmwareCS.bin b/TL866_Updater/firmwareCS.bin deleted file mode 100644 index ca728a3ac32baa1e63649b2695c104db5aadb418..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 131072 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 z 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 YwHOQ$|BV;*zi`f%Pe-?$In~ngKZt>V7XSbN diff --git a/TL866_Updater/hexwriter.cpp b/TL866_Updater/hexwriter.cpp deleted file mode 100644 index a8e23a3..0000000 --- a/TL866_Updater/hexwriter.cpp +++ /dev/null @@ -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 - -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 diff --git a/TL866_Updater/main.cpp b/TL866_Updater/main.cpp deleted file mode 100644 index 2ba619e..0000000 --- a/TL866_Updater/main.cpp +++ /dev/null @@ -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 -#include -//#include - - -int main(int argc, char *argv[]) -{ - //qDebug()< -#include -#include -#include -#include - - -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(""), 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(""), 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(""), false, false); - wait_ms(500); - emit update_gui(QString(""), 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>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(""), false, false); - wait_ms(500); - emit update_gui(QString(""), 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 "); - 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>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); -} diff --git a/TL866_Updater/mainwindow.h b/TL866_Updater/mainwindow.h deleted file mode 100644 index 0800718..0000000 --- a/TL866_Updater/mainwindow.h +++ /dev/null @@ -1,115 +0,0 @@ -#ifndef MAINWINDOW_H -#define MAINWINDOW_H - -#include - -#if QT_VERSION >= 0x050000 - #include -#else - #include -#endif -#include -#include -#include -#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 job_list; - QFutureWatcher 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 diff --git a/TL866_Updater/mainwindow.ui b/TL866_Updater/mainwindow.ui deleted file mode 100644 index cc81e56..0000000 --- a/TL866_Updater/mainwindow.ui +++ /dev/null @@ -1,820 +0,0 @@ - - - MainWindow - - - - 0 - 0 - 750 - 361 - - - - - 0 - 0 - - - - - 0 - 0 - - - - - 16777215 - 16777215 - - - - - - - - penDrive4.icopenDrive4.ico - - - - - - - - - 0 - 0 - 750 - 370 - - - - - 1 - 0 - - - - - Arial - 10 - 50 - false - - - - 0 - - - - false - - - Hardware - - - - - 157 - 305 - 568 - 12 - - - - 0 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - false - - - false - - - - - - 8 - 58 - 715 - 110 - - - - - Arial - 11 - 50 - false - - - - Firmware to write - - - - - 255 - 40 - 375 - 29 - - - - - 6 - - - QLayout::SetDefaultConstraint - - - 0 - - - - - - 10 - - - - Reflash - - - - - - - - 10 - - - - Reset - - - - - - - true - - - - 10 - - - - Dump - - - - - - - true - - - - 10 - - - - Advanced - - - - - - - - - 15 - 23 - 201 - 77 - - - - - - - - 10 - - - - TL866A firmware - - - true - - - - - - - - 10 - - - - TL866CS firmware - - - - - - - - 10 - - - - Firmware dumper - - - - - - - - - - 30 - 9 - 95 - 16 - - - - - Arial - 10 - 50 - false - - - - Update.dat file - - - - - - 8 - 174 - 717 - 115 - - - - - Courier New - 11 - - - - true - - - QTextEdit{color: black; background-color: rgb(255, 255, 225)}; - - - Qt::ScrollBarAlwaysOff - - - Qt::ScrollBarAlwaysOff - - - true - - - - - - 697 - 30 - 26 - 22 - - - - ... - - - - - - 14 - 305 - 29 - 12 - - - - true - - - QFrame::Box - - - - - - false - - - - - - 49 - 305 - 29 - 12 - - - - true - - - QFrame::Box - - - - - - false - - - - - - 84 - 305 - 29 - 12 - - - - true - - - QFrame::Box - - - - - - false - - - - - - 119 - 305 - 29 - 12 - - - - true - - - QFrame::Box - - - - - - false - - - - - - 15 - 292 - 32 - 13 - - - - - 8 - - - - Norm - - - - - - 51 - 292 - 30 - 13 - - - - - 8 - - - - Boot - - - - - - 85 - 292 - 32 - 13 - - - - - 8 - - - - Erase - - - - - - 121 - 292 - 32 - 13 - - - - - 8 - - - - Write - - - - - - 9 - 30 - 680 - 22 - - - - - 10 - - - - false - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - true - - - Qt::VisualMoveStyle - - - - - - 119 - 9 - 111 - 16 - - - - - Arial - 10 - 50 - false - - - - QLabel{color: green}; - - - <html><head/><body><p><br/></p></body></html> - - - - - - Firmware - - - - - 8 - 16 - 720 - 101 - - - - - Arial - 11 - 50 - false - - - - Device Serial number - - - - - 24 - 30 - 85 - 16 - - - - - 10 - - - - Device code - - - - - - 220 - 30 - 91 - 16 - - - - - 10 - - - - Serial number - - - - - - 135 - 49 - 324 - 29 - - - - - Courier New - 16 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 24 - - - true - - - - - - 9 - 49 - 117 - 29 - - - - - Courier New - 16 - 75 - true - - - - QLineEdit{color: black; background-color: rgb(255, 255, 225)}; - - - 8 - - - Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter - - - true - - - - - - 550 - 50 - 71 - 27 - - - - - 10 - - - - Clone - - - - - - 470 - 50 - 71 - 27 - - - - - 10 - - - - Edit - - - - - - 630 - 50 - 71 - 27 - - - - - 10 - - - - Default - - - - - - - 8 - 152 - 720 - 132 - - - - - Arial - 11 - 50 - false - - - - Hex file generator - - - - - 27 - 92 - 71 - 27 - - - - - 10 - - - - Save - - - - - - 15 - 26 - 141 - 54 - - - - - - - - Arial - 10 - 50 - false - - - - Full firmware - - - true - - - - - - - - 10 - - - - Bootloader only - - - - - - - - - 272 - 28 - 231 - 54 - - - - - - - - 10 - - - - Generate TL866A firmware - - - true - - - - - - - - 10 - - - - Generate TL866CS firmware - - - - - - - - - - - - - - diff --git a/TL866_Updater/notifier_linux.cpp b/TL866_Updater/notifier_linux.cpp deleted file mode 100644 index dd05807..0000000 --- a/TL866_Updater/notifier_linux.cpp +++ /dev/null @@ -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 -#include - -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."; -} diff --git a/TL866_Updater/notifier_linux.h b/TL866_Updater/notifier_linux.h deleted file mode 100644 index 022a55b..0000000 --- a/TL866_Updater/notifier_linux.h +++ /dev/null @@ -1,27 +0,0 @@ -#ifndef NOTIFIER_H -#define NOTIFIER_H - -#include -#include - -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 diff --git a/TL866_Updater/notifier_win.cpp b/TL866_Updater/notifier_win.cpp deleted file mode 100644 index 64bd341..0000000 --- a/TL866_Updater/notifier_win.cpp +++ /dev/null @@ -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 -#include -#include - -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(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 diff --git a/TL866_Updater/notifier_win.h b/TL866_Updater/notifier_win.h deleted file mode 100644 index 1528dd7..0000000 --- a/TL866_Updater/notifier_win.h +++ /dev/null @@ -1,31 +0,0 @@ -#ifndef NOTIFIER_H -#define NOTIFIER_H - -#include -#include - - -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 diff --git a/TL866_Updater/penDrive4.ico b/TL866_Updater/penDrive4.ico deleted file mode 100644 index e73eac33423a8402e9922669c47fc4ebd22987a3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 22534 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 diff --git a/TL866_Updater/resources.qrc b/TL866_Updater/resources.qrc deleted file mode 100644 index 25c85bd..0000000 --- a/TL866_Updater/resources.qrc +++ /dev/null @@ -1,7 +0,0 @@ - - - firmwareA.bin - firmwareCS.bin - dumper.bin - - diff --git a/TL866_Updater/tl866_global.h b/TL866_Updater/tl866_global.h deleted file mode 100644 index 4db5cba..0000000 --- a/TL866_Updater/tl866_global.h +++ /dev/null @@ -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 diff --git a/TL866_Updater/usb_linux.cpp b/TL866_Updater/usb_linux.cpp deleted file mode 100644 index 69137cc..0000000 --- a/TL866_Updater/usb_linux.cpp +++ /dev/null @@ -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 - -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; -} diff --git a/TL866_Updater/usb_linux.h b/TL866_Updater/usb_linux.h deleted file mode 100644 index cc2f68a..0000000 --- a/TL866_Updater/usb_linux.h +++ /dev/null @@ -1,29 +0,0 @@ -#ifndef USB_LINUX_H -#define USB_LINUX_H - -#include -#include -#include - -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 devices; - libusb_device **devs; -}; - -#endif // USB_LINUX_H diff --git a/TL866_Updater/usb_win.cpp b/TL866_Updater/usb_win.cpp deleted file mode 100644 index ae70ea5..0000000 --- a/TL866_Updater/usb_win.cpp +++ /dev/null @@ -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 -#include -#include - -#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); -} diff --git a/TL866_Updater/usb_win.h b/TL866_Updater/usb_win.h deleted file mode 100644 index bffdf31..0000000 --- a/TL866_Updater/usb_win.h +++ /dev/null @@ -1,25 +0,0 @@ -#ifndef USB_WIN_H -#define USB_WIN_H -#include -#include - -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 diff --git a/TL866_Updater/win_resources.rc b/TL866_Updater/win_resources.rc deleted file mode 100644 index 92a59b0..0000000 --- a/TL866_Updater/win_resources.rc +++ /dev/null @@ -1 +0,0 @@ -IDI_ICON1 ICON DISCARDABLE "penDrive4.ico" \ No newline at end of file