removed PrefixPath debug line
[opentx.git] / companion / src / process_flash.cpp
bloba57c3c02c5d3e533d9ede244eb72ec949ab4a7df
1 #include "process_flash.h"
2 #include "progresswidget.h"
3 #include <QFile>
4 #include <QMessageBox>
5 #include <QProcess>
6 #include "eeprominterface.h"
7 //#include "firmwareinterface.h"
9 #if defined WIN32 || !defined __GNUC__
10 #include <Windows.h>
11 #include <WinBase.h>
12 #include <tlhelp32.h>
13 #define sleep(x) Sleep(x*1000)
14 #else
15 #include <unistd.h>
16 #include "mountlist.h"
17 #endif
19 FlashProcess::FlashProcess(const QString &cmd, const QStringList &args, ProgressWidget *progress):
20 progress(progress),
21 cmd(cmd),
22 args(args),
23 process(new QProcess(this)),
24 hasErrors(false),
25 lfuse(0),
26 hfuse(0),
27 efuse(0),
28 flashPhase(READING)
29 #if !__GNUC__
30 , killTimer(NULL)
31 #endif
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()
41 #if !__GNUC__
42 delete killTimer;
43 #endif
46 bool FlashProcess::run()
48 if (!QFile::exists(cmd)) {
49 QMessageBox::critical(NULL, "Companion", tr("Executable %1 not found").arg(cmd));
50 return false;
53 #if !__GNUC__
54 if (cmd.toLower().contains("sam-ba")) {
55 killTimer = new QTimer(this);
56 connect(killTimer, SIGNAL(timeout()), this, SLOT(onKillTimerElapsed()));
57 killTimer->start(2000);
59 #endif
61 QEventLoop loop;
62 connect(this, SIGNAL(finished()), &loop, SLOT(quit()));
63 process->start(cmd, args);
64 loop.exec();
66 return true;
69 void FlashProcess::onStarted()
71 progress->lock(true);
72 progress->addText(cmd + " " + args.join(" "));
73 progress->addSeparator();
76 # if !__GNUC__
77 bool killProcessByName(const char *szProcessToKill)
79 HANDLE hProcessSnap;
80 HANDLE hProcess;
81 PROCESSENTRY32 pe32;
82 DWORD dwPriorityClass;
84 hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Takes a snapshot of all the processes
86 if (hProcessSnap == INVALID_HANDLE_VALUE) {
87 return false;
90 pe32.dwSize = sizeof(PROCESSENTRY32);
92 if (!Process32First(hProcessSnap, &pe32)) {
93 CloseHandle(hProcessSnap);
94 return false;
97 do {
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
106 return true;
108 #endif
110 void FlashProcess::onKillTimerElapsed()
112 # if !__GNUC__
113 // trick to accelerate SAM-BA startup
114 killProcessByName("tasklist.exe");
115 #endif
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 ")) {
144 #if !__GNUC__
145 delete killTimer;
146 killTimer = NULL;
147 #endif
148 int start = text.indexOf("Complete ");
149 int end = text.indexOf("%");
150 if (start > 0) {
151 start += 9;
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) {
161 bool ok = false;
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-")) {
169 hasErrors = true;
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..."));
187 else {
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")) {
202 hasErrors = true;
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");
228 QString FwStr = "";
230 if (pos > 0) {
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");
235 fwexist = true;
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");
240 fwexist = true;
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");
251 fwexist = true;
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));
260 else {
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."));
268 #else
269 QMessageBox::warning(NULL, "Companion - Tip of the day", tr("Your radio does not seem connected to USB or the driver is not initialized!!!."));
270 #endif
274 void FlashProcess::onFinished(int code=0)
276 progress->addSeparator();
277 if (code==1 && cmd.toLower().contains("sam-ba")) {
278 code = 0;
280 if (code) {
281 progress->setInfo(tr("Flashing done (exit code = %1)").arg(code));
282 if (cmd.toLower().contains("avrdude") || cmd.toLower().contains("dfu")) {
283 errorWizard();
286 else if (hasErrors) {
287 progress->setInfo(tr("Flashing done with errors"));
289 if (lfuse || hfuse || efuse) {
290 addReadFuses();
292 progress->setValue(progress->maximum());
293 progress->lock(false);
294 emit finished();
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();