QApplication::processEvents() would not work under Linux if ACK bytes are to be received from the target device. This has been changed by a call to a blocking function which ensures input data has been received.

This commit is contained in:
Xavier ASUS 2018-11-30 01:37:33 +01:00
parent 48ce5c59fe
commit e67ae84020
6 changed files with 178 additions and 177 deletions

View File

@ -14,9 +14,11 @@ TEMPLATE = app
win32:QT += winextras
SOURCES += main.cpp\
qpsxserial.cpp
qpsxserial.cpp \
serial.cpp
HEADERS += qpsxserial.h
HEADERS += qpsxserial.h \
serial.hpp
FORMS += qpsxserial.ui \
stdout.ui

View File

@ -7,36 +7,27 @@ int main(int argc, char *argv[])
QStringList param_list;
for(int i = 1; i < argc; i++)
for (int i = 1; i < argc; i++)
{
param_list.append(argv[i]);
}
QPSXSerial* w;
QPSXSerial w(nullptr, param_list.isEmpty() ? GUI_APP : CLI_APP);
if(param_list.isEmpty() == true)
{
w = new QPSXSerial(0, GUI_APP);
}
else
{
w = new QPSXSerial(0, CLI_APP);
}
w.setParamList(param_list);
w->setParamList(param_list);
if(param_list.isEmpty() == true)
if (param_list.isEmpty())
{
w->show();
w.show();
}
else
{
// This will cause the application to exit when
// the task signals finished.
QObject::connect(w, SIGNAL(finished(void)), &a, SLOT(quit(void)));
QObject::connect(&w, SIGNAL(finished(void)), &a, SLOT(quit(void)));
// This will run the task from the application event loop.
QTimer::singleShot(0, w, SLOT(cli_run()));
QTimer::singleShot(0, &w, SLOT(cli_run()));
}
return a.exec();

View File

@ -11,19 +11,25 @@ QPSXSerial::QPSXSerial(QWidget *parent, APP_INTERFACE interface) :
QMainWindow(parent),
ui(new Ui::QPSXSerial),
stdout_ui(new Ui::Stdout_Console),
stdout_dialog(new QDialog)
stdout_dialog(new QDialog),
app_interface(interface),
ack(false),
exe_sent(false),
write_ready(false),
byte_sent_received(false),
first_entered(false),
disable_psx_stdout(false)
{
app_interface = interface;
lost_packet_timer = new QTimer();
disable_psx_stdout = false;
connect(lost_packet_timer, SIGNAL(timeout()), this, SLOT(onPacketLost()));
connect(&lost_packet_timer, SIGNAL(timeout()), this, SLOT(onPacketLost()));
connect(&serial, SIGNAL(bytesWritten(qint64)), this, SLOT(onBytesWritten(qint64)));
connect(&serial, SIGNAL(readyRead()), this, SLOT(onReadyRead(void)));
if(app_interface == GUI_APP)
init_timer.setSingleShot(true);
init_timer.setInterval(CONNECT_TO_PSX_TIMEOUT);
connect(&init_timer, SIGNAL(timeout(void)), this, SLOT(connectToPSXTimeout(void)));
if (app_interface == GUI_APP)
{
ui->setupUi(this);
@ -43,24 +49,13 @@ QPSXSerial::QPSXSerial(QWidget *parent, APP_INTERFACE interface) :
connect(stdout_ui->close_Btn, SIGNAL(released()), stdout_dialog, SLOT(close()));
connect(this, SIGNAL(debug_frame_received(QString)), stdout_ui->stdout_Log, SLOT(append(QString)));
setWindowTitle( "QPSXSerial " +
QString(QPSXSERIAL_VERSION_STR) );
setWindowTitle( "QPSXSerial "
+ QString(QPSXSERIAL_VERSION_STR) );
}
ack = false;
init_timer = NULL;
write_ready = false;
exe_sent = false;
first_entered = false;
}
QPSXSerial::~QPSXSerial()
{
if(serial.isOpen() == true)
{
serial.close();
}
delete ui;
}
@ -79,11 +74,11 @@ void QPSXSerial::showError(QString error)
void QPSXSerial::onLoadFileBtnReleased(void)
{
selectedFolder = QFileDialog::getExistingDirectory( this,
"Load folder with PSX data",
"C:/",
QFileDialog::ShowDirsOnly );
"Load folder with PSX data",
"C:/",
QFileDialog::ShowDirsOnly );
if(selectedFolder.isEmpty() == true)
if (selectedFolder.isEmpty())
{
return;
}
@ -92,7 +87,7 @@ void QPSXSerial::onLoadFileBtnReleased(void)
inputExe = getInputExeFromFolder(&selectedFolder);
if(selectedPort.isEmpty() == false)
if (selectedPort.isEmpty() == false)
{
ui->send_Btn->setEnabled(true);
}
@ -110,9 +105,9 @@ void QPSXSerial::onUpdatePortsBtnReleased(void)
void QPSXSerial::onSendBtnReleased(void)
{
if(serial.isOpen() == false)
if (serial.isOpen() == false)
{
if(selectedPort.isEmpty() == true)
if (selectedPort.isEmpty())
{
showGUICLIerror("No selected port!");
return;
@ -124,42 +119,32 @@ void QPSXSerial::onSendBtnReleased(void)
serial.setDataBits(QSerialPort::Data8);
serial.setStopBits(QSerialPort::OneStop);
if(serial.open(QIODevice::ReadWrite) == false)
if (serial.open(QIODevice::ReadWrite) == false)
{
showGUICLIerror("Could not open port " + selectedPort);
return;
}
if(init_timer == NULL)
{
init_timer = new QTimer();
init_timer.start();
init_timer->setSingleShot(true);
init_timer->setInterval(CONNECT_TO_PSX_TIMEOUT);
connect(init_timer, SIGNAL(timeout(void)), this, SLOT(connectToPSXTimeout(void)));
}
init_timer->start(CONNECT_TO_PSX_TIMEOUT);
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->exeProgressBar->setVisible(true);
ui->exeProgressBar->setMinimum(0);
ui->exeProgressBar->setMaximum(0);
ui->inFileName->setText("Waiting for PSX response...");
ui->inFileName->setText("Waiting for response from the device...");
ui->inFileName->setVisible(true);
ui->send_Btn->setText("Disconnect from PSX");
}
else
{
printf("Connected to port successfully.\n");
printf("Waiting for PSX response...\n");
printf("Waiting for response from the device...\n");
}
}
else
{
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->send_Btn->setText("Send to PSX!");
ui->exeProgressBar->setVisible(false);
@ -167,11 +152,10 @@ void QPSXSerial::onSendBtnReleased(void)
}
serial.close();
//qDebug() << "Disconnected";
first_entered = false;
exe_sent = false;
lost_packet_timer->stop();
init_timer->stop();
lost_packet_timer.stop();
init_timer.stop();
}
}
@ -179,15 +163,13 @@ void QPSXSerial::connectToPSXTimeout(void)
{
QByteArray ba;
if(ack == false)
if (ack == false)
{
ba.append(99);
serial.write(ba);
//qDebug() << "Retry...";
init_timer->start(CONNECT_TO_PSX_TIMEOUT);
init_timer.start(CONNECT_TO_PSX_TIMEOUT);
}
}
@ -195,50 +177,36 @@ void QPSXSerial::onPortSelectedComboBox(QString port)
{
selectedPort = port;
if(inputExe.isEmpty() == false)
if (inputExe.isEmpty() == false)
{
ui->send_Btn->setEnabled(true);
}
qDebug() << "Selected port: " + selectedPort;
}
void QPSXSerial::onBytesWritten(qint64)
{
//qDebug() << "Bytes written: " + QString::number(bytes_written);
/*byte_sent_received = false;
while(byte_sent_received == false)
{
QApplication::processEvents();
}*/
write_ready = true;
}
void QPSXSerial::onReadyRead(void)
{
QByteArray data = serial.readAll();
const QByteArray data = serial.readAll();
static QTime time = QTime::currentTime();
static bool cdrom_petition;
//qDebug() << QString("Received ") + QString::number(data.count()) + QString(" bytes.");
//qDebug() << QString("Took ") + QString::number(time.msecsTo(QTime::currentTime()));
if(exe_sent == true)
if (exe_sent)
{
static QByteArray fileName;
if(data.contains("#") == true)
if (data.contains("#"))
{
cdrom_petition = true;
fileName.clear();
}
if(data.count() == 1)
if (data.count() == 1)
{
if(data.at(0) == 'b')
if (data.at(0) == 'b')
{
ack = true;
return;
@ -247,9 +215,9 @@ void QPSXSerial::onReadyRead(void)
qDebug() << data;
if(cdrom_petition == true)
if (cdrom_petition)
{
if(data.contains("#") == true)
if (data.contains("#"))
{
int initial_i = data.indexOf("#");
@ -262,11 +230,11 @@ void QPSXSerial::onReadyRead(void)
fileName.append(data);
}
if(fileName.contains("@") == true)
if (fileName.contains("@"))
{
int terminator_i = fileName.indexOf("@");
if(terminator_i >= fileName.count())
if (terminator_i >= fileName.count())
{
fileName.chop(terminator_i - fileName.count() - 1);
}
@ -293,7 +261,7 @@ void QPSXSerial::onReadyRead(void)
QFile f(filePath);
if(f.open(QFile::ReadOnly) == false)
if (f.open(QFile::ReadOnly) == false)
{
qDebug() << "Error while reading input file!";
return;
@ -304,27 +272,30 @@ void QPSXSerial::onReadyRead(void)
sendDataSize(sz);
while(ack == false)
if (serial.waitForReadyRead() == false)
{
QApplication::processEvents();
qDebug() << "Did not receive any ACK!";
}
else
{
qDebug() << "sendData for file...";
onReadyRead();
qDebug() << "sendData for file...";
sendData(file_data, filePath);
sendData(file_data, filePath);
f.close();
f.close();
}
}
}
else
{
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
emit debug_frame_received(QString(data));
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
if(disable_psx_stdout == false)
if (disable_psx_stdout == false)
{
const char* string_received = data.toStdString().c_str();
@ -334,24 +305,23 @@ void QPSXSerial::onReadyRead(void)
}
}
if(data.isEmpty() == false)
if (data.isEmpty() == false)
{
quint8 data_byte = (quint8)data.at(0);
quint8 data_byte = static_cast<quint8>(data.at(0));
if(data_byte == 'b')
if (data_byte == 'b')
{
//qDebug() << "Received ACK";
// Received handshaking byte. Start transmission!
ack = true;
init_timer->stop();
init_timer.stop();
if(first_entered == false)
if (first_entered == false)
{
first_entered = true;
if(sendExe() == false)
if (sendExe() == false)
{
qDebug() << "An error happened when sending EXE file!";
}
@ -368,7 +338,7 @@ bool QPSXSerial::sendExe(void)
{
QFile f(inputExe);
if(f.open(QFile::ReadOnly) == false)
if (f.open(QFile::ReadOnly) == false)
{
qDebug() << "Could not open input EXE file!";
return false;
@ -380,57 +350,64 @@ bool QPSXSerial::sendExe(void)
QByteArray data = f.read(2048 /* PSX-EXE header */);
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->inFileName->setText("Sending PSX-EXE size...");
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
printf("Sending PSX-EXE header data...\n");
}
// PSX-EXE header is actually 2048 bytes long, but initial 32 bytes
// contain all the information we need for this.
for(int i = 0; i < 32; i+=8)
for (int i = 0; i < 32; i+=4)
{
QByteArray send;
write_ready = false;
QThread::msleep(100);
send.append(data.mid(i, 8));
QApplication::processEvents();
qDebug() << "Sending " + data.mid(i, 4).toHex();
send.append(data.mid(i, 4));
serial.write(send);
while(write_ready == false)
{
QApplication::processEvents();
}
}
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->inFileName->setText("Sending PSX-EXE size...");
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
printf("Sending PSX-EXE size...\n");
}
while(ack == false)
if (serial.waitForReadyRead() == false)
{
QApplication::processEvents();
qDebug() << "Did not receive any ACK!";
}
else
{
onReadyRead();
}
qDebug () << "Sending EXE size...";
qint64 sz = f.size() - 2048;
sendDataSize((quint32)sz);
sendDataSize(static_cast<quint32>(sz));
while(ack == false)
if (serial.waitForReadyRead() == false)
{
QApplication::processEvents();
qDebug() << "Did not receive any ACK!";
}
else
{
onReadyRead();
}
// Send file size without header
@ -456,7 +433,7 @@ void QPSXSerial::sendDataSize(quint32 size)
{
QByteArray ar;
for(unsigned int i = 0; i < sizeof(quint32); i++)
for (unsigned int i = 0; i < sizeof(quint32); i++)
{
char send = (char)( size >> (i << 3) );
@ -468,13 +445,13 @@ void QPSXSerial::sendDataSize(quint32 size)
serial.write(send_arr);
while(write_ready == false)
while (write_ready == false)
{
QApplication::processEvents();
}
}
/*for(unsigned int i = 0; i < sizeof(quint32); i++)
/*for (unsigned int i = 0; i < sizeof(quint32); i++)
{
qDebug() << "0x" + QString::number(ar.at(i), 16);
}*/
@ -486,10 +463,10 @@ void QPSXSerial::onPacketLost(void)
{
qDebug() << "Entering onPacketLost...";
if(ack == false)
if (ack == false)
{
serial.write(last_packet_sent);
lost_packet_timer->start(LOST_PACKET_TIMEOUT);
lost_packet_timer.start(LOST_PACKET_TIMEOUT);
}
}
@ -499,7 +476,7 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
last_i = 0;
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->exeProgressBar->setVisible(true);
ui->exeProgressBar->setRange(0, data.count());
@ -507,10 +484,10 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
ui->inFileName->setVisible(true);
}
lost_packet_timer->setInterval(LOST_PACKET_TIMEOUT);
lost_packet_timer->setSingleShot(true);
lost_packet_timer.setInterval(LOST_PACKET_TIMEOUT);
lost_packet_timer.setSingleShot(true);
for(int i = 0; i < data.count(); i+= 8)
for (int i = 0; i < data.count(); i+= 8)
{
QByteArray send;
ack = false;
@ -519,24 +496,30 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
//qDebug() << "Sent packet";
QApplication::processEvents();
serial.write(send);
last_packet_sent = send;
lost_packet_timer->start(LOST_PACKET_TIMEOUT);
lost_packet_timer.start(LOST_PACKET_TIMEOUT);
while(ack == false)
if (serial.waitForReadyRead() == false)
{
QApplication::processEvents();
qDebug() << "Did not receive any ACK!";
}
else
{
onReadyRead();
}
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->exeProgressBar->setValue(i);
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
if( ( (i - last_i) > (data.count() >> 7))
if ( ( (i - last_i) > (data.count() >> 7))
||
(i > (data.count() - (data.count() >> 7) ) ) )
{
@ -549,15 +532,15 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
printf("|");
for(j = 0; j < data.count(); j += data.count() >> 5)
for (j = 0; j < data.count(); j += data.count() >> 5)
{
if(i > j)
if (i > j)
{
printf("=");
}
else if(i < j)
else if (i < j)
{
if(draw_arrow == true)
if (draw_arrow)
{
draw_arrow = false;
printf(">");
@ -581,14 +564,14 @@ void QPSXSerial::sendData(QByteArray data, QString fileName)
printf("\n");
lost_packet_timer->stop();
lost_packet_timer.stop();
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
ui->exeProgressBar->setValue(data.count());
ui->inFileName->setText("Transfer complete!");
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
printf("Transfer complete!\n");
}
@ -607,15 +590,15 @@ void QPSXSerial::cli_run(void)
foreach(QString flag, allowed_flags)
{
if(_paramlist.contains(flag) == true)
if (_paramlist.contains(flag))
{
correct_flag_used = true;
break;
}
}
if( (_paramlist.count() < 2) ||
(_paramlist.contains("--help") == true) ||
if ( (_paramlist.count() < 2) ||
(_paramlist.contains("--help")) ||
(correct_flag_used == false) )
{
showHelp();
@ -629,7 +612,7 @@ void QPSXSerial::cli_run(void)
int port_i = _paramlist.indexOf("--port");
if(port_i == -1)
if (port_i == -1)
{
printf("No port specified! Please include \"--port\" flag and port name e.g.: \"--port COM7\"\n");
@ -637,7 +620,7 @@ void QPSXSerial::cli_run(void)
return;
}
if(_paramlist.count() > (++port_i ) )
if (_paramlist.count() > (++port_i ) )
{
selectedPort = _paramlist.at(port_i);
}
@ -652,7 +635,7 @@ void QPSXSerial::cli_run(void)
int folder_i = _paramlist.indexOf("--input_folder");
if(folder_i == -1)
if (folder_i == -1)
{
printf("No input folder has been specified. Please include \"--help\" for further reference"
" about QPSXSerial usage.\n");
@ -660,7 +643,7 @@ void QPSXSerial::cli_run(void)
return;
}
if(_paramlist.count() > (++folder_i ) )
if (_paramlist.count() > (++folder_i ) )
{
selectedFolder = _paramlist.at(folder_i);
}
@ -674,7 +657,7 @@ void QPSXSerial::cli_run(void)
inputExe = getInputExeFromFolder(&selectedFolder);
if(inputExe.isEmpty() == true)
if (inputExe.isEmpty())
{
printf("Could not find PSX-EXE from specified input folder.\n");
emit finished();
@ -685,7 +668,7 @@ void QPSXSerial::cli_run(void)
int psx_sdtout_flag = _paramlist.indexOf("--disable_psx_stdout");
if(psx_sdtout_flag != -1)
if (psx_sdtout_flag != -1)
{
disable_psx_stdout = true;
}
@ -735,12 +718,12 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
QString fileSelected;
QString retExe;
if( (folder->endsWith("/") == false) && (folder->endsWith("\\") == false) )
if ( (folder->endsWith("/") == false) && (folder->endsWith("\\") == false) )
{
folder->append("/");
}
if(system_f.exists() == false)
if (system_f.exists() == false)
{
QDir d(*folder);
QStringList filters;
@ -750,13 +733,13 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
QStringList exe_list = d.entryList(filters);
if(exe_list.isEmpty() == true)
if (exe_list.isEmpty())
{
retExe.clear();
return retExe;
}
if(exe_list.contains("PSX.EXE") == true)
if (exe_list.contains("PSX.EXE"))
{
fileSelected = "PSX.EXE";
}
@ -767,7 +750,7 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
}
else
{
if(system_f.open(QFile::ReadOnly) == false)
if (system_f.open(QFile::ReadOnly) == false)
{
QString error = "Could not open " + *folder + "\\SYSTEM.CNF";
showGUICLIerror(error);
@ -784,12 +767,12 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
QStringList tokens = line.split("=");
if(tokens.isEmpty() == true)
if (tokens.isEmpty())
{
continue;
}
if(tokens.at(0).contains("BOOT") == false)
if (tokens.at(0).contains("BOOT") == false)
{
continue;
}
@ -799,7 +782,7 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
fileSelected.chop(2); // Remove ";1" suffix.
break;
}while(system_txt.atEnd() == false);
}while (system_txt.atEnd() == false);
}
@ -810,11 +793,11 @@ QString QPSXSerial::getInputExeFromFolder(QString* folder)
void QPSXSerial::showGUICLIerror(QString error)
{
if(app_interface == GUI_APP)
if (app_interface == GUI_APP)
{
showError(error);
}
else if(app_interface == CLI_APP)
else if (app_interface == CLI_APP)
{
const char* c_str_error = error.toStdString().c_str();

View File

@ -8,19 +8,20 @@
#include <QTimer>
#include <QThread>
#include <QTime>
#ifdef __WIN32__
#include <QWinTaskbarButton>
#endif
#include <QMessageBox>
#include <iostream>
#include "ui_stdout.h"
#define QPSXSERIAL_VERSION_NUMBER 0.4
#define QPSXSERIAL_VERSION_STR "0.4"
#define QPSXSERIAL_VERSION_STR "0.5"
#define QPSXSERIAL_URL "https://github.com/XaviDCR92/OpenSend"
#define OPENSEND_URL "https://github.com/XaviDCR92/QPSXSerial/"
typedef enum t_AppInterface
typedef enum
{
CLI_APP = 0,
CLI_APP,
GUI_APP
}APP_INTERFACE;
@ -33,7 +34,7 @@ class QPSXSerial : public QMainWindow
Q_OBJECT
public:
explicit QPSXSerial(QWidget *parent = 0, APP_INTERFACE interface = GUI_APP);
explicit QPSXSerial(QWidget *parent = nullptr, APP_INTERFACE interface = GUI_APP);
~QPSXSerial();
void setParamList(QStringList param){_paramlist = param;}
@ -49,19 +50,19 @@ private:
Ui::QPSXSerial *ui;
Ui::Stdout_Console *stdout_ui;
QDialog *stdout_dialog;
APP_INTERFACE app_interface;
const APP_INTERFACE app_interface;
QString inputExe;
QString selectedPort;
QString selectedFolder;
QSerialPort serial;
bool ack;
bool exe_sent;
QTimer* init_timer;
QTimer init_timer;
bool write_ready;
bool byte_sent_received;
QByteArray last_packet_sent;
bool first_entered;
QTimer* lost_packet_timer;
QTimer lost_packet_timer;
QStringList _paramlist;
bool disable_psx_stdout;

7
serial.cpp Normal file
View File

@ -0,0 +1,7 @@
#include "serial.hpp"
Serial::Serial(QObject *parent) :
QObject(parent)
{
}

17
serial.hpp Normal file
View File

@ -0,0 +1,17 @@
#ifndef SERIAL_HPP
#define SERIAL_HPP
#include <QObject>
class Serial : public QObject
{
Q_OBJECT
public:
explicit Serial(QObject *parent = nullptr);
signals:
public slots:
};
#endif // SERIAL_HPP