From 09dc43ba5cdbc6fe4effc9c1539308cf134de8c3 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint <Friedemann.Kleint@nokia.com> Date: Fri, 21 Aug 2009 16:34:06 +0200 Subject: [PATCH] Trk: Make adapter use TrkDevice --- tests/manual/trk/adapter.cpp | 423 +++++++-------------------------- tests/manual/trk/adapter.pro | 7 +- tests/manual/trk/launcher.cpp | 6 +- tests/manual/trk/launcher.h | 2 +- tests/manual/trk/run.pl | 10 + tests/manual/trk/trkdevice.cpp | 321 ++++++++++++++++++++----- tests/manual/trk/trkdevice.h | 72 +++++- tests/manual/trk/trkutils.cpp | 6 +- tests/manual/trk/trkutils.h | 2 +- 9 files changed, 431 insertions(+), 418 deletions(-) diff --git a/tests/manual/trk/adapter.cpp b/tests/manual/trk/adapter.cpp index 18d06b5bd13..0a4c4dc7f9e 100644 --- a/tests/manual/trk/adapter.cpp +++ b/tests/manual/trk/adapter.cpp @@ -28,6 +28,7 @@ **************************************************************************/ #include "trkutils.h" +#include "trkdevice.h" #include <QtCore/QPointer> #include <QtCore/QCoreApplication> @@ -40,50 +41,6 @@ #include <QtNetwork/QLocalServer> #include <QtNetwork/QLocalSocket> -#ifdef Q_OS_WIN -#include <windows.h> - -// 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) - return FALSE; - return ReadFile(hFile, - lpBuffer, - qMin(comStat.cbInQue, nNumberOfBytesToRead), - lpNumberOfBytesRead, - lpOverlapped); -} - -// Format windows error from GetLastError() value. -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; -} - -#endif - #ifdef Q_OS_UNIX #include <signal.h> @@ -97,9 +54,6 @@ void signalHandler(int) using namespace trk; -enum { TRK_SYNC = 0x7f }; - - enum { KnownRegisters = RegisterPSGdb + 1}; static const char *registerNames[KnownRegisters] = @@ -137,13 +91,13 @@ struct AdapterOptions { QString trkServer; }; -#define CB(s) &Adapter::s - class Adapter : public QObject { Q_OBJECT public: + typedef TrkFunctor1<const TrkResult &> Callback; + Adapter(); ~Adapter(); void setGdbServerName(const QString &name); @@ -154,38 +108,22 @@ public: void setUseSocket(bool s) { m_useSocket = s; } bool startServer(); +private slots: + void handleResult(const trk::TrkResult &data); + private: // // TRK // - Q_SLOT void readFromTrk(); - - typedef void (Adapter::*TrkCallBack)(const TrkResult &); - - struct TrkMessage - { - TrkMessage() : code(0), token(0), callBack(0), invokeOnFailure(0) {} - byte code; - byte token; - QByteArray data; - QVariant cookie; - TrkCallBack callBack; - bool invokeOnFailure; - }; bool openTrkPort(const QString &port, QString *errorMessage); // or server name for local server void sendTrkMessage(byte code, - TrkCallBack calBack = 0, + Callback callBack = Callback(), const QByteArray &data = QByteArray(), const QVariant &cookie = QVariant(), bool invokeOnFailure = false); - // adds message to 'send' queue - void queueTrkMessage(const TrkMessage &msg); - void tryTrkWrite(); - void tryTrkRead(); - // actually writes a message to the device - void trkWrite(const TrkMessage &msg); - // convienience messages + + // convenience messages void sendTrkInitialPing(); void sendTrkContinue(); void waitForTrkFinished(); @@ -194,10 +132,7 @@ private: // kill process and breakpoints void cleanUp(); - void timerEvent(QTimerEvent *ev); - byte nextTrkWriteToken(); - - void handleCpuType(const TrkResult &result); + void handleCpuType(const TrkResult &result); void handleCreateProcess(const TrkResult &result); void handleClearBreakpoint(const TrkResult &result); void handleSignalContinue(const TrkResult &result); @@ -215,26 +150,18 @@ private: void reportReadMemory(const TrkResult &result); void reportToGdb(const TrkResult &result); - void clearTrkBreakpoint(const Breakpoint &bp); - void handleResult(const TrkResult &data); + void clearTrkBreakpoint(const Breakpoint &bp); void readMemory(uint addr, uint len); void startInferiorIfNeeded(); void interruptInferior(); -#ifdef Q_OS_WIN - HANDLE m_winComDevice; -#endif - QLocalSocket *m_socketDevice; + QSharedPointer<TrkWriteQueueDevice> m_trkDevice; + QSharedPointer<QIODevice> m_socket; + QSharedPointer<TrkWriteQueueIODevice> m_socketDevice; QString m_trkServerName; QByteArray m_trkReadBuffer; - unsigned char m_trkWriteToken; - QQueue<TrkMessage> m_trkWriteQueue; - QHash<byte, TrkMessage> m_writtenTrkMessages; - QByteArray m_trkReadQueue; - bool m_trkWriteBusy; - QList<Breakpoint> m_breakpoints; // @@ -268,12 +195,6 @@ private: }; Adapter::Adapter() : -#ifdef Q_OS_WIN - m_winComDevice(NULL), -#endif - m_socketDevice(0), - m_trkWriteToken(0), - m_trkWriteBusy(false), m_gdbConnection(0), m_gdbServerPort(0), m_gdbAckMode(true), @@ -283,20 +204,14 @@ Adapter::Adapter() : m_serialFrame(true), m_startInferiorTriggered(false) { - startTimer(100); } Adapter::~Adapter() { // Trk -#ifdef Q_OS_WIN - if (m_winComDevice) - CloseHandle(m_winComDevice); -#endif - if (m_socketDevice) { - m_socketDevice->abort(); - delete m_socketDevice; - } + if (!m_socket.isNull()) + if (QLocalSocket *sock = qobject_cast<QLocalSocket *>(m_socket.data())) + sock->abort(); // Gdb m_gdbServer.close(); @@ -325,9 +240,9 @@ bool Adapter::startServer() sendTrkInitialPing(); sendTrkMessage(0x01); // Connect - sendTrkMessage(0x05, CB(handleSupportMask)); - sendTrkMessage(0x06, CB(handleCpuType)); - sendTrkMessage(0x04, CB(handleTrkVersions)); // Versions + sendTrkMessage(0x05, Callback(this, &Adapter::handleSupportMask)); + sendTrkMessage(0x06, Callback(this, &Adapter::handleCpuType)); + sendTrkMessage(0x04, Callback(this, &Adapter::handleTrkVersions)); // Versions //sendTrkMessage(0x09); // Unrecognized command //sendTrkMessage(0x4a, 0, // "10 " + formatString("C:\\data\\usingdlls.sisx")); // Open File @@ -491,7 +406,7 @@ void Adapter::sendGdbMessage(const QByteArray &msg, const QByteArray &logNote) void Adapter::sendGdbMessageAfterSync(const QByteArray &msg, const QByteArray &logNote) { QByteArray ba = msg + char(1) + logNote; - sendTrkMessage(TRK_SYNC, CB(reportToGdb), "", ba); // Answer gdb + sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, Callback(this, &Adapter::reportToGdb), "", ba); // Answer gdb } void Adapter::reportToGdb(const TrkResult &result) @@ -545,7 +460,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) appendInt(&ba, 0); // end address appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, 0, ba); + sendTrkMessage(0x18, Callback(), ba); // FIXME: should be triggered by real stop //sendGdbMessageAfterSync("S11", "target stopped"); } @@ -561,7 +476,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) QByteArray ba; appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, CB(handleSignalContinue), ba, signalNumber); // Continue + sendTrkMessage(0x18, Callback(this, &Adapter::handleSignalContinue), ba, signalNumber); // Continue } else if (response.startsWith("D")) { @@ -582,7 +497,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) appendShort(&ba, RegisterCount - 1); // last register appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x12, CB(handleAndReportReadRegisters), ba, QVariant(), true); + sendTrkMessage(0x12, Callback(this, &Adapter::handleAndReportReadRegisters), ba, QVariant(), true); } else if (response.startsWith("Hc")) { @@ -615,7 +530,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) QByteArray ba; appendByte(&ba, 0); // Sub-command: Delete Process appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, 0, ba, "Delete process"); // Delete Item + sendTrkMessage(0x41, Callback(), ba, "Delete process"); // Delete Item sendGdbMessageAfterSync("", "process killed"); } @@ -793,7 +708,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) appendInt(&ba, m_snapshot.registers[RegisterPC] + 4); // end address appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x19, 0, ba, "Step range"); + sendTrkMessage(0x19, Callback(), ba, "Step range"); // FIXME: should be triggered by "real" stop" //sendGdbMessageAfterSync("S05", "target halted"); } @@ -815,7 +730,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) QByteArray ba; appendByte(&ba, 0); // Sub-command: Delete Process appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, 0, ba, "Delete process"); // Delete Item + sendTrkMessage(0x41, Callback(), ba, "Delete process"); // Delete Item sendGdbMessageAfterSync("", "process killed"); } @@ -850,7 +765,7 @@ void Adapter::handleGdbResponse(const QByteArray &response) appendInt(&ba, m_session.pid); appendInt(&ba, 0xFFFFFFFF); - sendTrkMessage(0x1B, CB(handleAndReportSetBreakpoint), ba); + sendTrkMessage(0x1B, Callback(this, &Adapter::handleAndReportSetBreakpoint), ba); //m_session.toekn //---TRK------------------------------------------------------ @@ -864,95 +779,45 @@ void Adapter::handleGdbResponse(const QByteArray &response) } } -void Adapter::readFromTrk() -{ - //QByteArray ba = m_gdbConnection->readAll(); - //logMessage("Read from gdb: " + ba); -} - bool Adapter::openTrkPort(const QString &port, QString *errorMessage) { if (m_useSocket) { - m_socketDevice = new QLocalSocket(this); - m_socketDevice->connectToServer(port); - const bool rc = m_socketDevice->waitForConnected(); - if (!rc) - *errorMessage = "Unable to connect to TRK server " + m_trkServerName + ' ' + m_socketDevice->errorString(); - return rc; - } -#ifdef Q_OS_WIN - m_winComDevice = CreateFile(port.toStdWString().c_str(), - GENERIC_READ | GENERIC_WRITE, - 0, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - - if (INVALID_HANDLE_VALUE == m_winComDevice){ - *errorMessage = "Could not open device " + port + ' ' + winErrorMessage(GetLastError()); - return false; - } - return true; -#else - logMessage("Not implemented", true); - return false; -#endif - -#if 0 - m_socketDevice = new Win_QextSerialPort(port); - m_socketDevice->setBaudRate(BAUD115200); - m_socketDevice->setDataBits(DATA_8); - m_socketDevice->setParity(PAR_NONE); - //m_socketDevice->setStopBits(STO); - m_socketDevice->setFlowControl(FLOW_OFF); - m_socketDevice->setTimeout(0, 500); - - if (!m_socketDevice->open(QIODevice::ReadWrite)) { - QByteArray ba = m_socketDevice->errorString().toLatin1(); - logMessage("Could not open device " << ba); - return false; + QLocalSocket *socket = new QLocalSocket; + socket->connectToServer(port); + if (!socket->waitForConnected()) { + *errorMessage = "Unable to connect to TRK server " + m_trkServerName + ' ' + m_socket->errorString(); + delete socket; + return false; + } + m_socket = QSharedPointer<QIODevice>(socket); + m_socketDevice = QSharedPointer<TrkWriteQueueIODevice>(new TrkWriteQueueIODevice(m_socket)); + connect(m_socketDevice.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); + if (m_verbose > 1) + m_socketDevice->setVerbose(true); + return true; } - return true -#endif + m_trkDevice = QSharedPointer<TrkWriteQueueDevice>(new TrkWriteQueueDevice); + connect(m_trkDevice.data(), SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); + if (m_verbose > 1) + m_trkDevice->setVerbose(true); + return m_trkDevice->open(port, errorMessage); } -void Adapter::timerEvent(QTimerEvent *) -{ - //qDebug("."); - tryTrkWrite(); - tryTrkRead(); -} - -byte Adapter::nextTrkWriteToken() -{ - ++m_trkWriteToken; - if (m_trkWriteToken == 0) - ++m_trkWriteToken; - return m_trkWriteToken; -} - -void Adapter::sendTrkMessage(byte code, TrkCallBack callBack, +void Adapter::sendTrkMessage(byte code, Callback callBack, const QByteArray &data, const QVariant &cookie, bool invokeOnFailure) { - TrkMessage msg; - msg.code = code; - // Tokens must be strictly sequential - if (msg.code != TRK_SYNC) - msg.token = nextTrkWriteToken(); - msg.callBack = callBack; - msg.data = data; - msg.cookie = cookie; - msg.invokeOnFailure = invokeOnFailure; - queueTrkMessage(msg); + if (m_useSocket) + m_socketDevice->sendTrkMessage(code, callBack, data, cookie, invokeOnFailure); + else + m_trkDevice->sendTrkMessage(code, callBack, data, cookie, invokeOnFailure); } void Adapter::sendTrkInitialPing() { - TrkMessage msg; - msg.code = 0x00; // Ping - msg.token = 0; // reset sequence count - queueTrkMessage(msg); + if (m_useSocket) + m_socketDevice->sendTrkInitialPing(); + else + m_trkDevice->sendTrkInitialPing(); } void Adapter::sendTrkContinue() @@ -960,165 +825,39 @@ void Adapter::sendTrkContinue() QByteArray ba; appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, 0, ba, "CONTINUE"); + sendTrkMessage(0x18, Callback(), ba, "CONTINUE"); } void Adapter::waitForTrkFinished() { - TrkMessage msg; // initiate one last roundtrip to ensure all is flushed - msg.code = 0x00; // Ping - msg.token = nextTrkWriteToken(); - msg.callBack = CB(handleWaitForFinished); - queueTrkMessage(msg); + sendTrkMessage(0x0, Callback(this, &Adapter::handleWaitForFinished)); } void Adapter::sendTrkAck(byte token) { logMessage(QString("SENDING ACKNOWLEDGEMENT FOR TOKEN %1").arg(int(token))); - TrkMessage msg; - msg.code = 0x80; - msg.token = token; - msg.data.append('\0'); - // The acknowledgement must not be queued! - //queueMessage(msg); - trkWrite(msg); - // 01 90 00 07 7e 80 01 00 7d 5e 7e -} - -void Adapter::queueTrkMessage(const TrkMessage &msg) -{ - m_trkWriteQueue.append(msg); + if (m_useSocket) + m_socketDevice->sendTrkAck(token); + else + m_trkDevice->sendTrkAck(token); } -void Adapter::tryTrkWrite() +void Adapter::handleResult(const TrkResult &result) { - if (m_trkWriteBusy) + if (result.isDebugOutput) { + logMessage(QLatin1String("APPLICATION OUTPUT: ") + QString::fromAscii(result.data)); return; - if (m_trkWriteQueue.isEmpty()) - return; - - TrkMessage msg = m_trkWriteQueue.dequeue(); - if (msg.code == TRK_SYNC) { - logMessage(QString::fromLatin1("TRK SYNC [token=%1]").arg(msg.token)); - TrkResult result; - result.code = msg.code; - result.token = msg.token; - result.data = msg.data; - result.cookie = msg.cookie; - TrkCallBack cb = msg.callBack; - if (cb) - (this->*cb)(result); - } else { - trkWrite(msg); } -} - -void Adapter::trkWrite(const TrkMessage &msg) -{ - QByteArray ba = frameMessage(msg.code, msg.token, msg.data, m_serialFrame); - - m_writtenTrkMessages.insert(msg.token, msg); - m_trkWriteBusy = true; - - if (m_verbose > 1) { - const QString logMsg = QString::fromLatin1("WRITE: 0x%1 [token=%2]: %3").arg(msg.code, 0, 16).arg(msg.token).arg(stringFromArray(ba)); - logMessage(logMsg); - } - - if (m_useSocket) { - if (!m_socketDevice->write(ba)) - logMessage("WRITE ERROR: " + m_socketDevice->errorString()); - m_socketDevice->flush(); - } else { -#ifdef Q_OS_WIN - DWORD charsWritten; - if (!WriteFile(m_winComDevice, ba.data(), ba.size(), &charsWritten, NULL)) - logMessage("WRITE ERROR: " + winErrorMessage(GetLastError())); - FlushFileBuffers(m_winComDevice); -#endif - } -} - -void Adapter::tryTrkRead() -{ - //logMessage("TRY READ: " << m_socketDevice->bytesAvailable() - // << stringFromArray(m_trkReadQueue); - if (m_useSocket) { - if (m_socketDevice->bytesAvailable() == 0 && m_trkReadQueue.isEmpty()) - return; - - QByteArray res = m_socketDevice->readAll(); - m_trkReadQueue.append(res); - } else { -#ifdef Q_OS_WIN - const DWORD BUFFERSIZE = 1024; - char buffer[BUFFERSIZE]; - DWORD charsRead; - DWORD totalCharsRead = 0; - while (TryReadFile(m_winComDevice, buffer, BUFFERSIZE, &charsRead, NULL)) { - m_trkReadQueue.append(buffer, charsRead); - totalCharsRead += charsRead; - if (isValidTrkResult(m_trkReadQueue, m_serialFrame)) - break; - } - if (!totalCharsRead) - return; -#endif // USE_NATIVE - } - - if (m_trkReadQueue.size() < 9) { - logMessage("ERROR READBUFFER INVALID (1): " - + stringFromArray(m_trkReadQueue)); - m_trkReadQueue.clear(); - return; - } - - TrkResult r; - while (extractResult(&m_trkReadQueue, m_serialFrame, &r)) - handleResult(r); - - m_trkWriteBusy = false; -} - - -void Adapter::handleResult(const TrkResult &result) -{ QByteArray prefix = "READ BUF: "; QByteArray str = result.toString().toUtf8(); switch (result.code) { - case 0x80: { // ACK - //logMessage(prefix + "ACK: " + str); - if (const int ec = result.errorCode()) - logMessage(QString::fromLatin1("READ BUF ACK/ERR %1 for token=%2").arg(ec).arg(result.token), true); - if (!m_writtenTrkMessages.contains(result.token)) { - logMessage("NO ENTRY FOUND!"); - } - TrkMessage msg = m_writtenTrkMessages.take(result.token); - TrkResult result1 = result; - result1.cookie = msg.cookie; - TrkCallBack cb = msg.callBack; - if (cb) { - (this->*cb)(result1); - } else { - QString msg = result.cookie.toString(); - if (!msg.isEmpty()) - logMessage("HANDLE: " + msg + stringFromArray(result.data)); - } - break; - } + case 0x80: // ACK + break; case 0xff: { // NAK. This mostly means transmission error, not command failed. - const TrkMessage writtenMsg = m_writtenTrkMessages.take(result.token); QString logMsg; - QTextStream(&logMsg) << prefix << "NAK: for 0x" << QString::number(int(writtenMsg.code), 16) - << " token=" << result.token << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str; + QTextStream(&logMsg) << prefix << "NAK: for token=" << result.token << " ERROR: " << errorMessage(result.data.at(0)) << ' ' << str; logMessage(logMsg, true); - // Invoke failure if desired - if (writtenMsg.callBack && writtenMsg.invokeOnFailure) { - TrkResult result1 = result; - result1.cookie = writtenMsg.cookie; - (this->*writtenMsg.callBack)(result1); - } break; } case 0x90: { // Notified Stopped @@ -1258,10 +997,10 @@ void Adapter::handleCreateProcess(const TrkResult &result) // Command: 0x42 Read Info // [42 0C 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F // 72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00] - sendTrkMessage(0x42, CB(handleReadInfo), + sendTrkMessage(0x42, Callback(this, &Adapter::handleReadInfo), "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " "72 70 68 69 63 44 4C 4C 32 2E 64 6C 6C 00"); - //sendTrkMessage(0x42, CB(handleReadInfo), + //sendTrkMessage(0x42, Callback(this, &Adapter::handleReadInfo), // "00 01 00 00 00 00"); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge @@ -1273,7 +1012,7 @@ void Adapter::handleCreateProcess(const TrkResult &result) // Command: 0x42 Read Info // [42 0D 00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F // 72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00] - sendTrkMessage(0x42, CB(handleReadInfo), + sendTrkMessage(0x42, Callback(this, &Adapter::handleReadInfo), "00 06 00 00 00 00 00 14 50 6F 6C 79 6D 6F " "72 70 68 69 63 44 4C 4C 31 2E 64 6C 6C 00"); //---TRK------------------------------------------------------ @@ -1282,7 +1021,7 @@ void Adapter::handleCreateProcess(const TrkResult &result) // [80 0D 20] #endif - //sendTrkMessage(0x18, CB(handleStop), + //sendTrkMessage(0x18, Callback(this, &Adapter::handleStop), // "01 " + formatInt(m_session.pid) + formatInt(m_session.tid)); //---IDE------------------------------------------------------ @@ -1293,8 +1032,8 @@ void Adapter::handleCreateProcess(const TrkResult &result) QByteArray ba; appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); - sendTrkMessage(0x18, CB(handleContinue), ba); - //sendTrkMessage(0x18, CB(handleContinue), + sendTrkMessage(0x18, Callback(this, &Adapter::handleContinue), ba); + //sendTrkMessage(0x18, Callback(this, &Adapter::handleContinue), // formatInt(m_session.pid) + "ff ff ff ff"); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge @@ -1423,7 +1162,7 @@ void Adapter::clearTrkBreakpoint(const Breakpoint &bp) appendByte(&ba, 0x00); appendShort(&ba, bp.number); appendInt(&ba, m_session.codeseg + bp.offset); - sendTrkMessage(0x1C, CB(handleClearBreakpoint), ba); + sendTrkMessage(0x1C, Callback(this, &Adapter::handleClearBreakpoint), ba); } void Adapter::handleClearBreakpoint(const TrkResult &result) @@ -1497,7 +1236,7 @@ void Adapter::cleanUp() appendByte(&ba, 0x00); appendByte(&ba, 0x00); appendInt(&ba, m_session.pid); - sendTrkMessage(0x41, 0, ba, "Delete process"); + sendTrkMessage(0x41, Callback(), ba, "Delete process"); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge @@ -1507,7 +1246,7 @@ void Adapter::cleanUp() foreach (const Breakpoint &bp, m_breakpoints) clearTrkBreakpoint(bp); - sendTrkMessage(0x02, CB(handleDisconnect)); + sendTrkMessage(0x02, Callback(this, &Adapter::handleDisconnect)); m_startInferiorTriggered = false; //---IDE------------------------------------------------------ // Command: 0x1C Clear Break @@ -1538,7 +1277,7 @@ void Adapter::cleanUp() //---IDE------------------------------------------------------ // Command: 0x02 Disconnect // [02 27] -// sendTrkMessage(0x02, CB(handleDisconnect)); +// sendTrkMessage(0x02, Callback(this, &Adapter::handleDisconnect)); //---TRK------------------------------------------------------ // Command: 0x80 Acknowledge // Error: 0x00 @@ -1565,11 +1304,11 @@ void Adapter::readMemory(uint addr, uint len) appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); // Read Memory - sendTrkMessage(0x10, CB(handleReadMemory), ba, QVariant(blockaddr), true); + sendTrkMessage(0x10, Callback(this, &Adapter::handleReadMemory), ba, QVariant(blockaddr), true); } } qulonglong cookie = (qulonglong(addr) << 32) + len; - sendTrkMessage(TRK_SYNC, CB(reportReadMemory), QByteArray(), cookie); + sendTrkMessage(TRK_WRITE_QUEUE_NOOP_CODE, Callback(this, &Adapter::reportReadMemory), QByteArray(), cookie); } void Adapter::startInferiorIfNeeded() @@ -1589,7 +1328,7 @@ void Adapter::startInferiorIfNeeded() QByteArray file("C:\\sys\\bin\\filebrowseapp.exe"); appendString(&ba, file, TargetByteOrder); - sendTrkMessage(0x40, CB(handleCreateProcess), ba); // Create Item + sendTrkMessage(0x40, Callback(this, &Adapter::handleCreateProcess), ba); // Create Item } void Adapter::interruptInferior() @@ -1599,7 +1338,7 @@ void Adapter::interruptInferior() appendByte(&ba, 1); appendInt(&ba, m_session.pid); appendInt(&ba, m_session.tid); // threadID: 4 bytes Variable number of bytes. - sendTrkMessage(0x1A, 0, ba, "Interrupting..."); + sendTrkMessage(0x1A, Callback(), ba, "Interrupting..."); } static bool readAdapterArgs(const QStringList &args, AdapterOptions *o) diff --git a/tests/manual/trk/adapter.pro b/tests/manual/trk/adapter.pro index 48ebd9bec67..22f4aa3cddb 100644 --- a/tests/manual/trk/adapter.pro +++ b/tests/manual/trk/adapter.pro @@ -4,8 +4,11 @@ TEMPLATE = app QT = core network win32:CONFIG+=console -HEADERS += trkutils.h +HEADERS += trkutils.h \ +trkfunctor.h \ +trkdevice.h \ SOURCES += \ adapter.cpp \ - trkutils.cpp + trkutils.cpp \ + trkdevice.cpp diff --git a/tests/manual/trk/launcher.cpp b/tests/manual/trk/launcher.cpp index a3d3d06e035..474b965a236 100644 --- a/tests/manual/trk/launcher.cpp +++ b/tests/manual/trk/launcher.cpp @@ -67,7 +67,7 @@ LauncherPrivate::LauncherPrivate() : Launcher::Launcher() : d(new LauncherPrivate) { - connect(&d->m_device, SIGNAL(messageReceived(TrkResult)), this, SLOT(handleResult(TrkResult))); + connect(&d->m_device, SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(handleResult(trk::TrkResult))); } Launcher::~Launcher() @@ -147,7 +147,7 @@ void Launcher::installAndRun() void Launcher::logMessage(const QString &msg) { if (d->m_verbose) - qDebug() << "ADAPTER: " << qPrintable(msg); + qDebug() << "LAUNCHER: " << qPrintable(msg); } void Launcher::waitForTrkFinished(const TrkResult &result) @@ -239,7 +239,7 @@ void Launcher::handleResult(const TrkResult &result) case TrkNotifyDeleted: { // NotifyDeleted 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(); + const QString name = len ? QString::fromAscii(result.data.mid(12, len)) : QString(); logMessage(QString::fromLatin1("%1 %2 UNLOAD: %3"). arg(QString::fromAscii(prefix)).arg(itemType ? QLatin1String("LIB") : QLatin1String("PROCESS")). arg(name)); diff --git a/tests/manual/trk/launcher.h b/tests/manual/trk/launcher.h index c2527d57d5c..cb9881b5511 100644 --- a/tests/manual/trk/launcher.h +++ b/tests/manual/trk/launcher.h @@ -67,7 +67,7 @@ public slots: void terminate(); private slots: - void handleResult(const TrkResult &data); + void handleResult(const trk::TrkResult &data); private: void tryTrkRead(); diff --git a/tests/manual/trk/run.pl b/tests/manual/trk/run.pl index 2644c304970..9f4e31097c6 100755 --- a/tests/manual/trk/run.pl +++ b/tests/manual/trk/run.pl @@ -21,10 +21,15 @@ Usage: run.pl -av -aq -tv -tq -l [COM] Options: -av Adapter verbose -aq Adapter quiet + -af Adapter turn off serial frame -tv TrkServer verbose -tq TrkServer quiet trkserver simulator will be run unless COM is specified + +Bluetooth: + rfcomm listen /dev/rfcomm0 1 \$PWD/run.pl -av -af {} + EOF # ------- Parse arguments @@ -36,11 +41,16 @@ for (my $i = 0; $i < $argCount; $i++) { push(@ADAPTER_OPTIONS, '-v'); } elsif ($a eq '-aq') { push(@ADAPTER_OPTIONS, '-q'); + } elsif ($a eq '-af') { + push(@ADAPTER_OPTIONS, '-f'); } elsif ($a eq '-tv') { push(@TRKSERVEROPTIONS, '-v'); } elsif ($a eq '-tq') { push(@TRKSERVEROPTIONS, '-q'); } elsif ($a eq '-h') { + print $usage; + exit(0); + } else { print $usage; exit(1); } diff --git a/tests/manual/trk/trkdevice.cpp b/tests/manual/trk/trkdevice.cpp index 13608cb2da8..6746e5b1f64 100644 --- a/tests/manual/trk/trkdevice.cpp +++ b/tests/manual/trk/trkdevice.cpp @@ -35,6 +35,7 @@ #include <QtCore/QQueue> #include <QtCore/QHash> #include <QtCore/QMap> +#include <QtCore/QSharedPointer> #ifdef Q_OS_WIN # include <windows.h> @@ -312,10 +313,13 @@ void TrkDevice::tryTrkRead() } #endif // Q_OS_WIN TrkResult r; - while (extractResult(&d->trkReadBuffer, d->serialFrame, &r)) { + QByteArray rawData; + while (extractResult(&d->trkReadBuffer, d->serialFrame, &r, &rawData)) { if (d->verbose) qDebug() << "Read TrkResult " << r.data.toHex(); emit messageReceived(r); + if (!rawData.isEmpty()) + emit rawDataReceived(rawData); } } @@ -359,28 +363,149 @@ TrkMessage::TrkMessage(unsigned char c, } // ------- TrkWriteQueueDevice +typedef QSharedPointer<TrkMessage> SharedPointerTrkMessage; -struct TrkWriteQueueDevicePrivate { - typedef QMap<unsigned char, TrkMessage> TokenMessageMap; - TrkWriteQueueDevicePrivate(); +/* Mixin class that manages a write queue of Trk messages. */ + +class TrkWriteQueue { +public: + typedef TrkWriteQueueDevice::Callback Callback; + + TrkWriteQueue(); + + // Enqueue messages. + void queueTrkMessage(unsigned char code, Callback callback, + const QByteArray &data, const QVariant &cookie, + bool invokeOnNAK); + void queueTrkInitialPing(); + + // Call this from the device read notification with the results. + void slotHandleResult(const TrkResult &result); + + // This can be called periodically in a timer to retrieve + // the pending messages to be sent. + bool pendingMessage(SharedPointerTrkMessage *message = 0); + // Notify the queue about the success of the write operation + // after taking the pendingMessage off. + void notifyWriteResult(bool ok); + + // Factory function for ack message + static SharedPointerTrkMessage trkAck(unsigned char token); + +private: + typedef QMap<unsigned char, SharedPointerTrkMessage> TokenMessageMap; + + unsigned char nextTrkWriteToken(); unsigned char trkWriteToken; - QQueue<TrkMessage> trkWriteQueue; + QQueue<SharedPointerTrkMessage> trkWriteQueue; TokenMessageMap writtenTrkMessages; bool trkWriteBusy; }; -TrkWriteQueueDevicePrivate::TrkWriteQueueDevicePrivate() : +TrkWriteQueue::TrkWriteQueue() : trkWriteToken(0), trkWriteBusy(false) { } +unsigned char TrkWriteQueue::nextTrkWriteToken() +{ + ++trkWriteToken; + if (trkWriteToken == 0) + ++trkWriteToken; + return trkWriteToken; +} + +void TrkWriteQueue::queueTrkMessage(unsigned char code, Callback callback, + const QByteArray &data, const QVariant &cookie, + bool invokeOnNAK) +{ + const unsigned char token = code == TRK_WRITE_QUEUE_NOOP_CODE ? + (unsigned char)(0) : nextTrkWriteToken(); + SharedPointerTrkMessage msg(new TrkMessage(code, token, callback)); + msg->data = data; + msg->cookie = cookie; + msg->invokeOnNAK = invokeOnNAK; + trkWriteQueue.append(msg); +} + +bool TrkWriteQueue::pendingMessage(SharedPointerTrkMessage *message) +{ + // Invoked from timer, try to flush out message queue + if (trkWriteBusy || trkWriteQueue.isEmpty()) + return false; + // Handle the noop message, just invoke CB + if (trkWriteQueue.front()->code == TRK_WRITE_QUEUE_NOOP_CODE) { + const SharedPointerTrkMessage noopMessage = trkWriteQueue.dequeue(); + if (noopMessage->callback) { + TrkResult result; + result.code = noopMessage->code; + result.token = noopMessage->token; + result.data = noopMessage->data; + result.cookie = noopMessage->cookie; + noopMessage->callback(result); + } + } + // Check again for real messages + if (trkWriteQueue.isEmpty()) + return false; + if (message) + *message = trkWriteQueue.front(); + return true; +} + +void TrkWriteQueue::notifyWriteResult(bool ok) +{ + // On success, dequeue message and await result + if (ok) { + const SharedPointerTrkMessage firstMsg = trkWriteQueue.dequeue(); + writtenTrkMessages.insert(firstMsg->token, firstMsg); + trkWriteBusy = true; + } +} + +void TrkWriteQueue::slotHandleResult(const TrkResult &result) +{ + trkWriteBusy = false; + if (result.code != TrkNotifyAck && result.code != TrkNotifyNak) + return; + // Find which request the message belongs to and invoke callback + // if ACK or on NAK if desired. + const TokenMessageMap::iterator it = writtenTrkMessages.find(result.token); + if (it == writtenTrkMessages.end()) + return; + const bool invokeCB = it.value()->callback + && (result.code == TrkNotifyAck || it.value()->invokeOnNAK); + + if (invokeCB) { + TrkResult result1 = result; + result1.cookie = it.value()->cookie; + it.value()->callback(result1); + } + writtenTrkMessages.erase(it); +} + +SharedPointerTrkMessage TrkWriteQueue::trkAck(unsigned char token) +{ + SharedPointerTrkMessage msg(new TrkMessage(0x80, token)); + msg->token = token; + msg->data.append('\0'); + return msg; +} + +void TrkWriteQueue::queueTrkInitialPing() +{ + const SharedPointerTrkMessage msg(new TrkMessage(0, 0)); // Ping, reset sequence count + trkWriteQueue.append(msg); +} + +// ----------------------- TrkWriteQueueDevice::TrkWriteQueueDevice(QObject *parent) : TrkDevice(parent), - qd(new TrkWriteQueueDevicePrivate) + qd(new TrkWriteQueue) { - connect(this, SIGNAL(messageReceived(TrkResult)), this, SLOT(slotHandleResult(TrkResult))); + connect(this, SIGNAL(messageReceived(trk::TrkResult)), this, SLOT(slotHandleResult(trk::TrkResult))); } TrkWriteQueueDevice::~TrkWriteQueueDevice() @@ -388,56 +513,34 @@ TrkWriteQueueDevice::~TrkWriteQueueDevice() delete qd; } -unsigned char TrkWriteQueueDevice::nextTrkWriteToken() -{ - ++qd->trkWriteToken; - if (qd->trkWriteToken == 0) - ++qd->trkWriteToken; - return qd->trkWriteToken; -} - void TrkWriteQueueDevice::sendTrkMessage(unsigned char code, Callback callback, const QByteArray &data, const QVariant &cookie, bool invokeOnNAK) { - TrkMessage msg(code, nextTrkWriteToken(), callback); - msg.data = data; - msg.cookie = cookie; - msg.invokeOnNAK = invokeOnNAK; - queueTrkMessage(msg); + qd->queueTrkMessage(code, callback, data, cookie, invokeOnNAK); } void TrkWriteQueueDevice::sendTrkInitialPing() { - const TrkMessage msg(0, 0); // Ping, reset sequence count - queueTrkMessage(msg); + qd->queueTrkInitialPing(); } bool TrkWriteQueueDevice::sendTrkAck(unsigned char token) { - TrkMessage msg(0x80, token); - msg.token = token; - msg.data.append('\0'); // The acknowledgement must not be queued! - return trkWriteRawMessage(msg); + const SharedPointerTrkMessage ack = TrkWriteQueue::trkAck(token); + return trkWriteRawMessage(*ack); // 01 90 00 07 7e 80 01 00 7d 5e 7e } -void TrkWriteQueueDevice::queueTrkMessage(const TrkMessage &msg) -{ - qd->trkWriteQueue.append(msg); -} - void TrkWriteQueueDevice::tryTrkWrite() { - // Invoked from timer, try to flush out message queue - if (qd->trkWriteBusy) + if (!qd->pendingMessage()) return; - if (qd->trkWriteQueue.isEmpty()) - return; - - const TrkMessage msg = qd->trkWriteQueue.dequeue(); - trkWrite(msg); + SharedPointerTrkMessage message; + qd->pendingMessage(&message); + const bool success = trkWriteRawMessage(*message); + qd->notifyWriteResult(success); } bool TrkWriteQueueDevice::trkWriteRawMessage(const TrkMessage &msg) @@ -452,13 +555,6 @@ bool TrkWriteQueueDevice::trkWriteRawMessage(const TrkMessage &msg) return rc; } -bool TrkWriteQueueDevice::trkWrite(const TrkMessage &msg) -{ - qd->writtenTrkMessages.insert(msg.token, msg); - qd->trkWriteBusy = true; - return trkWriteRawMessage(msg); -} - void TrkWriteQueueDevice::timerEvent(QTimerEvent *ev) { tryTrkWrite(); @@ -467,23 +563,128 @@ void TrkWriteQueueDevice::timerEvent(QTimerEvent *ev) void TrkWriteQueueDevice::slotHandleResult(const TrkResult &result) { - qd->trkWriteBusy = false; - if (result.code != TrkNotifyAck && result.code != TrkNotifyNak) - return; - // Find which request the message belongs to and invoke callback - // if ACK or on NAK if desired. - const TrkWriteQueueDevicePrivate::TokenMessageMap::iterator it = qd->writtenTrkMessages.find(result.token); - if (it == qd->writtenTrkMessages.end()) + qd->slotHandleResult(result); +} + +// ----------- TrkWriteQueueDevice + +struct TrkWriteQueueIODevicePrivate { + TrkWriteQueueIODevicePrivate(const QSharedPointer<QIODevice> &d); + + const QSharedPointer<QIODevice> device; + TrkWriteQueue queue; + QByteArray readBuffer; + bool serialFrame; + bool verbose; +}; + +TrkWriteQueueIODevicePrivate::TrkWriteQueueIODevicePrivate(const QSharedPointer<QIODevice> &d) : + device(d), + serialFrame(true), + verbose(false) +{ +} + +TrkWriteQueueIODevice::TrkWriteQueueIODevice(const QSharedPointer<QIODevice> &device, + QObject *parent) : + QObject(parent), + d(new TrkWriteQueueIODevicePrivate(device)) +{ + startTimer(TimerInterval); +} + +TrkWriteQueueIODevice::~TrkWriteQueueIODevice() +{ + delete d; +} + +bool TrkWriteQueueIODevice::serialFrame() const +{ + return d->serialFrame; +} + +void TrkWriteQueueIODevice::setSerialFrame(bool f) +{ + d->serialFrame = f; +} + +bool TrkWriteQueueIODevice::verbose() const +{ + return d->verbose; +} + +void TrkWriteQueueIODevice::setVerbose(bool b) +{ + d->verbose = b; +} + +void TrkWriteQueueIODevice::sendTrkMessage(unsigned char code, Callback callback, + const QByteArray &data, const QVariant &cookie, + bool invokeOnNAK) +{ + d->queue.queueTrkMessage(code, callback, data, cookie, invokeOnNAK); +} + +void TrkWriteQueueIODevice::sendTrkInitialPing() +{ + d->queue.queueTrkInitialPing(); +} + +bool TrkWriteQueueIODevice::sendTrkAck(unsigned char token) +{ + // The acknowledgement must not be queued! + const SharedPointerTrkMessage ack = TrkWriteQueue::trkAck(token); + return trkWriteRawMessage(*ack); + // 01 90 00 07 7e 80 01 00 7d 5e 7e +} + + +void TrkWriteQueueIODevice::timerEvent(QTimerEvent *) +{ + tryTrkWrite(); + tryTrkRead(); +} + +void TrkWriteQueueIODevice::tryTrkWrite() +{ + if (!d->queue.pendingMessage()) return; - const bool invokeCB = it.value().callback - && (result.code == TrkNotifyAck || it.value().invokeOnNAK); + SharedPointerTrkMessage message; + d->queue.pendingMessage(&message); + const bool success = trkWriteRawMessage(*message); + d->queue.notifyWriteResult(success); +} - if (invokeCB) { - TrkResult result1 = result; - result1.cookie = it.value().cookie; - it.value().callback(result1); +bool TrkWriteQueueIODevice::trkWriteRawMessage(const TrkMessage &msg) +{ + const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, serialFrame()); + if (verbose()) + qDebug() << ("WRITE: " + stringFromArray(ba)); + const bool ok = d->device->write(ba) != -1; + if (!ok) { + const QString msg = QString::fromLatin1("Unable to write %1 bytes: %2:").arg(ba.size()).arg(d->device->errorString()); + qWarning("%s\n", qPrintable(msg)); + } + return ok; +} + +void TrkWriteQueueIODevice::tryTrkRead() +{ + const quint64 bytesAvailable = d->device->bytesAvailable(); + if (!bytesAvailable) + return; + const QByteArray newData = d->device->read(bytesAvailable); + if (d->verbose) + qDebug() << "READ " << newData.toHex(); + d->readBuffer.append(newData); + TrkResult r; + QByteArray rawData; + while (extractResult(&(d->readBuffer), d->serialFrame, &r, &rawData)) { + d->queue.slotHandleResult(r); + emit messageReceived(r); + if (!rawData.isEmpty()) + emit rawDataReceived(rawData); } - qd->writtenTrkMessages.erase(it); } } // namespace tr diff --git a/tests/manual/trk/trkdevice.h b/tests/manual/trk/trkdevice.h index 53047bfb899..61b382ad576 100644 --- a/tests/manual/trk/trkdevice.h +++ b/tests/manual/trk/trkdevice.h @@ -35,13 +35,19 @@ #include <QtCore/QObject> #include <QtCore/QVariant> #include <QtCore/QByteArray> +#include <QtCore/QSharedPointer> + +QT_BEGIN_NAMESPACE +class QIODevice; +QT_END_NAMESPACE namespace trk { struct TrkResult; struct TrkMessage; struct TrkDevicePrivate; -struct TrkWriteQueueDevicePrivate; +class TrkWriteQueue; +struct TrkWriteQueueIODevicePrivate; /* TrkDevice: Implements a Windows COM or Linux device for * Trk communications. Provides synchronous write and asynchronous @@ -74,7 +80,9 @@ public: bool write(const QByteArray &data, QString *errorMessage); signals: - void messageReceived(const TrkResult&); + void messageReceived(const trk::TrkResult&); + // Emitted with the contents of messages enclosed in 07e, not for log output + void rawDataReceived(const QByteArray &data); void error(const QString &s); protected: @@ -89,7 +97,12 @@ private: /* TrkWriteQueueDevice: Extends TrkDevice by write message queue allowing * for queueing messages with a notification callback. If the message receives - * an ACK, the callback is invoked. */ + * an ACK, the callback is invoked. + * The special message TRK_WRITE_QUEUE_NOOP_CODE code can be used for synchronisation. + * The respective message will not be sent, the callback is just invoked. */ + +enum { TRK_WRITE_QUEUE_NOOP_CODE = 0x7f }; + class TrkWriteQueueDevice : public TrkDevice { Q_OBJECT @@ -115,21 +128,64 @@ public: bool sendTrkAck(unsigned char token); private slots: - void slotHandleResult(const TrkResult &); + void slotHandleResult(const trk::TrkResult &); protected: virtual void timerEvent(QTimerEvent *ev); private: - unsigned char nextTrkWriteToken(); - void queueTrkMessage(const TrkMessage &msg); void tryTrkWrite(); bool trkWriteRawMessage(const TrkMessage &msg); - bool trkWrite(const TrkMessage &msg); - TrkWriteQueueDevicePrivate *qd; + TrkWriteQueue *qd; }; +/* A Trk queueing device wrapping around a QIODevice (otherwise + * mimicking TrkWriteQueueDevice). + * Can be used to forward Trk over a network or to simulate things. */ + +class TrkWriteQueueIODevice : public QObject +{ + Q_OBJECT + Q_DISABLE_COPY(TrkWriteQueueIODevice) + Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame) + Q_PROPERTY(bool verbose READ verbose WRITE setVerbose) +public: + typedef TrkFunctor1<const TrkResult &> Callback; + + explicit TrkWriteQueueIODevice(const QSharedPointer<QIODevice> &device, + QObject *parent = 0); + virtual ~TrkWriteQueueIODevice(); + + bool serialFrame() const; + void setSerialFrame(bool f); + + bool verbose() const; + void setVerbose(bool b); + + void sendTrkMessage(unsigned char code, + Callback callback = Callback(), + const QByteArray &data = QByteArray(), + const QVariant &cookie = QVariant(), + bool invokeOnNAK = false); + void sendTrkInitialPing(); + bool sendTrkAck(unsigned char token); + +signals: + void messageReceived(const trk::TrkResult&); + // Emitted with the contents of messages enclosed in 07e, not for log output + void rawDataReceived(const QByteArray &data); + +protected: + virtual void timerEvent(QTimerEvent *ev); + +private: + void tryTrkRead(); + void tryTrkWrite(); + bool trkWriteRawMessage(const TrkMessage &msg); + + TrkWriteQueueIODevicePrivate *d; +}; } // namespace trk diff --git a/tests/manual/trk/trkutils.cpp b/tests/manual/trk/trkutils.cpp index 8b5622ed9fa..81925c07d67 100644 --- a/tests/manual/trk/trkutils.cpp +++ b/tests/manual/trk/trkutils.cpp @@ -122,9 +122,11 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame) return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size(); } -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result) +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result, QByteArray *rawData) { result->clear(); + if(rawData) + rawData->clear(); const ushort len = isValidTrkResult(*buffer, serialFrame); if (!len) return false; @@ -140,6 +142,8 @@ bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *result) // FIXME: what happens if the length contains 0xfe? // Assume for now that it passes unencoded! const QByteArray data = decode7d(buffer->mid(delimiterPos + 1, len - 2)); + if(rawData) + *rawData = data; *buffer->remove(0, delimiterPos + len); byte sum = 0; diff --git a/tests/manual/trk/trkutils.h b/tests/manual/trk/trkutils.h index 77e469b8068..e54efc6f6e9 100644 --- a/tests/manual/trk/trkutils.h +++ b/tests/manual/trk/trkutils.h @@ -188,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); -bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r); +bool extractResult(QByteArray *buffer, bool serialFrame, TrkResult *r, QByteArray *rawData = 0); QByteArray errorMessage(byte code); QByteArray hexNumber(uint n, int digits = 0); uint swapEndian(uint in); -- GitLab