#include "process_flash.h" #include "progresswidget.h" #include #include #include #include "eeprominterface.h" //#include "firmwareinterface.h" #if defined WIN32 || !defined __GNUC__ #include #include #include #define sleep(x) Sleep(x*1000) #else #include #include "mountlist.h" #endif FlashProcess::FlashProcess(const QString &cmd, const QStringList &args, ProgressWidget *progress): progress(progress), cmd(cmd), args(args), process(new QProcess(this)), hasErrors(false), lfuse(0), hfuse(0), efuse(0), flashPhase(READING) #if !__GNUC__ , killTimer(NULL) #endif { connect(process, SIGNAL(started()),this, SLOT(onStarted())); connect(process, SIGNAL(readyReadStandardOutput()), this, SLOT(onReadyReadStandardOutput())); connect(process, SIGNAL(readyReadStandardError()), this, SLOT(onReadyReadStandardError())); connect(process, SIGNAL(finished(int)), this, SLOT(onFinished(int))); } FlashProcess::~FlashProcess() { #if !__GNUC__ delete killTimer; #endif } bool FlashProcess::run() { if (!QFile::exists(cmd)) { QMessageBox::critical(NULL, "Companion", tr("Executable %1 not found").arg(cmd)); return false; } #if !__GNUC__ if (cmd.toLower().contains("sam-ba")) { killTimer = new QTimer(this); connect(killTimer, SIGNAL(timeout()), this, SLOT(onKillTimerElapsed())); killTimer->start(2000); } #endif QEventLoop loop; connect(this, SIGNAL(finished()), &loop, SLOT(quit())); process->start(cmd, args); loop.exec(); return true; } void FlashProcess::onStarted() { progress->lock(true); progress->addText(cmd + " " + args.join(" ")); progress->addSeparator(); } # if !__GNUC__ bool killProcessByName(const char *szProcessToKill) { HANDLE hProcessSnap; HANDLE hProcess; PROCESSENTRY32 pe32; DWORD dwPriorityClass; hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0); // Takes a snapshot of all the processes if (hProcessSnap == INVALID_HANDLE_VALUE) { return false; } pe32.dwSize = sizeof(PROCESSENTRY32); if (!Process32First(hProcessSnap, &pe32)) { CloseHandle(hProcessSnap); return false; } do { if (!strcmp(pe32.szExeFile,szProcessToKill)) { // checks if process at current position has the name of to be killed app hProcess = OpenProcess(PROCESS_TERMINATE,0, pe32.th32ProcessID); // gets handle to process TerminateProcess(hProcess, 0); // Terminate process by handle CloseHandle(hProcess); // close the handle } } while (Process32Next(hProcessSnap, &pe32)); // gets next member of snapshot CloseHandle(hProcessSnap); // closes the snapshot handle return true; } #endif void FlashProcess::onKillTimerElapsed() { # if !__GNUC__ // trick to accelerate SAM-BA startup killProcessByName("tasklist.exe"); #endif } void FlashProcess::analyseStandardOutput(const QString &text) { currStdoutLine.append(text); if (currStdoutLine.contains("size = ")) { int pos = currStdoutLine.lastIndexOf("size = "); QString temp = currStdoutLine.mid(pos+7); pos = temp.lastIndexOf("\n"); int size = temp.left(pos).toInt(); progress->setMaximum(size/2048); } if (currStdoutLine.contains("\n")) { int nlPos = currStdoutLine.lastIndexOf("\n"); currStdoutLine = currStdoutLine.mid(nlPos+1); } if (!currStdoutLine.isEmpty()) { if (currStdoutLine.at(0) == QChar('.')) { int pos = currStdoutLine.lastIndexOf("."); progress->setValue(pos); } else if (currStdoutLine.startsWith("Starting upload: [")) { int pos = (currStdoutLine.lastIndexOf("#")-19)*100/256; progress->setValue(pos); } } if (text.contains("Complete ")) { #if !__GNUC__ delete killTimer; killTimer = NULL; #endif int start = text.indexOf("Complete "); int end = text.indexOf("%"); if (start > 0) { start += 9; int value = text.mid(start, end-start).toInt(); progress->setValue(value); } } if (text.contains(":010000")) { // contains fuse info QStringList stl = text.split(":01000000"); foreach (QString t, stl) { bool ok = false; if (!lfuse) lfuse = t.left(2).toInt(&ok, 16); if (!hfuse && !ok) hfuse = t.left(2).toInt(&ok, 16); if (!efuse && !ok) efuse = t.left(2).toInt(&ok, 16); } } if (text.contains("-E-")) { hasErrors = true; } } void FlashProcess::analyseStandardError(const QString &text) { currStderrLine.append(text); if (currStderrLine.contains("#")) { QString avrflashPhase = currStderrLine.left(1).toLower(); if (avrflashPhase == "w") { flashPhase = WRITING; progress->setInfo(tr("Writing...")); progress->setValue(2 * currStderrLine.count("#")); } else if (avrflashPhase == "r") { if (flashPhase == READING) { progress->setInfo(tr("Reading...")); } else { flashPhase = VERIFYING; progress->setInfo(tr("Verifying...")); } progress->setValue(2 * currStderrLine.count("#")); } } if (currStderrLine.contains("\n")) { int nlPos = currStderrLine.lastIndexOf("\n"); currStderrLine = currStderrLine.mid(nlPos+1); } if (text.contains("-E-") && !text.contains("-E- No receive file name")) { hasErrors = true; } if (text.contains("No DFU capable USB device found")) { hasErrors = true; } } void FlashProcess::onReadyReadStandardOutput() { QString text = QString(process->readAllStandardOutput()); progress->addText(text); analyseStandardOutput(text); } void FlashProcess::onReadyReadStandardError() { QString text = QString(process->readAllStandardError()); progress->addText(text); analyseStandardError(text); } void FlashProcess::errorWizard() { QString output=progress->getText(); // TODO = ui->plainTextEdit->toPlainText(); if (output.contains("avrdude: Expected signature for")) { // wrong signature int pos=output.indexOf("avrdude: Device signature = "); bool fwexist=false; QString DeviceStr="Unknown"; QString FwStr=""; if (pos>0) { QString DeviceId=output.mid(pos+28,8); if (DeviceId=="0x1e9602") { DeviceStr="Atmega 64"; FwStr="\n"+tr("ie: OpenTX for 9X board or OpenTX for 9XR board"); fwexist=true; } else if (DeviceId=="0x1e9702") { DeviceStr="Atmega 128"; FwStr="\n"+tr("ie: OpenTX for M128 / 9X board or OpenTX for 9XR board with M128 chip"); fwexist=true; } else if (DeviceId=="0x1e9703") { DeviceStr="Atmega 1280"; } else if (DeviceId=="0x1e9704") { DeviceStr="Atmega 1281"; } else if (DeviceId=="0x1e9801") { DeviceStr="Atmega 2560"; FwStr="\n"+tr("ie: OpenTX for Gruvin9X board"); fwexist = true; } else if (DeviceId=="0x1e9802") { DeviceStr="Atmega 2561"; } } if (fwexist==false) { 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)); } else { Firmware *firmware = GetCurrentFirmware(); 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())); } } else if (output.contains("No DFU capable USB device found")){ #if defined WIN32 || !defined __GNUC__ 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.")); #else QMessageBox::warning(NULL, "Companion - Tip of the day", tr("Your radio does not seem connected to USB or the driver is not initialized!!!.")); #endif } } void FlashProcess::onFinished(int code=0) { progress->addSeparator(); if (code==1 && cmd.toLower().contains("sam-ba")) { code = 0; } if (code) { progress->setInfo(tr("Flashing done (exit code = %1)").arg(code)); if (cmd.toLower().contains("avrdude") || cmd.toLower().contains("dfu")) { errorWizard(); } } else if (hasErrors) { progress->setInfo(tr("Flashing done with errors")); } if (lfuse || hfuse || efuse) { addReadFuses(); } progress->setValue(progress->maximum()); progress->lock(false); emit finished(); } void FlashProcess::addReadFuses() { progress->addSeparator(); 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'))); progress->addSeparator(); }