#include "pm3process.h" PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent) { moveToThread(thread); setProcessChannelMode(PM3Process::MergedChannels); isRequiringOutput = false; requiredOutput = new QString(); serialListener = new QTimer(); // if using new QTimer(this), the debug output will show "Cannot create children for a parent that is in a different thread." serialListener->moveToThread(this->thread());// I've tried many ways to creat a QTimer instance, but all of the instances are in the main thread(UI thread), so I have to move it manually serialListener->setInterval(1000); serialListener->setTimerType(Qt::VeryCoarseTimer); connect(serialListener, &QTimer::timeout, this, &PM3Process::onTimeout); connect(this, &PM3Process::readyRead, this, &PM3Process::onReadyRead); } void PM3Process::connectPM3(const QString path, const QString port) { QString result; Util::ClientType clientType = Util::CLIENTTYPE_OFFICIAL; setRequiringOutput(true); // using "-f" option to make the client output flushed after every print. start(path, QStringList() << port << "-f", QProcess::Unbuffered | QProcess::ReadWrite); if(waitForStarted(10000)) { waitForReadyRead(1000); setRequiringOutput(false); result = *requiredOutput; if(result.indexOf("[=]") != -1) { clientType = Util::CLIENTTYPE_ICEMAN; setRequiringOutput(true); write("hw version\r\n"); waitForReadyRead(1000); result = *requiredOutput; setRequiringOutput(false); } if(result.indexOf("os: ") != -1) // make sure the PM3 is connected { emit changeClientType(clientType); result = result.mid(result.indexOf("os: ")); result = result.left(result.indexOf("\r\n")); result = result.mid(3, result.lastIndexOf(" ") - 3); emit PM3StatedChanged(true, result); setSerialListener(port, true); } else kill(); } } void PM3Process::setRequiringOutput(bool st) { isRequiringOutput = st; if(isRequiringOutput) requiredOutput->clear(); } bool PM3Process::waitForReadyRead(int msecs) { return QProcess::waitForReadyRead(msecs); } void PM3Process::setSerialListener(const QString& name, bool state) { if(state) { portInfo = new QSerialPortInfo(name); serialListener->start(); qDebug() << serialListener->thread(); } else { serialListener->stop(); delete portInfo; } } void PM3Process::onTimeout() //when the proxmark3 client is unexpectedly terminated or the PM3 hardware is removed, the isBusy() will return false(only tested on Windows); { // qDebug()<isBusy(); if(!portInfo->isBusy()) { kill(); emit PM3StatedChanged(false); setSerialListener("", false); } } void PM3Process::testThread() { qDebug() << "PM3:" << QThread::currentThread(); } qint64 PM3Process::write(QString data) { return QProcess::write(data.toLatin1()); } void PM3Process::onReadyRead() { QString out = readAll(); if(isRequiringOutput) requiredOutput->append(out); if(out != "") { // qDebug() << "PM3Process::onReadyRead:" << out; emit newOutput(out); } }