2020-04-06 23:48:08 +08:00
# include " pm3process.h "
2020-04-21 19:12:44 +08:00
PM3Process : : PM3Process ( QThread * thread , QObject * parent ) : QProcess ( parent )
2020-04-06 23:48:08 +08:00
{
2020-04-21 19:12:44 +08:00
moveToThread ( thread ) ;
2020-04-07 18:16:00 +08:00
setProcessChannelMode ( PM3Process : : MergedChannels ) ;
2020-04-22 23:13:00 +08:00
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."
2020-04-21 19:12:44 +08:00
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
2020-04-18 02:01:42 +08:00
serialListener - > setInterval ( 1000 ) ;
serialListener - > setTimerType ( Qt : : VeryCoarseTimer ) ;
2020-04-22 23:13:00 +08:00
connect ( serialListener , & QTimer : : timeout , this , & PM3Process : : onTimeout ) ;
connect ( this , & PM3Process : : readyRead , this , & PM3Process : : onReadyRead ) ;
2021-02-21 23:00:07 +08:00
portInfo = nullptr ;
2020-04-07 18:16:00 +08:00
}
2020-04-06 23:48:08 +08:00
2021-02-21 23:00:07 +08:00
void PM3Process : : connectPM3 ( const QString & path , const QStringList args )
2020-04-07 18:16:00 +08:00
{
2020-08-05 19:08:02 +08:00
QString result ;
2021-02-15 18:38:34 +08:00
Util : : ClientType clientType ;
2020-04-21 19:12:44 +08:00
setRequiringOutput ( true ) ;
2020-04-06 23:48:08 +08:00
2021-02-15 18:38:34 +08:00
// stash for reconnect
currPath = path ;
currArgs = args ;
2020-04-07 18:16:00 +08:00
// using "-f" option to make the client output flushed after every print.
2021-09-05 21:35:03 +08:00
start ( path , args , QProcess : : Unbuffered | QProcess : : ReadWrite | QProcess : : Text ) ;
2020-04-21 19:12:44 +08:00
if ( waitForStarted ( 10000 ) )
2020-04-18 02:01:42 +08:00
{
2021-02-15 18:38:34 +08:00
waitForReadyRead ( 10000 ) ;
2020-04-21 19:12:44 +08:00
setRequiringOutput ( false ) ;
2020-08-05 19:08:02 +08:00
result = * requiredOutput ;
if ( result . indexOf ( " [=] " ) ! = - 1 )
{
2020-08-05 22:46:41 +08:00
clientType = Util : : CLIENTTYPE_ICEMAN ;
2020-08-05 19:08:02 +08:00
setRequiringOutput ( true ) ;
2021-09-05 21:35:03 +08:00
write ( " hw version \n " ) ;
for ( int i = 0 ; i < 50 ; i + + )
2021-02-15 23:00:02 +08:00
{
waitForReadyRead ( 200 ) ;
result + = * requiredOutput ;
2021-09-05 21:35:03 +08:00
if ( result . indexOf ( " os: " ) ! = - 1 )
break ;
2021-02-15 23:00:02 +08:00
}
2020-08-05 19:08:02 +08:00
setRequiringOutput ( false ) ;
}
2021-02-15 18:38:34 +08:00
else
{
clientType = Util : : CLIENTTYPE_OFFICIAL ;
}
2020-04-22 23:13:00 +08:00
if ( result . indexOf ( " os: " ) ! = - 1 ) // make sure the PM3 is connected
2020-04-21 19:12:44 +08:00
{
2020-08-05 22:46:41 +08:00
emit changeClientType ( clientType ) ;
2020-04-21 19:12:44 +08:00
result = result . mid ( result . indexOf ( " os: " ) ) ;
2021-09-05 21:35:03 +08:00
result = result . left ( result . indexOf ( " \n " ) ) ;
result = result . mid ( 4 , result . indexOf ( " " , 4 ) - 4 ) ;
2020-04-22 23:13:00 +08:00
emit PM3StatedChanged ( true , result ) ;
2020-04-21 19:12:44 +08:00
}
else
kill ( ) ;
2020-04-18 02:01:42 +08:00
}
2020-04-06 23:48:08 +08:00
}
2020-04-11 23:53:06 +08:00
2021-02-15 18:38:34 +08:00
void PM3Process : : reconnectPM3 ( )
{
2021-02-21 23:00:07 +08:00
connectPM3 ( currPath , currArgs ) ;
2021-02-15 18:38:34 +08:00
}
2020-04-11 23:53:06 +08:00
void PM3Process : : setRequiringOutput ( bool st )
{
2020-04-22 23:13:00 +08:00
isRequiringOutput = st ;
2020-04-11 23:53:06 +08:00
if ( isRequiringOutput )
requiredOutput - > clear ( ) ;
}
2020-04-15 00:38:43 +08:00
bool PM3Process : : waitForReadyRead ( int msecs )
{
return QProcess : : waitForReadyRead ( msecs ) ;
}
2020-04-16 00:39:10 +08:00
2020-04-22 23:13:00 +08:00
void PM3Process : : setSerialListener ( const QString & name , bool state )
2020-04-18 02:01:42 +08:00
{
if ( state )
{
2021-02-21 23:00:07 +08:00
currPort = name ;
2020-04-22 23:13:00 +08:00
portInfo = new QSerialPortInfo ( name ) ;
2020-04-18 02:01:42 +08:00
serialListener - > start ( ) ;
2020-04-22 23:13:00 +08:00
qDebug ( ) < < serialListener - > thread ( ) ;
2020-04-18 02:01:42 +08:00
}
else
{
serialListener - > stop ( ) ;
2021-02-21 23:00:07 +08:00
if ( portInfo ! = nullptr )
{
delete portInfo ;
portInfo = nullptr ;
}
2020-04-18 02:01:42 +08:00
}
}
2021-02-21 23:00:07 +08:00
void PM3Process : : setSerialListener ( bool state )
{
setSerialListener ( currPort , state ) ;
}
2020-04-22 21:14:33 +08:00
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);
2020-04-18 02:01:42 +08:00
{
2021-09-19 21:33:53 +08:00
// isBusy() is a deprecated function because it will block the serial port when the port is not in use.
2021-09-19 23:59:55 +08:00
// However, the PM3 client is supposed to use the target serial port exclusively, so it should be fine
2021-09-19 21:33:53 +08:00
// isBusy() will always return false on Raspbian, in this case, check "Keep the client active" in the Settings panel.
2021-09-05 21:35:03 +08:00
//
2020-04-22 23:13:00 +08:00
// qDebug()<<portInfo->isBusy();
2021-09-19 21:33:53 +08:00
if ( ! portInfo - > isBusy ( ) )
{
killPM3 ( ) ;
}
2020-04-18 02:01:42 +08:00
}
2020-04-21 19:12:44 +08:00
void PM3Process : : testThread ( )
{
2020-04-22 23:13:00 +08:00
qDebug ( ) < < " PM3: " < < QThread : : currentThread ( ) ;
2020-04-21 19:12:44 +08:00
}
2020-04-22 16:00:56 +08:00
qint64 PM3Process : : write ( QString data )
{
return QProcess : : write ( data . toLatin1 ( ) ) ;
}
2020-04-22 16:42:58 +08:00
void PM3Process : : onReadyRead ( )
{
2020-04-22 21:14:33 +08:00
QString out = readAll ( ) ;
if ( isRequiringOutput )
requiredOutput - > append ( out ) ;
if ( out ! = " " )
{
2020-04-23 17:50:20 +08:00
// qDebug() << "PM3Process::onReadyRead:" << out;
2020-04-22 21:14:33 +08:00
emit newOutput ( out ) ;
}
2020-04-22 16:42:58 +08:00
}
2021-02-15 18:38:34 +08:00
void PM3Process : : setProcEnv ( const QStringList * env )
{
// qDebug() << "passed Env List" << *env;
this - > setEnvironment ( * env ) ;
2021-02-17 01:26:14 +08:00
// qDebug() << "final Env List" << processEnvironment().toStringList();
}
void PM3Process : : setWorkingDir ( const QString & dir )
{
// the working directory cannot be the default, or the client will failed to load the dll
this - > setWorkingDirectory ( dir ) ;
2021-02-15 18:38:34 +08:00
}
2021-02-22 12:47:55 +08:00
void PM3Process : : killPM3 ( )
{
kill ( ) ;
emit PM3StatedChanged ( false ) ;
setSerialListener ( false ) ;
}