1 #include "process_flash.h"
2 #include "progresswidget.h"
6 #include "eeprominterface.h"
7 //#include "firmwareinterface.h"
9 #if defined WIN32 || !defined __GNUC__
13 #define sleep(x) Sleep(x*1000)
16 #include "mountlist.h"
19 FlashProcess::FlashProcess(const QString
&cmd
, const QStringList
&args
, ProgressWidget
*progress
):
23 process(new QProcess(this)),
33 connect(process
, SIGNAL(started()),this, SLOT(onStarted()));
34 connect(process
, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadyReadStandardOutput()));
35 connect(process
, SIGNAL(readyReadStandardError()), this, SLOT(onReadyReadStandardError()));
36 connect(process
, SIGNAL(finished(int)), this, SLOT(onFinished(int)));
39 FlashProcess::~FlashProcess()
46 bool FlashProcess::run()
48 if (!QFile::exists(cmd
)) {
49 QMessageBox::critical(NULL
, "Companion", tr("Executable %1 not found").arg(cmd
));
54 if (cmd
.toLower().contains("sam-ba")) {
55 killTimer
= new QTimer(this);
56 connect(killTimer
, SIGNAL(timeout()), this, SLOT(onKillTimerElapsed()));
57 killTimer
->start(2000);
62 connect(this, SIGNAL(finished()), &loop
, SLOT(quit()));
63 process
->start(cmd
, args
);
69 void FlashProcess::onStarted()
72 progress
->addText(cmd
+ " " + args
.join(" "));
73 progress
->addSeparator();
77 bool killProcessByName(const char *szProcessToKill
)
82 DWORD dwPriorityClass
;
84 hProcessSnap
= CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS
, 0); // Takes a snapshot of all the processes
86 if (hProcessSnap
== INVALID_HANDLE_VALUE
) {
90 pe32
.dwSize
= sizeof(PROCESSENTRY32
);
92 if (!Process32First(hProcessSnap
, &pe32
)) {
93 CloseHandle(hProcessSnap
);
98 if (!strcmp(pe32
.szExeFile
,szProcessToKill
)) { // checks if process at current position has the name of to be killed app
99 hProcess
= OpenProcess(PROCESS_TERMINATE
,0, pe32
.th32ProcessID
); // gets handle to process
100 TerminateProcess(hProcess
, 0); // Terminate process by handle
101 CloseHandle(hProcess
); // close the handle
103 } while (Process32Next(hProcessSnap
, &pe32
)); // gets next member of snapshot
105 CloseHandle(hProcessSnap
); // closes the snapshot handle
110 void FlashProcess::onKillTimerElapsed()
113 // trick to accelerate SAM-BA startup
114 killProcessByName("tasklist.exe");
118 void FlashProcess::analyseStandardOutput(const QString
&text
)
120 currStdoutLine
.append(text
);
121 if (currStdoutLine
.contains("size = ")) {
122 int pos
= currStdoutLine
.lastIndexOf("size = ");
123 QString temp
= currStdoutLine
.mid(pos
+7);
124 pos
= temp
.lastIndexOf("\n");
125 int size
= temp
.left(pos
).toInt();
126 progress
->setMaximum(size
/2048);
128 if (currStdoutLine
.contains("\n")) {
129 int nlPos
= currStdoutLine
.lastIndexOf("\n");
130 currStdoutLine
= currStdoutLine
.mid(nlPos
+1);
132 if (!currStdoutLine
.isEmpty()) {
133 if (currStdoutLine
.at(0) == QChar('.')) {
134 int pos
= currStdoutLine
.lastIndexOf(".");
135 progress
->setValue(pos
);
137 else if (currStdoutLine
.startsWith("Starting upload: [")) {
138 int pos
= (currStdoutLine
.lastIndexOf("#")-19)*100/256;
139 progress
->setValue(pos
);
143 if (text
.contains("Complete ")) {
148 int start
= text
.indexOf("Complete ");
149 int end
= text
.indexOf("%");
152 int value
= text
.mid(start
, end
-start
).toInt();
153 progress
->setValue(value
);
157 if (text
.contains(":010000")) {
158 // contains fuse info
159 QStringList stl
= text
.split(":01000000");
160 foreach (QString t
, stl
) {
162 if (!lfuse
) lfuse
= t
.left(2).toInt(&ok
, 16);
163 if (!hfuse
&& !ok
) hfuse
= t
.left(2).toInt(&ok
, 16);
164 if (!efuse
&& !ok
) efuse
= t
.left(2).toInt(&ok
, 16);
168 if (text
.contains("-E-")) {
173 void FlashProcess::analyseStandardError(const QString
&text
)
175 currStderrLine
.append(text
);
176 if (currStderrLine
.contains("#")) {
177 QString avrflashPhase
= currStderrLine
.left(1).toLower();
178 if (avrflashPhase
== "w") {
179 flashPhase
= WRITING
;
180 progress
->setInfo(tr("Writing..."));
181 progress
->setValue(2 * currStderrLine
.count("#"));
183 else if (avrflashPhase
== "r") {
184 if (flashPhase
== READING
) {
185 progress
->setInfo(tr("Reading..."));
188 flashPhase
= VERIFYING
;
189 progress
->setInfo(tr("Verifying..."));
191 progress
->setValue(2 * currStderrLine
.count("#"));
195 if (currStderrLine
.contains("\n")) {
196 int nlPos
= currStderrLine
.lastIndexOf("\n");
197 currStderrLine
= currStderrLine
.mid(nlPos
+1);
200 if ((text
.contains("-E-") && !text
.contains("-E- No receive file name")) ||
201 text
.contains("No DFU capable USB device found")) {
206 void FlashProcess::onReadyReadStandardOutput()
208 QString text
= QString(process
->readAllStandardOutput());
209 progress
->addText(text
);
210 analyseStandardOutput(text
);
213 void FlashProcess::onReadyReadStandardError()
215 QString text
= QString(process
->readAllStandardError());
216 progress
->addText(text
);
217 analyseStandardError(text
);
220 void FlashProcess::errorWizard()
222 QString output
= progress
->getText();
224 if (output
.contains("avrdude: Expected signature for")) { // wrong signature
225 int pos
= output
.indexOf("avrdude: Device signature = ");
226 bool fwexist
= false;
227 QString DeviceStr
= tr("unknown");
231 QString DeviceId
= output
.mid(pos
+28, 8);
232 if (DeviceId
=="0x1e9602") {
233 DeviceStr
= "Atmega 64";
234 FwStr
="\n" + tr("ie: OpenTX for 9X board or OpenTX for 9XR board");
237 else if (DeviceId
=="0x1e9702") {
238 DeviceStr
= "Atmega 128";
239 FwStr
="\n" + tr("ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip");
242 else if (DeviceId
=="0x1e9703") {
243 DeviceStr
= "Atmega 1280";
245 else if (DeviceId
=="0x1e9704") {
246 DeviceStr
= "Atmega 1281";
248 else if (DeviceId
=="0x1e9801") {
249 DeviceStr
= "Atmega 2560";
250 FwStr
="\n" + tr("ie: OpenTX for Gruvin9X board");
253 else if (DeviceId
=="0x1e9802") {
254 DeviceStr
= "Atmega 2561";
257 if (fwexist
==false) {
258 QMessageBox::warning(NULL
, "Companion - Tip of the day", tr("Your radio uses a %1 CPU!!!\n\nPlease check advanced burn options to set the correct cpu type.").arg(DeviceStr
));
261 Firmware
*firmware
= GetCurrentFirmware();
262 QMessageBox::warning(NULL
, "Companion - Tip of the day", tr("Your radio uses a %1 CPU!!!\n\nPlease select an appropriate firmware type to program it.").arg(DeviceStr
)+FwStr
+tr("\nYou are currently using:\n %1").arg(firmware
->getName()));
265 else if (output
.contains("No DFU capable USB device found")){
266 #if defined WIN32 || !defined __GNUC__
267 QMessageBox::warning(NULL
, "Companion - Tip of the day", tr("Your radio does not seem connected to USB or the driver is not installed!!!\n\nPlease use ZADIG to properly install the driver."));
269 QMessageBox::warning(NULL
, "Companion - Tip of the day", tr("Your radio does not seem connected to USB or the driver is not initialized!!!."));
274 void FlashProcess::onFinished(int code
=0)
276 progress
->addSeparator();
277 if (code
==1 && cmd
.toLower().contains("sam-ba")) {
281 progress
->setInfo(tr("Flashing done (exit code = %1)").arg(code
));
282 if (cmd
.toLower().contains("avrdude") || cmd
.toLower().contains("dfu")) {
286 else if (hasErrors
) {
287 progress
->setInfo(tr("Flashing done with errors"));
289 if (lfuse
|| hfuse
|| efuse
) {
292 progress
->setValue(progress
->maximum());
293 progress
->lock(false);
297 void FlashProcess::addReadFuses()
299 progress
->addSeparator();
300 progress
->addText(tr("FUSES: Low=%1 High=%2 Ext=%3").arg(lfuse
, 2, 16, QChar('0')).arg(hfuse
, 2, 16, QChar('0')).arg(efuse
, 2, 16, QChar('0')));
301 progress
->addSeparator();