From fdf6120d17ec49e1aa06477cd10fbf31bd33a3d6 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Thu, 20 Aug 2009 15:58:20 +0200 Subject: [PATCH] Trk: Add device class. --- tests/manual/trk/adapter.cpp | 7 +- tests/manual/trk/launcher.cpp | 213 +++----------------- tests/manual/trk/launcher.h | 8 +- tests/manual/trk/trkdevice.cpp | 323 +++++++++++++++++++++++++++++++ tests/manual/trk/trkdevice.h | 84 ++++++++ tests/manual/trk/trklauncher.pri | 4 +- tests/manual/trk/trkserver.cpp | 7 +- tests/manual/trk/trkutils.cpp | 30 +-- tests/manual/trk/trkutils.h | 3 +- 9 files changed, 473 insertions(+), 206 deletions(-) create mode 100644 tests/manual/trk/trkdevice.cpp create mode 100644 tests/manual/trk/trkdevice.h diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp index 0f28ad8f012..18d06b5bd13 100644 --- a/tests/manual/trk/adapter.cpp +++ b/tests/manual/trk/adapter.cpp @@ -1059,7 +1059,7 @@ void Adapter::tryTrkRead() while (TryReadFile(m_winComDevice, buffer, BUFFERSIZE, &charsRead, NULL)) { m_trkReadQueue.append(buffer, charsRead); totalCharsRead += charsRead; - if (isValidTrkResult(m_trkReadQueue)) + if (isValidTrkResult(m_trkReadQueue, m_serialFrame)) break; } if (!totalCharsRead) @@ -1074,8 +1074,9 @@ void Adapter::tryTrkRead() return; } - while (!m_trkReadQueue.isEmpty()) - handleResult(extractResult(&m_trkReadQueue, m_serialFrame)); + TrkResult r; + while (extractResult(&m_trkReadQueue, m_serialFrame, &r)) + handleResult(r); m_trkWriteBusy = false; } diff --git a/tests/manual/trk/launcher.cpp b/tests/manual/trk/launcher.cpp index 389548fd053..6e3a68ee3f3 100644 --- a/tests/manual/trk/launcher.cpp +++ b/tests/manual/trk/launcher.cpp @@ -29,6 +29,7 @@ #include "launcher.h" #include "trkutils.h" +#include "trkdevice.h" #include <QtCore/QTimer> #include <QtCore/QDateTime> @@ -37,60 +38,6 @@ #include <QtCore/QQueue> #include <QtCore/QFile> -#ifdef Q_OS_WIN -# include <windows.h> -#else -# include <stdio.h> -# include <sys/ioctl.h> -# include <termios.h> -# include <errno.h> -# include <string.h> -#endif - -#ifdef Q_OS_WIN - -// 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, - DWORD nNumberOfBytesToRead, - LPDWORD lpNumberOfBytesRead, - LPOVERLAPPED lpOverlapped) -{ - COMSTAT comStat; - if (!ClearCommError(hFile, NULL, &comStat)){ - qDebug() << "ClearCommError() failed"; - return FALSE; - } - if (comStat.cbInQue == 0) { - *lpNumberOfBytesRead = 0; - return FALSE; - } - return ReadFile(hFile, - lpBuffer, - qMin(comStat.cbInQue, nNumberOfBytesToRead), - lpNumberOfBytesRead, - lpOverlapped); -} -#endif - namespace trk { struct TrkMessage { @@ -104,12 +51,7 @@ struct TrkMessage { struct LauncherPrivate { LauncherPrivate(); -#ifdef Q_OS_WIN - HANDLE m_hdevice; -#else - QFile m_file; -#endif - + TrkDevice m_device; QString m_trkServerName; QByteArray m_trkReadBuffer; @@ -128,18 +70,13 @@ struct LauncherPrivate { QString m_copySrcFileName; QString m_copyDstFileName; QString m_installFileName; - bool m_serialFrame; int m_verbose; }; LauncherPrivate::LauncherPrivate() : -#ifdef Q_OS_WIN - m_hdevice(0), -#endif m_trkWriteToken(0), m_trkWriteBusy(false), m_timerId(-1), - m_serialFrame(true), m_verbose(0) { } @@ -149,6 +86,7 @@ LauncherPrivate::LauncherPrivate() : Launcher::Launcher() : d(new LauncherPrivate) { + connect(&d->m_device, SIGNAL(messageReceived(TrkResult)), this, SLOT(handleResult(TrkResult))); } Launcher::~Launcher() @@ -180,7 +118,12 @@ void Launcher::setInstallFileName(const QString &name) void Launcher::setSerialFrame(bool b) { - d->m_serialFrame = b; + d->m_device.setSerialFrame(b); +} + +bool Launcher::serialFrame() const +{ + return d->m_device.serialFrame(); } bool Launcher::startServer(QString *errorMessage) @@ -190,7 +133,7 @@ bool Launcher::startServer(QString *errorMessage) .arg(d->m_trkServerName, d->m_fileName, d->m_copySrcFileName, d->m_copyDstFileName, d->m_installFileName); logMessage(msg); } - if (!openTrkPort(d->m_trkServerName, errorMessage)) + if (!d->m_device.open(d->m_trkServerName, errorMessage)) return false; d->m_timerId = startTimer(100); sendTrkInitialPing(); @@ -210,6 +153,7 @@ bool Launcher::startServer(QString *errorMessage) void Launcher::setVerbose(int v) { d->m_verbose = v; + d->m_device.setVerbose(v > 1); } void Launcher::installAndRun() @@ -226,60 +170,11 @@ void Launcher::logMessage(const QString &msg) qDebug() << "ADAPTER: " << qPrintable(msg); } -bool Launcher::openTrkPort(const QString &port, QString *errorMessage) -{ -#ifdef Q_OS_WIN - d->m_hdevice = CreateFile(port.toStdWString().c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (INVALID_HANDLE_VALUE == d->m_hdevice){ - *errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, winErrorMessage(GetLastError())); - logMessage(*errorMessage); - return false; - } - return true; -#else - d->m_file.setFileName(port); - if (!d->m_file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) { - *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->m_file.errorString()); - return false; - } - - struct termios termInfo; - if (tcgetattr(d->m_file.handle(), &termInfo) < 0) { - *errorMessage = QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))); - return false; - } - // Turn off terminal echo as not get messages back, among other things - termInfo.c_cflag|=CREAD|CLOCAL; - termInfo.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); - termInfo.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); - termInfo.c_oflag&=(~OPOST); - termInfo.c_cc[VMIN]=0; - termInfo.c_cc[VINTR] = _POSIX_VDISABLE; - termInfo.c_cc[VQUIT] = _POSIX_VDISABLE; - termInfo.c_cc[VSTART] = _POSIX_VDISABLE; - termInfo.c_cc[VSTOP] = _POSIX_VDISABLE; - termInfo.c_cc[VSUSP] = _POSIX_VDISABLE; - if (tcsetattr(d->m_file.handle(), TCSAFLUSH, &termInfo) < 0) { - *errorMessage = QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))); - return false; - } - return true; -#endif -} - void Launcher::timerEvent(QTimerEvent *) { if (d->m_verbose>1) qDebug("."); tryTrkWrite(); - tryTrkRead(); } byte Launcher::nextTrkWriteToken() @@ -333,7 +228,7 @@ void Launcher::sendTrkAck(byte token) msg.data.append('\0'); // The acknowledgement must not be queued! //queueMessage(msg); - trkWrite(msg); + trkWriteRawMessage(msg); // 01 90 00 07 7e 80 01 00 7d 5e 7e } @@ -353,80 +248,25 @@ void Launcher::tryTrkWrite() trkWrite(msg); } -void Launcher::trkWrite(const TrkMessage &msg) +void Launcher::trkWriteRawMessage(const TrkMessage &msg) { - QByteArray ba = frameMessage(msg.code, msg.token, msg.data, d->m_serialFrame); - - d->m_writtenTrkMessages.insert(msg.token, msg); - d->m_trkWriteBusy = true; - + const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, serialFrame()); logMessage("WRITE: " + stringFromArray(ba)); - -#ifdef Q_OS_WIN - DWORD charsWritten; - if (!WriteFile(d->m_hdevice, ba.data(), ba.size(), &charsWritten, NULL)) - logMessage("WRITE ERROR: "); - - //logMessage("WRITE: " + stringFromArray(ba)); - FlushFileBuffers(d->m_hdevice); -#else - if (d->m_file.write(ba) == -1 || !d->m_file.flush()) - logMessage(QString::fromLatin1("Cannot write: %1").arg(d->m_file.errorString())); -#endif -} - -#ifndef Q_OS_WIN -static inline int bytesAvailable(int fileNo) -{ - int numBytes; - const int rc = ioctl(fileNo, FIONREAD, &numBytes); - if (rc < 0) - numBytes=0; - return numBytes; + QString errorMessage; + if (!d->m_device.write(ba, &errorMessage)) + logMessage(errorMessage); } -#endif -void Launcher::tryTrkRead() +void Launcher::trkWrite(const TrkMessage &msg) { -#ifdef Q_OS_WIN - const DWORD BUFFERSIZE = 1024; - char buffer[BUFFERSIZE]; - DWORD charsRead; - - while (TryReadFile(d->m_hdevice, buffer, BUFFERSIZE, &charsRead, NULL)) { - d->m_trkReadQueue.append(buffer, charsRead); - if (isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame)) - break; - } - const ushort len = isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame); - if (!len) { - logMessage("Partial message: " + stringFromArray(d->m_trkReadQueue)); - return; - } -#else - const int size = bytesAvailable(d->m_file.handle()); - if (!size) - return; - const QByteArray data = d->m_file.read(size); - d->m_trkReadQueue.append(data); - const ushort len = isValidTrkResult(d->m_trkReadQueue, d->m_serialFrame); - if (!len) { - if (d->m_trkReadQueue.size() > 10) { - logMessage(QString::fromLatin1("Unable to extract message from '%1' '%2'"). - arg(QLatin1String(d->m_trkReadQueue.toHex())).arg(QString::fromAscii(d->m_trkReadQueue))); - } - return; - } -#endif // Q_OS_WIN - logMessage(QString::fromLatin1("READ: %1 bytes %2").arg(len).arg(stringFromArray(d->m_trkReadQueue))); - handleResult(extractResult(&d->m_trkReadQueue, d->m_serialFrame)); - - d->m_trkWriteBusy = false; + d->m_writtenTrkMessages.insert(msg.token, msg); + d->m_trkWriteBusy = true; + trkWriteRawMessage(msg); } - void Launcher::handleResult(const TrkResult &result) { + d->m_trkWriteBusy = false; QByteArray prefix = "READ BUF: "; QByteArray str = result.toString().toUtf8(); if (result.isDebugOutput) { // handle application output @@ -518,10 +358,13 @@ void Launcher::handleResult(const TrkResult &result) break; } case TrkNotifyDeleted: { // NotifyDeleted - logMessage(prefix + "NOTE: LIBRARY UNLOAD: " + str); + const ushort itemType = (unsigned char)result.data.at(1); + const ushort len = result.data.size() > 12 ? extractShort(result.data.data() + 10) : ushort(0); + const QString name = len ? QString::fromAscii(result.data.mid(13, len)) : QString(); + logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). + arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). + arg(name)); sendTrkAck(result.token); - const char *data = result.data.data(); - ushort itemType = extractShort(data); if (itemType == 0) { // process sendTrkMessage(TrkDisconnect, CB(waitForTrkFinished)); } diff --git a/tests/manual/trk/launcher.h b/tests/manual/trk/launcher.h index 27af42425e1..d37aab16bb6 100644 --- a/tests/manual/trk/launcher.h +++ b/tests/manual/trk/launcher.h @@ -53,6 +53,7 @@ public: bool startServer(QString *errorMessage); void setVerbose(int v); void setSerialFrame(bool b); + bool serialFrame() const; signals: void copyingStarted(); @@ -65,8 +66,10 @@ signals: public slots: void terminate(); +private slots: + void handleResult(const TrkResult &data); + private: - bool openTrkPort(const QString &port, QString *errorMessage); // or server name for local server void sendTrkMessage(unsigned char code, TrkCallBack callBack = 0, const QByteArray &data = QByteArray(), @@ -77,6 +80,7 @@ private: void tryTrkRead(); // actually writes a message to the device void trkWrite(const TrkMessage &msg); + void trkWriteRawMessage(const TrkMessage &msg); // convienience messages void sendTrkInitialPing(); void sendTrkAck(unsigned char token); @@ -99,8 +103,6 @@ private: void waitForTrkFinished(const TrkResult &data); void handleAndReportCreateProcess(const TrkResult &result); - void handleResult(const TrkResult &data); - void copyFileToRemote(); void installRemotePackageSilently(const QString &filename); void installAndRun(); diff --git a/tests/manual/trk/trkdevice.cpp b/tests/manual/trk/trkdevice.cpp new file mode 100644 index 00000000000..a045fa41027 --- /dev/null +++ b/tests/manual/trk/trkdevice.cpp @@ -0,0 +1,323 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "trkdevice.h" +#include "trkutils.h" + +#include <QtCore/QString> +#include <QtCore/QDebug> + +#ifdef Q_OS_WIN +# include <windows.h> +#else +# include <QtCore/QFile> + +# include <stdio.h> +# include <sys/ioctl.h> +# include <termios.h> +# include <errno.h> +# include <string.h> +#endif + +enum { TimerInterval = 100 }; + +#ifdef Q_OS_WIN + +// 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, + DWORD nNumberOfBytesToRead, + LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped) +{ + COMSTAT comStat; + if (!ClearCommError(hFile, NULL, &comStat)){ + qDebug() << "ClearCommError() failed"; + return FALSE; + } + if (comStat.cbInQue == 0) { + *lpNumberOfBytesRead = 0; + return FALSE; + } + return ReadFile(hFile, + lpBuffer, + qMin(comStat.cbInQue, nNumberOfBytesToRead), + lpNumberOfBytesRead, + lpOverlapped); +} +#endif + +namespace trk { + +struct TrkDevicePrivate { + TrkDevicePrivate(); +#ifdef Q_OS_WIN + HANDLE hdevice; +#else + QFile file; +#endif + + QByteArray trkReadBuffer; + bool trkWriteBusy; + int timerId; + bool serialFrame; + bool verbose; + QString errorString; +}; + +TrkDevicePrivate::TrkDevicePrivate() : +#ifdef Q_OS_WIN + hdevice(INVALID_HANDLE_VALUE), +#endif + trkWriteBusy(false), + timerId(-1), + serialFrame(true), + verbose(false) +{ + +} + +TrkDevice::TrkDevice(QObject *parent) : + QObject(parent), + d(new TrkDevicePrivate) +{ +} + +bool TrkDevice::open(const QString &port, QString *errorMessage) +{ + close(); +#ifdef Q_OS_WIN + d->hdevice = CreateFile(port.toStdWString().c_str(), + GENERIC_READ | GENERIC_WRITE, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (INVALID_HANDLE_VALUE == d->hdevice) { + *errorMessage = QString::fromLatin1("Could not open device '%1': %2").arg(port, winErrorMessage(GetLastError())); + return false; + } + d->timerId = startTimer(TimerInterval); + return true; +#else + d->file.setFileName(port); + if (!d->file.open(QIODevice::ReadWrite|QIODevice::Unbuffered)) { + *errorMessage = QString::fromLatin1("Cannot open %1: %2").arg(port, d->file.errorString()); + return false; + } + + struct termios termInfo; + if (tcgetattr(d->file.handle(), &termInfo) < 0) { + *errorMessage = QString::fromLatin1("Unable to retrieve terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))); + return false; + } + // Turn off terminal echo as not get messages back, among other things + termInfo.c_cflag|=CREAD|CLOCAL; + termInfo.c_lflag&=(~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG)); + termInfo.c_iflag&=(~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY)); + termInfo.c_oflag&=(~OPOST); + termInfo.c_cc[VMIN]=0; + termInfo.c_cc[VINTR] = _POSIX_VDISABLE; + termInfo.c_cc[VQUIT] = _POSIX_VDISABLE; + termInfo.c_cc[VSTART] = _POSIX_VDISABLE; + termInfo.c_cc[VSTOP] = _POSIX_VDISABLE; + termInfo.c_cc[VSUSP] = _POSIX_VDISABLE; + if (tcsetattr(d->file.handle(), TCSAFLUSH, &termInfo) < 0) { + *errorMessage = QString::fromLatin1("Unable to apply terminal settings: %1 %2").arg(errno).arg(QString::fromAscii(strerror(errno))); + return false; + } + d->timerId = startTimer(TimerInterval); + return true; +#endif +} + + +TrkDevice::~TrkDevice() +{ + close(); + delete d; +} + +void TrkDevice::close() +{ + if (!isOpen()) + return; + if (d->timerId != -1) { + killTimer(d->timerId); + d->timerId = -1; + } +#ifdef Q_OS_WIN + CloseHandle(d->hdevice); +#else + d->file.close(); +#endif + if (d->verbose) + qDebug() << "Close"; +} + +bool TrkDevice::isOpen() const +{ +#ifdef Q_OS_WIN + return d->hdevice != INVALID_HANDLE_VALUE; +#else + return d->file.isOpen(); +#endif +} + +QString TrkDevice::errorString() const +{ + return d->errorString; +} + +bool TrkDevice::serialFrame() const +{ + return d->serialFrame; +} + +void TrkDevice::setSerialFrame(bool f) +{ + d->serialFrame = f; +} + +bool TrkDevice::verbose() const +{ + return d->verbose; +} + +void TrkDevice::setVerbose(bool b) +{ + d->verbose = b; +} + +bool TrkDevice::write(const QByteArray &data, QString *errorMessage) +{ + if (d->verbose) + qDebug() << ">WRITE" << data.toHex(); +#ifdef Q_OS_WIN + DWORD charsWritten; + if (!WriteFile(d->hdevice, data.data(), data.size(), &charsWritten, NULL)) { + *errorMessage = QString::fromLatin1("Error writing data: %1").arg(winErrorMessage(GetLastError())); + return false; + } + FlushFileBuffers(d->hdevice); + return true; +#else + if (d->file.write(data) == -1 || !d->file.flush()) { + *errorMessage = QString::fromLatin1("Cannot write: %1").arg(d->file.errorString()); + return false; + } + return true; +#endif +} + +#ifndef Q_OS_WIN +static inline int bytesAvailable(int fileNo) +{ + int numBytes; + const int rc = ioctl(fileNo, FIONREAD, &numBytes); + if (rc < 0) + numBytes=0; + return numBytes; +} +#endif + +void TrkDevice::tryTrkRead() +{ +#ifdef Q_OS_WIN + const DWORD BUFFERSIZE = 1024; + char buffer[BUFFERSIZE]; + DWORD charsRead; + DWORD totalCharsRead = 0; + + while (TryReadFile(d->hdevice, buffer, BUFFERSIZE, &charsRead, NULL)) { + totalCharsRead += charsRead; + d->trkReadBuffer.append(buffer, charsRead); + if (isValidTrkResult(d->trkReadBuffer, d->serialFrame)) + break; + } + if (d->verbose && totalCharsRead) + qDebug() << "Read" << d->trkReadBuffer.toHex(); + if (!totalCharsRead) + return; + const ushort len = isValidTrkResult(d->trkReadBuffer, d->serialFrame); + if (!len) { + d->errorString = QString::fromLatin1("Partial message: %1").arg(stringFromArray(d->trkReadBuffer)); + qWarning("%s\n", qPrintable(d->errorString)); + return; + } +#else + const int size = bytesAvailable(d->file.handle()); + if (!size) + return; + const QByteArray data = d->file.read(size); + d->trkReadBuffer.append(data); + const ushort len = isValidTrkResult(d->trkReadBuffer, d->serialFrame); + if (!len) { + if (d->trkReadBuffer.size() > 10) { + d->errorString = QString::fromLatin1("Unable to extract message from '%1' '%2'"). + arg(QLatin1String(d->trkReadBuffer.toHex())).arg(QString::fromAscii(d->trkReadBuffer)); + qWarning("%s\n", qPrintable(d->errorString)); + } + return; + } +#endif // Q_OS_WIN + TrkResult r; + while (extractResult(&d->trkReadBuffer, d->serialFrame, &r)) { + if (d->verbose) + qDebug() << "Read TrkResult " << r.data.toHex(); + emit messageReceived(r); + } +} + +void TrkDevice::timerEvent(QTimerEvent *) +{ + tryTrkRead(); +} + +} // namespace trk diff --git a/tests/manual/trk/trkdevice.h b/tests/manual/trk/trkdevice.h new file mode 100644 index 00000000000..7392c8a62c3 --- /dev/null +++ b/tests/manual/trk/trkdevice.h @@ -0,0 +1,84 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef TRKDEVICE_H +#define TRKDEVICE_H + +#include <QtCore/QObject> +#include <QtCore/QVariant> +#include <QtCore/QByteArray> + +namespace trk { + +struct TrkResult; +struct TrkDevicePrivate; + +/* TrkDevice: Implements a Windows COM or Linux device for + * Trk communications. Provides synchronous write and asynchronous + * read operation. + * The serialFrames property specifies whether packets are encapsulated in + * "0x90 <length>" frames, which is currently the case for serial ports. */ + +class TrkDevice : public QObject +{ + Q_DISABLE_COPY(TrkDevice) + Q_OBJECT + Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame) + Q_PROPERTY(bool verbose READ verbose WRITE setVerbose) +public: + explicit TrkDevice(QObject *parent = 0); + virtual ~TrkDevice(); + + bool open(const QString &port, QString *errorMessage); + bool isOpen() const; + void close(); + + QString errorString() const; + + bool serialFrame() const; + void setSerialFrame(bool f); + + bool verbose() const; + void setVerbose(bool b); + + bool write(const QByteArray &data, QString *errorMessage); + +signals: + void messageReceived(const TrkResult&); + +private: + void tryTrkRead(); + virtual void timerEvent(QTimerEvent *ev); + + TrkDevicePrivate *d; +}; + +} // namespace trk + +#endif // TRKDEVICE_H diff --git a/tests/manual/trk/trklauncher.pri b/tests/manual/trk/trklauncher.pri index b39ec0a816c..8824c4a5c40 100644 --- a/tests/manual/trk/trklauncher.pri +++ b/tests/manual/trk/trklauncher.pri @@ -1,6 +1,8 @@ DEFINES += DEBUG_TRK=0 INCLUDEPATH *= $$PWD SOURCES += $$PWD/launcher.cpp \ - $$PWD/trkutils.cpp + $$PWD/trkutils.cpp \ + $$PWD/trkdevice.cpp HEADERS += $$PWD/trkutils.h \ + $$PWD/trkdevice.h \ $$PWD/launcher.h diff --git a/tests/manual/trk/trkserver.cpp b/tests/manual/trk/trkserver.cpp index e764562c3c9..aa3b5534161 100644 --- a/tests/manual/trk/trkserver.cpp +++ b/tests/manual/trk/trkserver.cpp @@ -298,8 +298,11 @@ void TrkServer::readFromAdapter() if (packet != m_adapterReadBuffer) logMessage("buffer: " + stringFromArray(m_adapterReadBuffer)); - while (!m_adapterReadBuffer.isEmpty()) - handleAdapterMessage(extractResult(&m_adapterReadBuffer, m_serialFrame)); + while (!m_adapterReadBuffer.isEmpty()) { + TrkResult r; + while (extractResult(&m_adapterReadBuffer, m_serialFrame, &r)) + handleAdapterMessage(r); + } } void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data) diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index 1709cf31b3c..8b5622ed9fa 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -50,6 +50,14 @@ TrkResult::TrkResult() : { } +void TrkResult::clear() +{ + code = token= 0; + isDebugOutput = false; + data.clear(); + cookie = QVariant(); +} + QString TrkResult::toString() const { QString res = stringFromByte(code) + "[" + stringFromByte(token); @@ -114,20 +122,20 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame) return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size(); } -TrkResult extractResult(QByteArray *buffer, bool serialFrame) +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result) { - TrkResult result; + result->clear(); const ushort len = isValidTrkResult(*buffer, serialFrame); if (!len) - return result; + return false; // handle receiving application output, which is not a regular command const int delimiterPos = serialFrame ? 4 : 0; if (buffer->at(delimiterPos) != 0x7e) { - result.isDebugOutput = true; - result.data = buffer->mid(delimiterPos, len); - result.data.replace("\r\n", "\n"); + result->isDebugOutput = true; + result->data = buffer->mid(delimiterPos, len); + result->data.replace("\r\n", "\n"); *buffer->remove(0, delimiterPos + len); - return result; + return true; } // FIXME: what happens if the length contains 0xfe? // Assume for now that it passes unencoded! @@ -140,14 +148,14 @@ TrkResult extractResult(QByteArray *buffer, bool serialFrame) if (sum != 0xff) logMessage("*** CHECKSUM ERROR: " << byte(sum)); - result.code = data.at(0); - result.token = data.at(1); - result.data = data.mid(2, data.size() - 3); + result->code = data.at(0); + result->token = data.at(1); + result->data = data.mid(2, data.size() - 3); //logMessage(" REST BUF: " << stringFromArray(*buffer)); //logMessage(" CURR DATA: " << stringFromArray(data)); //QByteArray prefix = "READ BUF: "; //logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data()); - return result; + return true; } ushort extractShort(const char *data) diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index ce5baa79d4c..77e469b8068 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -172,6 +172,7 @@ struct Breakpoint struct TrkResult { TrkResult(); + void clear(); QString toString() const; // 0 for no error. int errorCode() const; @@ -187,7 +188,7 @@ struct TrkResult // the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame); ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame); -TrkResult extractResult(QByteArray *buffer, bool serialFrame); +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r); QByteArray errorMessage(byte code); QByteArray hexNumber(uint n, int digits = 0); uint swapEndian(uint in); -- GitLab