Refactor the basic connect function(using QThread)

pull/2/head
wh201906 4 years ago
parent 80a8db540f
commit 6b8e98b735

@ -6,17 +6,27 @@ MainWindow::MainWindow(QWidget *parent)
, ui(new Ui::MainWindow) , ui(new Ui::MainWindow)
{ {
ui->setupUi(this); ui->setupUi(this);
pm3 = new PM3Process;
pm3Thread=new QThread(this);
pm3 = new PM3Process(pm3Thread);
// pm3->moveToThread(pm3Thread);
// pm3->init();
pm3Thread->start();
pm3state=false;
mifare = new Mifare; mifare = new Mifare;
connect(pm3, &PM3Process::readyRead, this, &MainWindow::refresh);
connect(pm3, &PM3Process::PM3disconnected, this, &MainWindow::onPM3disconnected);
connect(ui->Raw_CMDEdit, &QLineEdit::editingFinished, this, &MainWindow::sendMSG);
uiInit(); uiInit();
signalInit();
} }
MainWindow::~MainWindow() MainWindow::~MainWindow()
{ {
delete ui; delete ui;
pm3Thread->exit(0);
pm3Thread->wait(5000);
delete pm3;
delete pm3Thread;
} }
// ******************** basic functions ******************** // ******************** basic functions ********************
@ -25,7 +35,20 @@ void MainWindow::on_PM3_refreshPortButton_clicked()
{ {
ui->PM3_portBox->clear(); ui->PM3_portBox->clear();
ui->PM3_portBox->addItem(""); ui->PM3_portBox->addItem("");
foreach(QString port, pm3->findPort()) QSerialPort serial;
QStringList serialList;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
qDebug()<<info.isBusy()<<info.isNull()<<info.portName();
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
serialList<<info.portName();
serial.close();
}
}
foreach(QString port, serialList)
{ {
ui->PM3_portBox->addItem(port); ui->PM3_portBox->addItem(port);
} }
@ -33,36 +56,36 @@ void MainWindow::on_PM3_refreshPortButton_clicked()
void MainWindow::on_PM3_connectButton_clicked() void MainWindow::on_PM3_connectButton_clicked()
{ {
qDebug()<<"Main:"<<QThread::currentThread();
QString port = ui->PM3_portBox->currentText(); QString port = ui->PM3_portBox->currentText();
if(port == "") if(port == "")
QMessageBox::information(NULL, "Info", "Plz choose a port first", QMessageBox::Ok); QMessageBox::information(NULL, "Info", "Plz choose a port first", QMessageBox::Ok);
else else
{ {
pm3->setRequiringOutput(true); emit requiringOutput(true);
if(pm3->start(ui->PM3_pathEdit->text(), port)) emit connectPM3(ui->PM3_pathEdit->text(), port);
{
while(pm3->waitForReadyRead())
;
QString result = pm3->getRequiredOutput();
pm3->setRequiringOutput(false);
result = result.mid(result.indexOf("os: "));
result = result.left(result.indexOf("\r\n"));
result = result.mid(3, result.lastIndexOf(" ") - 3);
setStatusBar(PM3VersionBar, result);
setStatusBar(connectStatusBar,"Connected");
}
} }
} }
void MainWindow::on_PM3_disconnectButton_clicked() void MainWindow::onPM3StateChanged(bool st, QString info)
{ {
pm3->kill(); pm3state=st;
pm3->setSerialListener("",false); if(st==true)
onPM3disconnected(); {
setStatusBar(PM3VersionBar,info);
setStatusBar(connectStatusBar,"Connected");
}
else
{
setStatusBar(connectStatusBar,"Not Connected");
}
} }
void MainWindow::onPM3disconnected() void MainWindow::on_PM3_disconnectButton_clicked()
{ {
pm3state=false;
emit killPM3();
emit setSerialListener("", false);
setStatusBar(connectStatusBar,"Not Connected"); setStatusBar(connectStatusBar,"Not Connected");
} }
@ -179,8 +202,8 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
{ {
QApplication::processEvents(); QApplication::processEvents();
result = ""; result = "";
isKeyAValid=false; isKeyAValid = false;
isKeyBValid=false; isKeyBValid = false;
// check keys and read the first block of each sector // check keys and read the first block of each sector
if(ui->MF_keyWidget->item(i, 1) != nullptr && MF_isKeyValid(ui->MF_keyWidget->item(i, 1)->text())) if(ui->MF_keyWidget->item(i, 1) != nullptr && MF_isKeyValid(ui->MF_keyWidget->item(i, 1)->text()))
@ -191,7 +214,7 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
+ ui->MF_keyWidget->item(i, 1)->text(), waitTime); + ui->MF_keyWidget->item(i, 1)->text(), waitTime);
if(result.indexOf("isOk:01") != -1) if(result.indexOf("isOk:01") != -1)
{ {
isKeyAValid=true; isKeyAValid = true;
ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper())); ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper()));
} }
} }
@ -204,7 +227,7 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
+ ui->MF_keyWidget->item(i, 2)->text(), waitTime); + ui->MF_keyWidget->item(i, 2)->text(), waitTime);
if(result.indexOf("isOk:01") != -1) if(result.indexOf("isOk:01") != -1)
{ {
isKeyBValid=true; isKeyBValid = true;
ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper())); ui->MF_dataWidget->setItem(4 * i, 2, new QTableWidgetItem(result.mid(result.indexOf("isOk:01") + 13, 47).toUpper()));
} }
} }
@ -221,7 +244,7 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
+ (isKeyAValid ? "A" : "B") + (isKeyAValid ? "A" : "B")
+ " " + " "
+ ui->MF_keyWidget->item(i, (isKeyAValid ? 1 : 2))->text(), waitTime); + ui->MF_keyWidget->item(i, (isKeyAValid ? 1 : 2))->text(), waitTime);
result=result.mid(result.indexOf("isOk:01") + 13, 47).toUpper(); result = result.mid(result.indexOf("isOk:01") + 13, 47).toUpper();
ui->MF_dataWidget->setItem(4 * i + j, 2, new QTableWidgetItem(result)); ui->MF_dataWidget->setItem(4 * i + j, 2, new QTableWidgetItem(result));
} }
@ -233,12 +256,12 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
// //
// the structure is not symmetric, since you cannot get KeyA from output // the structure is not symmetric, since you cannot get KeyA from output
// this program will only process the provided KeyA(in MF_keyWidget) // this program will only process the provided KeyA(in MF_keyWidget)
result=ui->MF_dataWidget->item(4 * i + 3, 2)->text(); result = ui->MF_dataWidget->item(4 * i + 3, 2)->text();
if(isKeyAValid) if(isKeyAValid)
{ {
for(int j = 0; j < 6; j++) for(int j = 0; j < 6; j++)
{ {
result = result.replace(j * 3, 2, ui->MF_keyWidget->item(i,1)->text().mid(j * 2, 2)); result = result.replace(j * 3, 2, ui->MF_keyWidget->item(i, 1)->text().mid(j * 2, 2));
} }
} }
else else
@ -251,24 +274,24 @@ void MainWindow::on_MF_RW_readAllButton_clicked()
{ {
for(int j = 0; j < 6; j++) for(int j = 0; j < 6; j++)
{ {
result = result.replace(30 + j * 3, 2, ui->MF_keyWidget->item(i,2)->text().mid(j * 2, 2)); result = result.replace(30 + j * 3, 2, ui->MF_keyWidget->item(i, 2)->text().mid(j * 2, 2));
ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result)); ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result));
} }
} }
else else
{ {
QString tmpKey=result.right(18).replace(" ",""); QString tmpKey = result.right(18).replace(" ", "");
result = execCMDWithOutput("hf mf rdbl " result = execCMDWithOutput("hf mf rdbl "
+ QString::number(4 * i + 3) + QString::number(4 * i + 3)
+ " B " + " B "
+ tmpKey, waitTime); + tmpKey, waitTime);
if(result.indexOf("isOk:01") != -1) if(result.indexOf("isOk:01") != -1)
{ {
ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem(tmpKey)); ui->MF_keyWidget->setItem(i, 2, new QTableWidgetItem(tmpKey));
} }
else else
{ {
result=ui->MF_dataWidget->item(4 * i + 3, 2)->text(); result = ui->MF_dataWidget->item(4 * i + 3, 2)->text();
result = result.replace(30, 17, "?? ?? ?? ?? ?? ??"); result = result.replace(30, 17, "?? ?? ?? ?? ?? ??");
ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result)); ui->MF_dataWidget->setItem(4 * i + 3, 2, new QTableWidgetItem(result));
} }
@ -298,14 +321,14 @@ void MainWindow::on_MF_RW_readBlockButton_clicked()
result = result.replace(i * 3, 2, ui->MF_RW_keyEdit->text().mid(i * 2, 2)); result = result.replace(i * 3, 2, ui->MF_RW_keyEdit->text().mid(i * 2, 2));
} }
ui->MF_RW_dataEdit->setText(result); ui->MF_RW_dataEdit->setText(result);
QString tmpKey=result.right(18).replace(" ",""); QString tmpKey = result.right(18).replace(" ", "");
result = execCMDWithOutput("hf mf rdbl " result = execCMDWithOutput("hf mf rdbl "
+ ui->MF_RW_keyTypeBox->currentText() + ui->MF_RW_keyTypeBox->currentText()
+ " B " + " B "
+ tmpKey); + tmpKey);
if(result.indexOf("isOk:01") == -1) if(result.indexOf("isOk:01") == -1)
{ {
result= ui->MF_RW_dataEdit->text(); result = ui->MF_RW_dataEdit->text();
result = result.replace(30, 17, "?? ?? ?? ?? ?? ??"); result = result.replace(30, 17, "?? ?? ?? ?? ?? ??");
ui->MF_RW_dataEdit->setText(result); ui->MF_RW_dataEdit->setText(result);
} }
@ -340,6 +363,32 @@ void MainWindow::on_MF_RW_writeBlockButton_clicked()
} }
} }
void MainWindow::on_MF_RW_writeAllButton_clicked()
{
QString result;
for(int i = 0; i < 16; i++)
{
for(int j = 0; j < 4; j++)
{
result = execCMDWithOutput("hf mf wrbl "
+ QString::number(i * 4 + j)
+ " A "
+ ui->MF_keyWidget->item(i, 1)->text()
+ " "
+ ui->MF_dataWidget->item(2, i * 4 + j)->text().replace(" ", ""));
if(result.indexOf("isOk:01") == -1)
{
result = execCMDWithOutput("hf mf wrbl "
+ QString::number(i * 4 + j)
+ " B "
+ ui->MF_keyWidget->item(i, 2)->text()
+ " "
+ ui->MF_dataWidget->item(2, i * 4 + j)->text().replace(" ", ""));
}
}
}
}
// ************************************************ // ************************************************
@ -365,6 +414,8 @@ void MainWindow::sendMSG()
void MainWindow::uiInit() void MainWindow::uiInit()
{ {
connect(ui->Raw_CMDEdit, &QLineEdit::editingFinished, this, &MainWindow::sendMSG);
connectStatusBar = new QLabel(this); connectStatusBar = new QLabel(this);
programStatusBar = new QLabel(this); programStatusBar = new QLabel(this);
PM3VersionBar = new QLabel(this); PM3VersionBar = new QLabel(this);
@ -401,7 +452,7 @@ void MainWindow::uiInit()
ui->MF_keyWidget->setColumnWidth(1, 200); ui->MF_keyWidget->setColumnWidth(1, 200);
ui->MF_keyWidget->setColumnWidth(2, 200); ui->MF_keyWidget->setColumnWidth(2, 200);
for(int i=0;i<64;i++) for(int i = 0; i < 64; i++)
{ {
ui->MF_RW_blockBox->addItem(QString::number(i)); ui->MF_RW_blockBox->addItem(QString::number(i));
ui->MF_UID_blockBox->addItem(QString::number(i)); ui->MF_UID_blockBox->addItem(QString::number(i));
@ -411,6 +462,16 @@ void MainWindow::uiInit()
on_PM3_refreshPortButton_clicked(); on_PM3_refreshPortButton_clicked();
} }
void MainWindow::signalInit()
{
connect(pm3, &PM3Process::readyRead, this, &MainWindow::refresh);
connect(this,&MainWindow::requiringOutput,pm3,&PM3Process::setRequiringOutput);
connect(this,&MainWindow::connectPM3,pm3,&PM3Process::connectPM3);
connect(pm3, &PM3Process::PM3StatedChanged, this, &MainWindow::onPM3StateChanged);
connect(this,&MainWindow::killPM3,pm3,&PM3Process::kill);
}
void MainWindow::setStatusBar(QLabel* target, const QString & text) void MainWindow::setStatusBar(QLabel* target, const QString & text)
{ {
if(target == PM3VersionBar) if(target == PM3VersionBar)
@ -452,3 +513,5 @@ bool MainWindow::MF_isKeyValid(const QString key)
} }
// *********************************************** // ***********************************************

@ -2,10 +2,14 @@
#define MAINWINDOW_H #define MAINWINDOW_H
#include <QMainWindow> #include <QMainWindow>
#include <QThread>
#include <QProcess> #include <QProcess>
#include <QDebug> #include <QDebug>
#include <QMessageBox> #include <QMessageBox>
#include <QListWidgetItem> #include <QListWidgetItem>
#include <QtSerialPort/QSerialPortInfo>
#include <QtSerialPort/QSerialPort>
#include "pm3process.h" #include "pm3process.h"
#include "mifare.h" #include "mifare.h"
#include "mf_attack_hardnesteddialog.h" #include "mf_attack_hardnesteddialog.h"
@ -28,7 +32,7 @@ public slots:
void refresh(); void refresh();
void setStatusBar(QLabel* target,const QString & text); void setStatusBar(QLabel* target,const QString & text);
void execCMD(QString cmd, bool gotoRawTab); void execCMD(QString cmd, bool gotoRawTab);
void onPM3disconnected(); void onPM3StateChanged(bool st, QString info);
private slots: private slots:
void on_PM3_connectButton_clicked(); void on_PM3_connectButton_clicked();
@ -66,13 +70,23 @@ private slots:
void on_MF_Attack_infoButton_clicked(); void on_MF_Attack_infoButton_clicked();
void on_MF_RW_writeAllButton_clicked();
private: private:
Ui::MainWindow *ui; Ui::MainWindow *ui;
PM3Process* pm3; PM3Process* pm3;
bool pm3state;
QThread* pm3Thread;
Mifare* mifare; Mifare* mifare;
void uiInit(); void uiInit();
QLabel* connectStatusBar; QLabel* connectStatusBar;
QLabel* programStatusBar; QLabel* programStatusBar;
QLabel* PM3VersionBar; QLabel* PM3VersionBar;
void signalInit();
signals:
void requiringOutput(bool st);
void connectPM3(const QString path, const QString port);
void killPM3();
void setSerialListener(const QString &name, bool state);
}; };
#endif // MAINWINDOW_H #endif // MAINWINDOW_H

@ -1,46 +1,40 @@
#include "pm3process.h" #include "pm3process.h"
PM3Process::PM3Process(QObject* parent): QProcess(parent) PM3Process::PM3Process(QThread* thread, QObject* parent): QProcess(parent)
{ {
moveToThread(thread);
setProcessChannelMode(PM3Process::MergedChannels); setProcessChannelMode(PM3Process::MergedChannels);
isRequiringOutput=false; isRequiringOutput=false;
requiredOutput=new QString(); requiredOutput=new QString();
serialListener=new QTimer(this); 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->setInterval(1000);
serialListener->setTimerType(Qt::VeryCoarseTimer); serialListener->setTimerType(Qt::VeryCoarseTimer);
connect(serialListener,&QTimer::timeout,this,&PM3Process::onTimeout); connect(serialListener,&QTimer::timeout,this,&PM3Process::onTimeout);
} }
QStringList PM3Process::findPort() void PM3Process::connectPM3(const QString path, const QString port)
{ {
QSerialPort serial; setRequiringOutput(true);
QStringList retList;
foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
{
qDebug()<<info.isBusy()<<info.isNull()<<info.portName();
serial.setPort(info);
if(serial.open(QIODevice::ReadWrite))
{
retList<<info.portName();
serial.close();
}
}
return retList;
}
bool PM3Process::start(const QString path, const QString port)
{
// using "-f" option to make the client output flushed after every print. // using "-f" option to make the client output flushed after every print.
QProcess::start(path, QStringList()<<port<<"-f",QProcess::Unbuffered|QProcess::ReadWrite); start(path, QStringList()<<port<<"-f",QProcess::Unbuffered|QProcess::ReadWrite);
if(waitForStarted()) if(waitForStarted(10000))
{ {
setSerialListener(port,true); while(waitForReadyRead(1000))
return true; ;
} setRequiringOutput(false);
else QString result = *requiredOutput;
{ if(result.indexOf("os: ")!=-1)// make sure the PM3 is connected
return false; {
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();
} }
} }
@ -74,6 +68,7 @@ void PM3Process::setSerialListener(const QString& name,bool state)
{ {
portInfo=new QSerialPortInfo(name); portInfo=new QSerialPortInfo(name);
serialListener->start(); serialListener->start();
qDebug()<<serialListener->thread();
} }
else else
{ {
@ -87,7 +82,13 @@ void PM3Process::onTimeout()
qDebug()<<portInfo->isBusy(); qDebug()<<portInfo->isBusy();
if(!portInfo->isBusy()) if(!portInfo->isBusy())
{ {
emit PM3disconnected(); kill();
emit PM3StatedChanged(false);
setSerialListener("",false); setSerialListener("",false);
} }
} }
void PM3Process::testThread()
{
qDebug()<<"PM3:"<<QThread::currentThread();
}

@ -2,6 +2,7 @@
#define PM3PROCESS_H #define PM3PROCESS_H
#include <QProcess> #include <QProcess>
#include <QThread>
#include <QString> #include <QString>
#include <QDebug> #include <QDebug>
#include <QTimer> #include <QTimer>
@ -12,13 +13,16 @@ class PM3Process : public QProcess
{ {
Q_OBJECT Q_OBJECT
public: public:
explicit PM3Process(QObject* parent=nullptr); explicit PM3Process(QThread* thread, QObject* parent=nullptr);
bool start(const QString path, const QString port);
QStringList findPort();
QByteArray readLine(qint64 maxlen = 0); QByteArray readLine(qint64 maxlen = 0);
void setRequiringOutput(bool st);
QString getRequiredOutput(); QString getRequiredOutput();
bool waitForReadyRead(int msecs = 2000); bool waitForReadyRead(int msecs = 2000);
void testThread();
public slots:
void setRequiringOutput(bool st);
void connectPM3(const QString path, const QString port);
void setSerialListener(const QString &name, bool state); void setSerialListener(const QString &name, bool state);
private slots: private slots:
void onTimeout(); void onTimeout();
@ -28,7 +32,7 @@ private:
QTimer* serialListener; QTimer* serialListener;
QSerialPortInfo* portInfo; QSerialPortInfo* portInfo;
signals: signals:
void PM3disconnected(); void PM3StatedChanged(bool st, QString info="");
}; };
#endif // PM3PROCESS_H #endif // PM3PROCESS_H

Loading…
Cancel
Save