Commit b68cbcc9 authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

S60: Give more progress/error information.

- Add methods to obtain executable from the run configuration
  (to be used by Debugger later on)
- Log the file names and sizes
- Pass on CreateFile() errors.
- Rename class Adapter to Launcher.
parent 695ac13c
......@@ -48,6 +48,15 @@
using namespace ProjectExplorer;
using namespace Qt4ProjectManager::Internal;
// Format information about a file
static QString lsFile(const QString &f)
{
QString rc;
const QFileInfo fi(f);
QTextStream str(&rc);
str << fi.size() << ' ' << fi.lastModified().toString(Qt::ISODate) << ' ' << QDir::toNativeSeparators(fi.absoluteFilePath());
return rc;
}
// ======== S60DeviceRunConfiguration
S60DeviceRunConfiguration::S60DeviceRunConfiguration(Project *project, const QString &proFilePath)
: RunConfiguration(project),
......@@ -164,6 +173,49 @@ void S60DeviceRunConfiguration::setCustomKeyPath(const QString &path)
m_customKeyPath = path;
}
QString S60DeviceRunConfiguration::packageFileName() const
{
QString rc = basePackageFilePath();
if (!rc.isEmpty())
rc += QLatin1String(".pkg");
return rc;
}
/* Grep the pkg file for \code
; Executable and default resource files
"/S60/devices/S60_3rd_FP2_SDK_v1.1/epoc32/release/gcce/udeb/foo.exe" - "!:\sys\bin\foo.exe"
\endcode */
static QString executableFromPkgFile(const QString &pkgFileName, QString *errorMessage)
{
QFile pkgFile(pkgFileName);
if (!pkgFile.open(QIODevice::ReadOnly|QIODevice::Text)) {
*errorMessage = S60DeviceRunConfiguration::tr("Cannot open %1: %2").arg(pkgFileName, pkgFile.errorString());
return QString();
}
// "<SDK>/foo.exe" - "!:\device_bin\foo.exe"
const QRegExp exePattern = QRegExp(QLatin1String("^\"([^\"]+\\.exe)\" +-.*$"));
Q_ASSERT(exePattern.isValid());
foreach(const QString &line, QString::fromLocal8Bit(pkgFile.readAll()).split(QLatin1Char('\n')))
if (exePattern.exactMatch(line))
return exePattern.cap(1);
*errorMessage = S60DeviceRunConfiguration::tr("Unable to find the executable in the package file %1.").arg(pkgFileName);
return QString();
}
QString S60DeviceRunConfiguration::executableFileName() const
{
const QString pkg = packageFileName();
if (!pkg.isEmpty()) {
QString errorMessage;
const QString rc = executableFromPkgFile(pkg, &errorMessage);
if (rc.isEmpty())
qWarning("%s\n", qPrintable(errorMessage));
return rc;
}
return QString();
}
void S60DeviceRunConfiguration::updateTarget()
{
if (m_cachedTargetInformationValid)
......@@ -455,7 +507,7 @@ RunControl* S60DeviceRunConfigurationRunner::run(QSharedPointer<RunConfiguration
// ======== S60DeviceRunControl
S60DeviceRunControl::S60DeviceRunControl(QSharedPointer<RunConfiguration> runConfiguration)
: RunControl(runConfiguration), m_adapter(0)
: RunControl(runConfiguration), m_launcher(0)
{
m_makesis = new QProcess(this);
connect(m_makesis, SIGNAL(readyReadStandardError()),
......@@ -480,9 +532,10 @@ S60DeviceRunControl::S60DeviceRunControl(QSharedPointer<RunConfiguration> runCon
void S60DeviceRunControl::start()
{
QSharedPointer<S60DeviceRunConfiguration> rc = runConfiguration().dynamicCast<S60DeviceRunConfiguration>();
Q_ASSERT(!rc.isNull());
QTC_ASSERT(!rc.isNull(), return);
Qt4Project *project = qobject_cast<Qt4Project *>(rc->project());
QTC_ASSERT(project, return);
m_serialPortName = rc->serialPortName();
m_serialPortFriendlyName = S60Manager::instance()->serialDeviceLister()->friendlyNameForPort(m_serialPortName);
......@@ -497,26 +550,25 @@ void S60DeviceRunControl::start()
emit started();
emit addToOutputWindow(this, tr("Creating %1.sisx ...").arg(QDir::toNativeSeparators(m_baseFileName)));
emit addToOutputWindow(this, tr("Executable file: %1").arg(lsFile(rc->executableFileName())));
Q_ASSERT(project);
m_toolsDirectory = S60Manager::instance()->deviceForQtVersion(
project->qtVersion(project->activeBuildConfiguration())).toolsRoot
+ "/epoc32/tools";
QString makesisTool = m_toolsDirectory + "/makesis.exe";
QString packageFile = QFileInfo(m_baseFileName + ".pkg").fileName();
const QString makesisTool = m_toolsDirectory + "/makesis.exe";
const QString packageFile = QFileInfo(rc->packageFileName()).fileName();
m_makesis->setWorkingDirectory(m_workingDirectory);
emit addToOutputWindow(this, tr("%1 %2").arg(QDir::toNativeSeparators(makesisTool), packageFile));
m_makesis->start(makesisTool, QStringList()
<< packageFile,
QIODevice::ReadOnly);
m_makesis->start(makesisTool, QStringList(packageFile), QIODevice::ReadOnly);
}
void S60DeviceRunControl::stop()
{
m_makesis->kill();
m_signsis->kill();
if (m_adapter)
m_adapter->terminate();
if (m_launcher)
m_launcher->terminate();
}
bool S60DeviceRunControl::isRunning() const
......@@ -578,28 +630,29 @@ void S60DeviceRunControl::signsisProcessFinished()
emit finished();
return;
}
m_adapter = new trk::Adapter;
connect(m_adapter, SIGNAL(finished()), this, SLOT(runFinished()));
connect(m_adapter, SIGNAL(copyingStarted()), this, SLOT(printCopyingNotice()));
connect(m_adapter, SIGNAL(installingStarted()), this, SLOT(printInstallingNotice()));
connect(m_adapter, SIGNAL(startingApplication()), this, SLOT(printStartingNotice()));
connect(m_adapter, SIGNAL(applicationRunning(uint)), this, SLOT(printRunNotice(uint)));
connect(m_adapter, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString)));
m_launcher = new trk::Launcher;
connect(m_launcher, SIGNAL(finished()), this, SLOT(runFinished()));
connect(m_launcher, SIGNAL(copyingStarted()), this, SLOT(printCopyingNotice()));
connect(m_launcher, SIGNAL(installingStarted()), this, SLOT(printInstallingNotice()));
connect(m_launcher, SIGNAL(startingApplication()), this, SLOT(printStartingNotice()));
connect(m_launcher, SIGNAL(applicationRunning(uint)), this, SLOT(printRunNotice(uint)));
connect(m_launcher, SIGNAL(applicationOutputReceived(QString)), this, SLOT(printApplicationOutput(QString)));
//TODO sisx destination and file path user definable
m_adapter->setTrkServerName(m_serialPortName);
m_launcher->setTrkServerName(m_serialPortName);
const QString copySrc(m_baseFileName + ".sisx");
const QString copyDst = QString("C:\\Data\\%1.sisx").arg(QFileInfo(m_baseFileName).fileName());
const QString runFileName = QString("C:\\sys\\bin\\%1.exe").arg(m_targetName);
m_adapter->setCopyFileName(copySrc, copyDst);
m_adapter->setInstallFileName(copyDst);
m_adapter->setFileName(runFileName);
emit addToOutputWindow(this, tr("Deploying application to %1...").arg(m_serialPortFriendlyName));
if (!m_adapter->startServer()) {
delete m_adapter;
m_adapter = 0;
error(this, tr("Could not connect to phone on port %1. "
"Check if the phone is connected and if it runs the TRK application.").arg(m_serialPortName));
m_launcher->setCopyFileName(copySrc, copyDst);
m_launcher->setInstallFileName(copyDst);
m_launcher->setFileName(runFileName);
emit addToOutputWindow(this, tr("Package: %1\nDeploying application to '%2'...").arg(lsFile(copySrc), m_serialPortFriendlyName));
QString errorMessage;
if (!m_launcher->startServer(&errorMessage)) {
delete m_launcher;
m_launcher = 0;
error(this, tr("Could not connect to phone on port '%1': %2\n"
"Check if the phone is connected and the TRK application is running.").arg(m_serialPortName, errorMessage));
emit finished();
}
}
......@@ -631,8 +684,8 @@ void S60DeviceRunControl::printApplicationOutput(const QString &output)
void S60DeviceRunControl::runFinished()
{
m_adapter->deleteLater();
m_adapter = 0;
m_launcher->deleteLater();
m_launcher = 0;
emit addToOutputWindow(this, tr("Finished."));
emit finished();
}
......
......@@ -72,6 +72,9 @@ public:
QString customKeyPath() const;
void setCustomKeyPath(const QString &path);
QString packageFileName() const;
QString executableFileName() const;
signals:
void targetInformationChanged();
......@@ -178,7 +181,7 @@ private:
QString m_customKeyPath;
QProcess *m_makesis;
QProcess *m_signsis;
trk::Adapter *m_adapter;
trk::Launcher *m_launcher;
};
} // namespace Internal
......
......@@ -32,6 +32,24 @@
#if USE_NATIVE
#include <windows.h>
// Format windows error from GetLastError() value: TODO: Use the one provided by the utisl lib.
QString winErrorMessage(unsigned long error)
{
QString rc = QString::fromLatin1("#%1: ").arg(error);
ushort *lpMsgBuf;
const int len = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, 0, (LPTSTR)&lpMsgBuf, 0, NULL);
if (len) {
rc = QString::fromUtf16(lpMsgBuf, len);
LocalFree(lpMsgBuf);
} else {
rc += QString::fromLatin1("<unknown error>");
}
return rc;
}
// Non-blocking replacement for win-api ReadFile function
BOOL WINAPI TryReadFile(HANDLE hFile,
LPVOID lpBuffer,
......@@ -58,9 +76,9 @@ BOOL WINAPI TryReadFile(HANDLE hFile,
using namespace trk;
#define CB(s) &Adapter::s
#define CB(s) &Launcher::s
Adapter::Adapter()
Launcher::Launcher()
{
// Trk
#if USE_NATIVE
......@@ -72,7 +90,7 @@ Adapter::Adapter()
m_trkWriteBusy = false;
}
Adapter::~Adapter()
Launcher::~Launcher()
{
// Trk
#if USE_NATIVE
......@@ -85,12 +103,10 @@ Adapter::~Adapter()
logMessage("Shutting down.\n");
}
bool Adapter::startServer()
bool Launcher::startServer(QString *errorMessage)
{
if (!openTrkPort(m_trkServerName)) {
logMessage("Unable to connect to TRK server");
if (!openTrkPort(m_trkServerName, errorMessage))
return false;
}
m_timerId = startTimer(100);
sendTrkInitialPing();
sendTrkMessage(TrkConnect); // Connect
......@@ -104,7 +120,7 @@ bool Adapter::startServer()
return true;
}
void Adapter::installAndRun()
void Launcher::installAndRun()
{
if (!m_installFileName.isEmpty()) {
installRemotePackageSilently(m_installFileName);
......@@ -112,13 +128,13 @@ void Adapter::installAndRun()
startInferiorIfNeeded();
}
}
void Adapter::logMessage(const QString &msg)
void Launcher::logMessage(const QString &msg)
{
if (DEBUG_TRK)
qDebug() << "ADAPTER: " << qPrintable(msg);
}
bool Adapter::openTrkPort(const QString &port)
bool Launcher::openTrkPort(const QString &port, QString *errorMessage)
{
#if USE_NATIVE
m_hdevice = CreateFile(port.toStdWString().c_str(),
......@@ -130,7 +146,8 @@ bool Adapter::openTrkPort(const QString &port)
NULL);
if (INVALID_HANDLE_VALUE == m_hdevice){
logMessage("Could not open device " + port);
*errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, winErrorMessage(GetLastError()));
logMessage(*errorMessage);
return false;
}
return true;
......@@ -145,8 +162,8 @@ bool Adapter::openTrkPort(const QString &port)
m_trkDevice->setTimeout(0, 500);
if (!m_trkDevice->open(QIODevice::ReadWrite)) {
QByteArray ba = m_trkDevice->errorString().toLatin1();
logMessage("Could not open device " << ba);
*errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, m_trkDevice->errorString());
logMessage(*errorMessage);
return false;
}
return true;
......@@ -158,14 +175,14 @@ bool Adapter::openTrkPort(const QString &port)
#endif
}
void Adapter::timerEvent(QTimerEvent *)
void Launcher::timerEvent(QTimerEvent *)
{
//qDebug(".");
tryTrkWrite();
tryTrkRead();
}
byte Adapter::nextTrkWriteToken()
byte Launcher::nextTrkWriteToken()
{
++m_trkWriteToken;
if (m_trkWriteToken == 0)
......@@ -173,7 +190,7 @@ byte Adapter::nextTrkWriteToken()
return m_trkWriteToken;
}
void Adapter::sendTrkMessage(byte code, TrkCallBack callBack,
void Launcher::sendTrkMessage(byte code, TrkCallBack callBack,
const QByteArray &data, const QVariant &cookie)
{
TrkMessage msg;
......@@ -185,7 +202,7 @@ void Adapter::sendTrkMessage(byte code, TrkCallBack callBack,
queueTrkMessage(msg);
}
void Adapter::sendTrkInitialPing()
void Launcher::sendTrkInitialPing()
{
TrkMessage msg;
msg.code = 0x00; // Ping
......@@ -193,13 +210,13 @@ void Adapter::sendTrkInitialPing()
queueTrkMessage(msg);
}
void Adapter::waitForTrkFinished(const TrkResult &result)
void Launcher::waitForTrkFinished(const TrkResult &result)
{
Q_UNUSED(result)
sendTrkMessage(TrkPing, CB(handleWaitForFinished));
}
void Adapter::terminate()
void Launcher::terminate()
{
QByteArray ba;
appendShort(&ba, 0x0000, TargetByteOrder);
......@@ -207,7 +224,7 @@ void Adapter::terminate()
sendTrkMessage(TrkDeleteItem, CB(waitForTrkFinished), ba);
}
void Adapter::sendTrkAck(byte token)
void Launcher::sendTrkAck(byte token)
{
logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token)));
TrkMessage msg;
......@@ -220,12 +237,12 @@ void Adapter::sendTrkAck(byte token)
// 01 90 00 07 7e 80 01 00 7d 5e 7e
}
void Adapter::queueTrkMessage(const TrkMessage &msg)
void Launcher::queueTrkMessage(const TrkMessage &msg)
{
m_trkWriteQueue.append(msg);
}
void Adapter::tryTrkWrite()
void Launcher::tryTrkWrite()
{
if (m_trkWriteBusy)
return;
......@@ -236,7 +253,7 @@ void Adapter::tryTrkWrite()
trkWrite(msg);
}
void Adapter::trkWrite(const TrkMessage &msg)
void Launcher::trkWrite(const TrkMessage &msg)
{
QByteArray ba = frameMessage(msg.code, msg.token, msg.data);
......@@ -260,7 +277,7 @@ void Adapter::trkWrite(const TrkMessage &msg)
#endif
}
void Adapter::tryTrkRead()
void Launcher::tryTrkRead()
{
#if USE_NATIVE
const DWORD BUFFERSIZE = 1024;
......@@ -292,7 +309,7 @@ void Adapter::tryTrkRead()
}
void Adapter::handleResult(const TrkResult &result)
void Launcher::handleResult(const TrkResult &result)
{
QByteArray prefix = "READ BUF: ";
QByteArray str = result.toString().toUtf8();
......@@ -416,7 +433,7 @@ void Adapter::handleResult(const TrkResult &result)
}
}
void Adapter::handleFileCreation(const TrkResult &result)
void Launcher::handleFileCreation(const TrkResult &result)
{
// we don't do any error handling yet, which is bad
const char *data = result.data.data();
......@@ -441,13 +458,13 @@ void Adapter::handleFileCreation(const TrkResult &result)
sendTrkMessage(TrkCloseFile, CB(handleFileCreated), ba);
}
void Adapter::handleFileCreated(const TrkResult &result)
void Launcher::handleFileCreated(const TrkResult &result)
{
Q_UNUSED(result)
installAndRun();
}
void Adapter::handleCpuType(const TrkResult &result)
void Launcher::handleCpuType(const TrkResult &result)
{
logMessage("HANDLE CPU TYPE: " + result.toString());
//---TRK------------------------------------------------------
......@@ -463,7 +480,7 @@ void Adapter::handleCpuType(const TrkResult &result)
//m_session.extended2TypeSize = result.data[6];
}
void Adapter::handleCreateProcess(const TrkResult &result)
void Launcher::handleCreateProcess(const TrkResult &result)
{
// 40 00 00]
//logMessage(" RESULT: " + result.toString());
......@@ -484,14 +501,14 @@ void Adapter::handleCreateProcess(const TrkResult &result)
sendTrkMessage(TrkContinue, 0, ba, "CONTINUE");
}
void Adapter::handleWaitForFinished(const TrkResult &result)
void Launcher::handleWaitForFinished(const TrkResult &result)
{
logMessage(" FINISHED: " + stringFromArray(result.data));
killTimer(m_timerId);
emit finished();
}
void Adapter::handleSupportMask(const TrkResult &result)
void Launcher::handleSupportMask(const TrkResult &result)
{
const char *data = result.data.data();
QByteArray str;
......@@ -505,7 +522,7 @@ void Adapter::handleSupportMask(const TrkResult &result)
}
void Adapter::cleanUp()
void Launcher::cleanUp()
{
//
//---IDE------------------------------------------------------
......@@ -559,7 +576,7 @@ void Adapter::cleanUp()
// Error: 0x00
}
void Adapter::copyFileToRemote()
void Launcher::copyFileToRemote()
{
emit copyingStarted();
QByteArray ba;
......@@ -568,7 +585,7 @@ void Adapter::copyFileToRemote()
sendTrkMessage(TrkOpenFile, CB(handleFileCreation), ba);
}
void Adapter::installRemotePackageSilently(const QString &fileName)
void Launcher::installRemotePackageSilently(const QString &fileName)
{
emit installingStarted();
QByteArray ba;
......@@ -577,12 +594,12 @@ void Adapter::installRemotePackageSilently(const QString &fileName)
sendTrkMessage(TrkInstallFile, CB(handleInstallPackageFinished), ba);
}
void Adapter::handleInstallPackageFinished(const TrkResult &)
void Launcher::handleInstallPackageFinished(const TrkResult &)
{
startInferiorIfNeeded();
}
void Adapter::startInferiorIfNeeded()
void Launcher::startInferiorIfNeeded()
{
emit startingApplication();
if (m_session.pid != 0) {
......
......@@ -48,18 +48,18 @@
namespace trk {
class Adapter : public QObject
class Launcher : public QObject
{
Q_OBJECT
public:
Adapter();
~Adapter();
Launcher();
~Launcher();
void setTrkServerName(const QString &name) { m_trkServerName = name; }
void setFileName(const QString &name) { m_fileName = name; }
void setCopyFileName(const QString &srcName, const QString &dstName) { m_copySrcFileName = srcName; m_copyDstFileName = dstName; }
void setInstallFileName(const QString &name) { m_installFileName = name; }
bool startServer();
bool startServer(QString *errorMessage);
signals:
void copyingStarted();
......@@ -76,7 +76,7 @@ private:
//
// TRK
//
typedef void (Adapter::*TrkCallBack)(const TrkResult &);
typedef void (Launcher::*TrkCallBack)(const TrkResult &);
struct TrkMessage
{
......@@ -88,7 +88,7 @@ private:
TrkCallBack callBack;
};
bool openTrkPort(const QString &port); // or server name for local server
bool openTrkPort(const QString &port, QString *errorMessage); // or server name for local server
void sendTrkMessage(byte code,
TrkCallBack callBack = 0,
const QByteArray &data = QByteArray(),
......
......@@ -16,21 +16,23 @@ int main(int argc, char *argv[])
QCoreApplication app(argc, argv);
Adapter adapter;
adapter.setTrkServerName(argv[1]);
Launcher launcher;
launcher.setTrkServerName(argv[1]);
if (argc == 3) {
adapter.setFileName(argv[2]);
launcher.setFileName(argv[2]);
} else if (argc == 5) {
adapter.setInstallFileName(argv[3]);
adapter.setFileName(argv[4]);
launcher.setInstallFileName(argv[3]);
launcher.setFileName(argv[4]);
} else {
adapter.setCopyFileName(argv[3], argv[4]);
adapter.setInstallFileName(argv[4]);
adapter.setFileName(argv[5]);
launcher.setCopyFileName(argv[3], argv[4]);
launcher.setInstallFileName(argv[4]);
launcher.setFileName(argv[5]);
}
QObject::connect(&adapter, SIGNAL(finished()), &app, SLOT(quit()));
if (adapter.startServer())
QObject::connect(&launcher, SIGNAL(finished()), &app, SLOT(quit()));
QString errorMessage;
if (launcher.startServer(&errorMessage))
return app.exec();
qWarning("%s\n", qPrintable(errorMessage));
return 4;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment