diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/runonphone/main.cpp | 78 | ||||
-rw-r--r-- | tools/runonphone/symbianutils/launcher.cpp | 163 | ||||
-rw-r--r-- | tools/runonphone/symbianutils/launcher.h | 8 | ||||
-rw-r--r-- | tools/runonphone/symbianutils/trkutils.h | 53 |
4 files changed, 242 insertions, 60 deletions
diff --git a/tools/runonphone/main.cpp b/tools/runonphone/main.cpp index 80e5e34..37e4548 100644 --- a/tools/runonphone/main.cpp +++ b/tools/runonphone/main.cpp @@ -55,18 +55,20 @@ void printUsage(QTextStream& outstream, QString exeName) { outstream << exeName << " [options] [program] [program arguments]" << endl - << "-s, --sis <file> specify sis file to install" << endl - << "-p, --portname <COMx> specify COM port to use by device name" << endl - << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl - << "-t, --timeout <milliseconds> terminate test if timeout occurs" << endl - << "-v, --verbose show debugging output" << endl - << "-q, --quiet hide progress messages" << endl + << "-s, --sis <file> specify sis file to install" << endl + << "-p, --portname <COMx> specify COM port to use by device name" << endl + << "-f, --portfriendlyname <substring> specify COM port to use by friendly name" << endl + << "-t, --timeout <milliseconds> terminate test if timeout occurs" << endl + << "-v, --verbose show debugging output" << endl + << "-q, --quiet hide progress messages" << endl + << "-d, --download <remote file> <local file> copy file from phone to PC after running test" << endl << endl << "USB COM ports can usually be autodetected, use -p or -f to force a specific port." << endl << "If using System TRK, it is possible to copy the program directly to sys/bin on the phone." << endl << "-s can be used with both System and Application TRK to install the program" << endl; } +#define CHECK_PARAMETER_EXISTS if(!it.hasNext()) { printUsage(outstream, args[0]); return 1; } int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); @@ -79,59 +81,59 @@ int main(int argc, char *argv[]) QStringList args = QCoreApplication::arguments(); QTextStream outstream(stdout); QTextStream errstream(stderr); + QString downloadRemoteFile; + QString downloadLocalFile; int loglevel=1; int timeout=0; - for (int i=1;i<args.size();i++) { - QString arg = args.at(i); + QListIterator<QString> it(args); + it.next(); //skip name of program + while (it.hasNext()) { + QString arg = it.next(); + if (arg.startsWith("-")) { - if (args.size() < i+2) { - errstream << "Command line missing argument parameters" << endl; - return 1; + if (arg == "--portname" || arg == "-p") { + CHECK_PARAMETER_EXISTS + serialPortName = it.next(); } - QString param = args.at(i+1); - if (arg.compare("--portname", Qt::CaseSensitive) == 0 - || arg.compare("-p", Qt::CaseSensitive) == 0) { - serialPortName = param; - i++; + else if (arg == "--portfriendlyname" || arg == "-f") { + CHECK_PARAMETER_EXISTS + serialPortFriendlyName = it.next(); } - else if (arg.compare("--portfriendlyname", Qt::CaseSensitive) == 0 - || arg.compare("-f", Qt::CaseSensitive) == 0) { - serialPortFriendlyName = param; - i++; + else if (arg == "--sis" || arg == "-s") { + CHECK_PARAMETER_EXISTS + sisFile = it.next(); } - else if (arg.compare("--sis", Qt::CaseSensitive) == 0 - || arg.compare("-s", Qt::CaseSensitive) == 0) { - sisFile = param; - i++; + else if (arg == "--download" || arg == "-d") { + CHECK_PARAMETER_EXISTS + downloadRemoteFile = it.next(); + CHECK_PARAMETER_EXISTS + downloadLocalFile = it.next(); } - else if (arg.compare("--timeout", Qt::CaseSensitive) == 0 - || arg.compare("-t", Qt::CaseSensitive) == 0) { + else if (arg == "--timeout" || arg == "-t") { + CHECK_PARAMETER_EXISTS bool ok; - timeout = param.toInt(&ok); + timeout = it.next().toInt(&ok); if (!ok) { errstream << "Timeout must be specified in milliseconds" << endl; return 1; } - i++; } - else if (arg.compare("--verbose", Qt::CaseSensitive) == 0 - || arg.compare("-v", Qt::CaseSensitive) == 0) + else if (arg == "--verbose" || arg == "-v") loglevel=2; - else if (arg.compare("--quiet", Qt::CaseSensitive) == 0 - || arg.compare("-q", Qt::CaseSensitive) == 0) + else if (arg == "--quiet" || arg == "-q") loglevel=0; else errstream << "unknown command line option " << arg << endl; } else { exeFile = arg; - i++; - for(;i<args.size();i++) { - cmdLine.append(args.at(i)); + while(it.hasNext()) { + cmdLine.append(it.next()); } } } - if (exeFile.isEmpty() && sisFile.isEmpty()) { + if (exeFile.isEmpty() && sisFile.isEmpty() && + (downloadLocalFile.isEmpty() || downloadRemoteFile.isEmpty())) { printUsage(outstream, args[0]); return 1; } @@ -180,6 +182,10 @@ int main(int argc, char *argv[]) launcher->setFileName(QString("c:\\sys\\bin\\") + info.fileName()); launcher->setCommandLineArgs(cmdLine); } + if (!downloadRemoteFile.isEmpty() && !downloadLocalFile.isEmpty()) { + launcher->addStartupActions(trk::Launcher::ActionDownload); + launcher->setDownloadFileName(downloadRemoteFile, downloadLocalFile); + } if (loglevel > 0) outstream << "Connecting to target via " << serialPortName << endl; launcher->setTrkServerName(serialPortName); diff --git a/tools/runonphone/symbianutils/launcher.cpp b/tools/runonphone/symbianutils/launcher.cpp index 92b494a..fa509e7 100644 --- a/tools/runonphone/symbianutils/launcher.cpp +++ b/tools/runonphone/symbianutils/launcher.cpp @@ -54,6 +54,8 @@ #include <QtCore/QFile> #include <QtCore/QScopedPointer> +#include <cstdio> + namespace trk { struct LauncherPrivate { @@ -62,7 +64,8 @@ struct LauncherPrivate { QString destinationFileName; uint copyFileHandle; QScopedPointer<QByteArray> data; - int position; + qint64 position; + QScopedPointer<QFile> localFile; }; explicit LauncherPrivate(const TrkDevicePtr &d); @@ -76,6 +79,7 @@ struct LauncherPrivate { Session m_session; // global-ish data (process id, target information) CopyState m_copyState; + CopyState m_downloadState; QString m_fileName; QStringList m_commandLineArgs; QString m_installFileName; @@ -158,6 +162,12 @@ void Launcher::setCopyFileName(const QString &srcName, const QString &dstName) d->m_copyState.destinationFileName = dstName; } +void Launcher::setDownloadFileName(const QString &srcName, const QString &dstName) +{ + d->m_downloadState.sourceFileName = srcName; + d->m_downloadState.destinationFileName = dstName; +} + void Launcher::setInstallFileName(const QString &name) { d->m_installFileName = name; @@ -193,10 +203,26 @@ bool Launcher::startServer(QString *errorMessage) { errorMessage->clear(); if (d->m_verbose) { - const QString msg = QString::fromLatin1("Port=%1 Executable=%2 Arguments=%3 Package=%4 Remote Package=%5 Install file=%6") - .arg(trkServerName(), d->m_fileName, - d->m_commandLineArgs.join(QString(QLatin1Char(' '))), - d->m_copyState.sourceFileName, d->m_copyState.destinationFileName, d->m_installFileName); + QString msg; + QTextStream str(&msg); + str.setIntegerBase(16); + str << "Actions=0x" << d->m_startupActions; + str.setIntegerBase(10); + str << " Port=" << trkServerName(); + if (!d->m_fileName.isEmpty()) + str << " Executable=" << d->m_fileName; + if (!d->m_commandLineArgs.isEmpty()) + str << " Arguments= " << d->m_commandLineArgs.join(QString(QLatin1Char(' '))); + if (!d->m_copyState.sourceFileName.isEmpty()) + str << " Package/Source=" << d->m_copyState.sourceFileName; + if (!d->m_copyState.destinationFileName.isEmpty()) + str << " Remote Package/Destination=" << d->m_copyState.destinationFileName; + if (!d->m_downloadState.sourceFileName.isEmpty()) + str << " Source=" << d->m_downloadState.sourceFileName; + if (!d->m_downloadState.destinationFileName.isEmpty()) + str << " Destination=" << d->m_downloadState.destinationFileName; + if (!d->m_installFileName.isEmpty()) + str << " Install file=" << d->m_installFileName; logMessage(msg); } if (d->m_startupActions & ActionCopy) { @@ -251,6 +277,8 @@ void Launcher::handleConnect(const TrkResult &result) installRemotePackageSilently(); else if (d->m_startupActions & ActionRun) startInferiorIfNeeded(); + else if (d->m_startupActions & ActionDownload) + copyFileFromRemote(); } void Launcher::setVerbose(int v) @@ -416,7 +444,7 @@ void Launcher::handleResult(const TrkResult &result) if (itemType == 0 // process && result.data.size() >= 10 && d->m_session.pid == extractInt(result.data.data() + 6)) { - disconnectTrk(); + copyFileFromRemote(); } break; } @@ -471,23 +499,99 @@ void Launcher::handleTrkVersion(const TrkResult &result) } } +static inline QString msgCannotOpenRemoteFile(const QString &fileName, const QString &message) +{ + return Launcher::tr("Cannot open remote file '%1': %2").arg(fileName, message); +} + +static inline QString msgCannotOpenLocalFile(const QString &fileName, const QString &message) +{ + return Launcher::tr("Cannot open '%1': %2").arg(fileName, message); +} + void Launcher::handleFileCreation(const TrkResult &result) { if (result.errorCode() || result.data.size() < 6) { - emit canNotCreateFile(d->m_copyState.destinationFileName, result.errorString()); + const QString msg = msgCannotOpenRemoteFile(d->m_copyState.destinationFileName, result.errorString()); + logMessage(msg); + emit canNotCreateFile(d->m_copyState.destinationFileName, msg); disconnectTrk(); return; } const char *data = result.data.data(); d->m_copyState.copyFileHandle = extractInt(data + 2); - QFile file(d->m_copyState.sourceFileName); - file.open(QIODevice::ReadOnly); - d->m_copyState.data.reset(new QByteArray(file.readAll())); + const QString localFileName = d->m_copyState.sourceFileName; + QFile file(localFileName); d->m_copyState.position = 0; + if (!file.open(QIODevice::ReadOnly)) { + const QString msg = msgCannotOpenLocalFile(localFileName, file.errorString()); + logMessage(msg); + emit canNotOpenLocalFile(localFileName, msg); + closeRemoteFile(true); + disconnectTrk(); + return; + } + d->m_copyState.data.reset(new QByteArray(file.readAll())); file.close(); continueCopying(); } +void Launcher::handleFileOpened(const TrkResult &result) +{ + if (result.errorCode() || result.data.size() < 6) { + const QString msg = msgCannotOpenRemoteFile(d->m_downloadState.sourceFileName, result.errorString()); + logMessage(msg); + emit canNotOpenFile(d->m_downloadState.sourceFileName, msg); + disconnectTrk(); + return; + } + d->m_downloadState.position = 0; + const QString localFileName = d->m_downloadState.destinationFileName; + bool opened = false; + if (localFileName == QLatin1String("-")) { + d->m_downloadState.localFile.reset(new QFile); + opened = d->m_downloadState.localFile->open(stdout, QFile::WriteOnly); + } else { + d->m_downloadState.localFile.reset(new QFile(localFileName)); + opened = d->m_downloadState.localFile->open(QFile::WriteOnly | QFile::Truncate); + } + if (!opened) { + const QString msg = msgCannotOpenLocalFile(localFileName, d->m_downloadState.localFile->errorString()); + logMessage(msg); + emit canNotOpenLocalFile(localFileName, msg); + closeRemoteFile(true); + disconnectTrk(); + } + continueReading(); +} + +void Launcher::continueReading() +{ + QByteArray ba; + appendInt(&ba, d->m_downloadState.copyFileHandle, TargetByteOrder); + appendShort(&ba, 2048, TargetByteOrder); + d->m_device->sendTrkMessage(TrkReadFile, TrkCallback(this, &Launcher::handleRead), ba); +} + +void Launcher::handleRead(const TrkResult &result) +{ + if (result.errorCode() || result.data.size() < 4) { + d->m_downloadState.localFile->close(); + closeRemoteFile(true); + disconnectTrk(); + } else { + int length = extractShort(result.data.data() + 2); + //TRK doesn't tell us the file length, so we need to keep reading until it returns 0 length + if (length > 0) { + d->m_downloadState.localFile->write(result.data.data() + 4, length); + continueReading(); + } else { + closeRemoteFile(true); + disconnectTrk(); + } + } +} + void Launcher::handleCopy(const TrkResult &result) { if (result.errorCode() || result.data.size() < 4) { @@ -501,13 +605,14 @@ void Launcher::handleCopy(const TrkResult &result) void Launcher::continueCopying(uint lastCopiedBlockSize) { - int size = d->m_copyState.data->length(); + qint64 size = d->m_copyState.data->length(); d->m_copyState.position += lastCopiedBlockSize; if (size == 0) emit copyProgress(100); else { - int percent = qMin((d->m_copyState.position*100)/size, 100); - emit copyProgress(percent); + const qint64 hundred = 100; + const qint64 percent = qMin( (d->m_copyState.position * hundred) / size, hundred); + emit copyProgress(static_cast<int>(percent)); } if (d->m_copyState.position < size) { QByteArray ba; @@ -540,6 +645,8 @@ void Launcher::handleFileCopied(const TrkResult &result) installRemotePackageSilently(); else if (d->m_startupActions & ActionRun) startInferiorIfNeeded(); + else if (d->m_startupActions & ActionDownload) + copyFileFromRemote(); else disconnectTrk(); } @@ -603,17 +710,18 @@ void Launcher::handleSupportMask(const TrkResult &result) return; const char *data = result.data.data() + 1; - QString str = QLatin1String("SUPPORTED: "); - for (int i = 0; i < 32; ++i) { - //str.append(" [" + formatByte(data[i]) + "]: "); - for (int j = 0; j < 8; ++j) { - if (data[i] & (1 << j)) { - str.append(QString::number(i * 8 + j, 16)); - str.append(QLatin1Char(' ')); + if (d->m_verbose > 1) { + QString str = QLatin1String("SUPPORTED: "); + for (int i = 0; i < 32; ++i) { + for (int j = 0; j < 8; ++j) { + if (data[i] & (1 << j)) { + str.append(QString::number(i * 8 + j, 16)); + str.append(QLatin1Char(' ')); + } } } + logMessage(str); } - logMessage(str); } void Launcher::cleanUp() @@ -677,11 +785,20 @@ void Launcher::copyFileToRemote() { emit copyingStarted(); QByteArray ba; - ba.append(char(10)); + ba.append(char(10)); //kDSFileOpenWrite | kDSFileOpenBinary appendString(&ba, d->m_copyState.destinationFileName.toLocal8Bit(), TargetByteOrder, false); d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileCreation), ba); } +void Launcher::copyFileFromRemote() +{ + emit copyingStarted(); + QByteArray ba; + ba.append(char(9)); //kDSFileOpenRead | kDSFileOpenBinary + appendString(&ba, d->m_downloadState.sourceFileName.toLocal8Bit(), TargetByteOrder, false); + d->m_device->sendTrkMessage(TrkOpenFile, TrkCallback(this, &Launcher::handleFileOpened), ba); +} + void Launcher::installRemotePackageSilently() { emit installingStarted(); @@ -702,6 +819,8 @@ void Launcher::handleInstallPackageFinished(const TrkResult &result) } if (d->m_startupActions & ActionRun) { startInferiorIfNeeded(); + } else if (d->m_startupActions & ActionDownload) { + copyFileFromRemote(); } else { disconnectTrk(); } diff --git a/tools/runonphone/symbianutils/launcher.h b/tools/runonphone/symbianutils/launcher.h index c47285c..6db69d0 100644 --- a/tools/runonphone/symbianutils/launcher.h +++ b/tools/runonphone/symbianutils/launcher.h @@ -69,6 +69,7 @@ public: ActionInstall = 0x2, ActionCopyInstall = ActionCopy | ActionInstall, ActionRun = 0x4, + ActionDownload = 0x8, ActionCopyRun = ActionCopy | ActionRun, ActionInstallRun = ActionInstall | ActionRun, ActionCopyInstallRun = ActionCopy | ActionInstall | ActionRun @@ -94,6 +95,7 @@ public: QString trkServerName() const; void setFileName(const QString &name); void setCopyFileName(const QString &srcName, const QString &dstName); + void setDownloadFileName(const QString &srcName, const QString &dstName); void setInstallFileName(const QString &name); void setCommandLineArgs(const QStringList &args); bool startServer(QString *errorMessage); @@ -132,6 +134,8 @@ signals: void copyingStarted(); void canNotConnect(const QString &errorMessage); void canNotCreateFile(const QString &filename, const QString &errorMessage); + void canNotOpenFile(const QString &filename, const QString &errorMessage); + void canNotOpenLocalFile(const QString &filename, const QString &errorMessage); void canNotWriteFile(const QString &filename, const QString &errorMessage); void canNotCloseFile(const QString &filename, const QString &errorMessage); void installingStarted(); @@ -164,8 +168,11 @@ private: void handleRemoteProcessKilled(const TrkResult &result); void handleConnect(const TrkResult &result); void handleFileCreation(const TrkResult &result); + void handleFileOpened(const TrkResult &result); void handleCopy(const TrkResult &result); + void handleRead(const TrkResult &result); void continueCopying(uint lastCopiedBlockSize = 0); + void continueReading(); void closeRemoteFile(bool failed = false); void handleFileCopied(const TrkResult &result); void handleInstallPackageFinished(const TrkResult &result); @@ -177,6 +184,7 @@ private: void handleTrkVersion(const TrkResult &result); void copyFileToRemote(); + void copyFileFromRemote(); void installRemotePackageSilently(); void startInferiorIfNeeded(); void handleFinished(); diff --git a/tools/runonphone/symbianutils/trkutils.h b/tools/runonphone/symbianutils/trkutils.h index 3a485c7..553fc7d 100644 --- a/tools/runonphone/symbianutils/trkutils.h +++ b/tools/runonphone/symbianutils/trkutils.h @@ -43,6 +43,7 @@ #define DEBUGGER_TRK_UTILS #include "symbianutils_global.h" + #include <QtCore/QByteArray> #include <QtCore/QHash> #include <QtCore/QStringList> @@ -57,33 +58,81 @@ namespace trk { typedef unsigned char byte; enum Command { + //meta commands TrkPing = 0x00, TrkConnect = 0x01, TrkDisconnect = 0x02, + TrkReset = 0x03, TrkVersions = 0x04, TrkSupported = 0x05, TrkCpuType = 0x06, + TrkConfigTransport = 0x07, + TrkVersions2 = 0x08, TrkHostVersions = 0x09, + + //state commands + TrkReadMemory = 0x10, + TrkWriteMemory = 0x11, + TrkReadRegisters = 0x12, + TrkWriteRegisters = 0x13, + TrkFillMemory = 0x14, + TrkCopyMemory = 0x15, + TrkFlushCache = 0x16, + + //execution commands TrkContinue = 0x18, + TrkStep = 0x19, + TrkStop = 0x1a, + TrkSetBreak = 0x1b, + TrkClearBreak = 0x1c, + TrkDownload = 0x1d, + TrkModifyBreakThread = 0x1e, + + //host -> target IO management + TrkNotifyFileInput = 0x20, + TrkBlockFileIo = 0x21, + + //host -> target os commands TrkCreateItem = 0x40, TrkDeleteItem = 0x41, + TrkReadInfo = 0x42, + TrkWriteInfo = 0x43, TrkWriteFile = 0x48, + TrkReadFile = 0x49, TrkOpenFile = 0x4a, TrkCloseFile = 0x4b, + TrkPositionFile = 0x4c, TrkInstallFile = 0x4d, TrkInstallFile2 = 0x4e, + TrkPhoneSwVersion = 0x4f, + TrkPhoneName = 0x50, + TrkVersions3 = 0x51, + + //replies TrkNotifyAck = 0x80, TrkNotifyNak = 0xff, + + //target -> host notification TrkNotifyStopped = 0x90, TrkNotifyException = 0x91, TrkNotifyInternalError = 0x92, + TrkNotifyStopped2 = 0x94, + + //target -> host OS notification TrkNotifyCreated = 0xa0, TrkNotifyDeleted = 0xa1, TrkNotifyProcessorStarted = 0xa2, TrkNotifyProcessorStandBy = 0xa6, - TrkNotifyProcessorReset = 0xa7 + TrkNotifyProcessorReset = 0xa7, + + //target -> host support commands (these are defined but not implemented in TRK) + TrkDSWriteFile = 0xd0, + TrkDSReadFile = 0xd1, + TrkDSOpenFile = 0xd2, + TrkDSCloseFile = 0xd3, + TrkDSPositionFile = 0xd4 }; inline byte extractByte(const char *data) { return *data; } @@ -118,7 +167,7 @@ struct SYMBIANUTILS_EXPORT Library struct SYMBIANUTILS_EXPORT TrkAppVersion { TrkAppVersion(); - void reset(); + void reset(); int trkMajor; int trkMinor; |