From b68cbcc9ae0c5544f067e4b25dab4bb9b9f791d8 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Fri, 14 Aug 2009 14:29:19 +0200 Subject: [PATCH] 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. --- .../qt-s60/s60devicerunconfiguration.cpp | 111 +++++++++++++----- .../qt-s60/s60devicerunconfiguration.h | 5 +- tests/manual/trk/launcher.cpp | 89 ++++++++------ tests/manual/trk/launcher.h | 12 +- tests/manual/trk/main_launcher.cpp | 22 ++-- 5 files changed, 157 insertions(+), 82 deletions(-) diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp index 448d909e303..87134bf6263 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.cpp @@ -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(); } diff --git a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h index 85761079667..f9402d2964c 100644 --- a/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h +++ b/src/plugins/qt4projectmanager/qt-s60/s60devicerunconfiguration.h @@ -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 diff --git a/tests/manual/trk/launcher.cpp b/tests/manual/trk/launcher.cpp index 56b983fbe19..3be5078f8cc 100644 --- a/tests/manual/trk/launcher.cpp +++ b/tests/manual/trk/launcher.cpp @@ -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) { diff --git a/tests/manual/trk/launcher.h b/tests/manual/trk/launcher.h index cda0ac2e4fd..44d70aa9f22 100644 --- a/tests/manual/trk/launcher.h +++ b/tests/manual/trk/launcher.h @@ -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(), diff --git a/tests/manual/trk/main_launcher.cpp b/tests/manual/trk/main_launcher.cpp index e6b6d322969..18b29d1dd15 100644 --- a/tests/manual/trk/main_launcher.cpp +++ b/tests/manual/trk/main_launcher.cpp @@ -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; } -- GitLab