forked from qt-creator/qt-creator
Trk: Add device class.
This commit is contained in:
@@ -1059,7 +1059,7 @@ void Adapter::tryTrkRead()
|
|||||||
while (TryReadFile(m_winComDevice, buffer, BUFFERSIZE, &charsRead, NULL)) {
|
while (TryReadFile(m_winComDevice, buffer, BUFFERSIZE, &charsRead, NULL)) {
|
||||||
m_trkReadQueue.append(buffer, charsRead);
|
m_trkReadQueue.append(buffer, charsRead);
|
||||||
totalCharsRead += charsRead;
|
totalCharsRead += charsRead;
|
||||||
if (isValidTrkResult(m_trkReadQueue))
|
if (isValidTrkResult(m_trkReadQueue, m_serialFrame))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if (!totalCharsRead)
|
if (!totalCharsRead)
|
||||||
@@ -1074,8 +1074,9 @@ void Adapter::tryTrkRead()
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
while (!m_trkReadQueue.isEmpty())
|
TrkResult r;
|
||||||
handleResult(extractResult(&m_trkReadQueue, m_serialFrame));
|
while (extractResult(&m_trkReadQueue, m_serialFrame, &r))
|
||||||
|
handleResult(r);
|
||||||
|
|
||||||
m_trkWriteBusy = false;
|
m_trkWriteBusy = false;
|
||||||
}
|
}
|
||||||
|
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "launcher.h"
|
#include "launcher.h"
|
||||||
#include "trkutils.h"
|
#include "trkutils.h"
|
||||||
|
#include "trkdevice.h"
|
||||||
|
|
||||||
#include <QtCore/QTimer>
|
#include <QtCore/QTimer>
|
||||||
#include <QtCore/QDateTime>
|
#include <QtCore/QDateTime>
|
||||||
@@ -37,60 +38,6 @@
|
|||||||
#include <QtCore/QQueue>
|
#include <QtCore/QQueue>
|
||||||
#include <QtCore/QFile>
|
#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 {
|
namespace trk {
|
||||||
|
|
||||||
struct TrkMessage {
|
struct TrkMessage {
|
||||||
@@ -104,12 +51,7 @@ struct TrkMessage {
|
|||||||
|
|
||||||
struct LauncherPrivate {
|
struct LauncherPrivate {
|
||||||
LauncherPrivate();
|
LauncherPrivate();
|
||||||
#ifdef Q_OS_WIN
|
TrkDevice m_device;
|
||||||
HANDLE m_hdevice;
|
|
||||||
#else
|
|
||||||
QFile m_file;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
QString m_trkServerName;
|
QString m_trkServerName;
|
||||||
QByteArray m_trkReadBuffer;
|
QByteArray m_trkReadBuffer;
|
||||||
|
|
||||||
@@ -128,18 +70,13 @@ struct LauncherPrivate {
|
|||||||
QString m_copySrcFileName;
|
QString m_copySrcFileName;
|
||||||
QString m_copyDstFileName;
|
QString m_copyDstFileName;
|
||||||
QString m_installFileName;
|
QString m_installFileName;
|
||||||
bool m_serialFrame;
|
|
||||||
int m_verbose;
|
int m_verbose;
|
||||||
};
|
};
|
||||||
|
|
||||||
LauncherPrivate::LauncherPrivate() :
|
LauncherPrivate::LauncherPrivate() :
|
||||||
#ifdef Q_OS_WIN
|
|
||||||
m_hdevice(0),
|
|
||||||
#endif
|
|
||||||
m_trkWriteToken(0),
|
m_trkWriteToken(0),
|
||||||
m_trkWriteBusy(false),
|
m_trkWriteBusy(false),
|
||||||
m_timerId(-1),
|
m_timerId(-1),
|
||||||
m_serialFrame(true),
|
|
||||||
m_verbose(0)
|
m_verbose(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -149,6 +86,7 @@ LauncherPrivate::LauncherPrivate() :
|
|||||||
Launcher::Launcher() :
|
Launcher::Launcher() :
|
||||||
d(new LauncherPrivate)
|
d(new LauncherPrivate)
|
||||||
{
|
{
|
||||||
|
connect(&d->m_device, SIGNAL(messageReceived(TrkResult)), this, SLOT(handleResult(TrkResult)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Launcher::~Launcher()
|
Launcher::~Launcher()
|
||||||
@@ -180,7 +118,12 @@ void Launcher::setInstallFileName(const QString &name)
|
|||||||
|
|
||||||
void Launcher::setSerialFrame(bool b)
|
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)
|
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);
|
.arg(d->m_trkServerName, d->m_fileName, d->m_copySrcFileName, d->m_copyDstFileName, d->m_installFileName);
|
||||||
logMessage(msg);
|
logMessage(msg);
|
||||||
}
|
}
|
||||||
if (!openTrkPort(d->m_trkServerName, errorMessage))
|
if (!d->m_device.open(d->m_trkServerName, errorMessage))
|
||||||
return false;
|
return false;
|
||||||
d->m_timerId = startTimer(100);
|
d->m_timerId = startTimer(100);
|
||||||
sendTrkInitialPing();
|
sendTrkInitialPing();
|
||||||
@@ -210,6 +153,7 @@ bool Launcher::startServer(QString *errorMessage)
|
|||||||
void Launcher::setVerbose(int v)
|
void Launcher::setVerbose(int v)
|
||||||
{
|
{
|
||||||
d->m_verbose = v;
|
d->m_verbose = v;
|
||||||
|
d->m_device.setVerbose(v > 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void Launcher::installAndRun()
|
void Launcher::installAndRun()
|
||||||
@@ -226,60 +170,11 @@ void Launcher::logMessage(const QString &msg)
|
|||||||
qDebug() << "ADAPTER: " << qPrintable(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 *)
|
void Launcher::timerEvent(QTimerEvent *)
|
||||||
{
|
{
|
||||||
if (d->m_verbose>1)
|
if (d->m_verbose>1)
|
||||||
qDebug(".");
|
qDebug(".");
|
||||||
tryTrkWrite();
|
tryTrkWrite();
|
||||||
tryTrkRead();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
byte Launcher::nextTrkWriteToken()
|
byte Launcher::nextTrkWriteToken()
|
||||||
@@ -333,7 +228,7 @@ void Launcher::sendTrkAck(byte token)
|
|||||||
msg.data.append('\0');
|
msg.data.append('\0');
|
||||||
// The acknowledgement must not be queued!
|
// The acknowledgement must not be queued!
|
||||||
//queueMessage(msg);
|
//queueMessage(msg);
|
||||||
trkWrite(msg);
|
trkWriteRawMessage(msg);
|
||||||
// 01 90 00 07 7e 80 01 00 7d 5e 7e
|
// 01 90 00 07 7e 80 01 00 7d 5e 7e
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -353,80 +248,25 @@ void Launcher::tryTrkWrite()
|
|||||||
trkWrite(msg);
|
trkWrite(msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Launcher::trkWriteRawMessage(const TrkMessage &msg)
|
||||||
|
{
|
||||||
|
const QByteArray ba = frameMessage(msg.code, msg.token, msg.data, serialFrame());
|
||||||
|
logMessage("WRITE: " + stringFromArray(ba));
|
||||||
|
QString errorMessage;
|
||||||
|
if (!d->m_device.write(ba, &errorMessage))
|
||||||
|
logMessage(errorMessage);
|
||||||
|
}
|
||||||
|
|
||||||
void Launcher::trkWrite(const TrkMessage &msg)
|
void Launcher::trkWrite(const TrkMessage &msg)
|
||||||
{
|
{
|
||||||
QByteArray ba = frameMessage(msg.code, msg.token, msg.data, d->m_serialFrame);
|
|
||||||
|
|
||||||
d->m_writtenTrkMessages.insert(msg.token, msg);
|
d->m_writtenTrkMessages.insert(msg.token, msg);
|
||||||
d->m_trkWriteBusy = true;
|
d->m_trkWriteBusy = true;
|
||||||
|
trkWriteRawMessage(msg);
|
||||||
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;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
void Launcher::tryTrkRead()
|
|
||||||
{
|
|
||||||
#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;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Launcher::handleResult(const TrkResult &result)
|
void Launcher::handleResult(const TrkResult &result)
|
||||||
{
|
{
|
||||||
|
d->m_trkWriteBusy = false;
|
||||||
QByteArray prefix = "READ BUF: ";
|
QByteArray prefix = "READ BUF: ";
|
||||||
QByteArray str = result.toString().toUtf8();
|
QByteArray str = result.toString().toUtf8();
|
||||||
if (result.isDebugOutput) { // handle application output
|
if (result.isDebugOutput) { // handle application output
|
||||||
@@ -518,10 +358,13 @@ void Launcher::handleResult(const TrkResult &result)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case TrkNotifyDeleted: { // NotifyDeleted
|
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);
|
sendTrkAck(result.token);
|
||||||
const char *data = result.data.data();
|
|
||||||
ushort itemType = extractShort(data);
|
|
||||||
if (itemType == 0) { // process
|
if (itemType == 0) { // process
|
||||||
sendTrkMessage(TrkDisconnect, CB(waitForTrkFinished));
|
sendTrkMessage(TrkDisconnect, CB(waitForTrkFinished));
|
||||||
}
|
}
|
||||||
|
@@ -53,6 +53,7 @@ public:
|
|||||||
bool startServer(QString *errorMessage);
|
bool startServer(QString *errorMessage);
|
||||||
void setVerbose(int v);
|
void setVerbose(int v);
|
||||||
void setSerialFrame(bool b);
|
void setSerialFrame(bool b);
|
||||||
|
bool serialFrame() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void copyingStarted();
|
void copyingStarted();
|
||||||
@@ -65,8 +66,10 @@ signals:
|
|||||||
public slots:
|
public slots:
|
||||||
void terminate();
|
void terminate();
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void handleResult(const TrkResult &data);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
bool openTrkPort(const QString &port, QString *errorMessage); // or server name for local server
|
|
||||||
void sendTrkMessage(unsigned char code,
|
void sendTrkMessage(unsigned char code,
|
||||||
TrkCallBack callBack = 0,
|
TrkCallBack callBack = 0,
|
||||||
const QByteArray &data = QByteArray(),
|
const QByteArray &data = QByteArray(),
|
||||||
@@ -77,6 +80,7 @@ private:
|
|||||||
void tryTrkRead();
|
void tryTrkRead();
|
||||||
// actually writes a message to the device
|
// actually writes a message to the device
|
||||||
void trkWrite(const TrkMessage &msg);
|
void trkWrite(const TrkMessage &msg);
|
||||||
|
void trkWriteRawMessage(const TrkMessage &msg);
|
||||||
// convienience messages
|
// convienience messages
|
||||||
void sendTrkInitialPing();
|
void sendTrkInitialPing();
|
||||||
void sendTrkAck(unsigned char token);
|
void sendTrkAck(unsigned char token);
|
||||||
@@ -99,8 +103,6 @@ private:
|
|||||||
void waitForTrkFinished(const TrkResult &data);
|
void waitForTrkFinished(const TrkResult &data);
|
||||||
|
|
||||||
void handleAndReportCreateProcess(const TrkResult &result);
|
void handleAndReportCreateProcess(const TrkResult &result);
|
||||||
void handleResult(const TrkResult &data);
|
|
||||||
|
|
||||||
void copyFileToRemote();
|
void copyFileToRemote();
|
||||||
void installRemotePackageSilently(const QString &filename);
|
void installRemotePackageSilently(const QString &filename);
|
||||||
void installAndRun();
|
void installAndRun();
|
||||||
|
323
tests/manual/trk/trkdevice.cpp
Normal file
323
tests/manual/trk/trkdevice.cpp
Normal file
@@ -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
|
84
tests/manual/trk/trkdevice.h
Normal file
84
tests/manual/trk/trkdevice.h
Normal file
@@ -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
|
@@ -1,6 +1,8 @@
|
|||||||
DEFINES += DEBUG_TRK=0
|
DEFINES += DEBUG_TRK=0
|
||||||
INCLUDEPATH *= $$PWD
|
INCLUDEPATH *= $$PWD
|
||||||
SOURCES += $$PWD/launcher.cpp \
|
SOURCES += $$PWD/launcher.cpp \
|
||||||
$$PWD/trkutils.cpp
|
$$PWD/trkutils.cpp \
|
||||||
|
$$PWD/trkdevice.cpp
|
||||||
HEADERS += $$PWD/trkutils.h \
|
HEADERS += $$PWD/trkutils.h \
|
||||||
|
$$PWD/trkdevice.h \
|
||||||
$$PWD/launcher.h
|
$$PWD/launcher.h
|
||||||
|
@@ -298,8 +298,11 @@ void TrkServer::readFromAdapter()
|
|||||||
if (packet != m_adapterReadBuffer)
|
if (packet != m_adapterReadBuffer)
|
||||||
logMessage("buffer: " + stringFromArray(m_adapterReadBuffer));
|
logMessage("buffer: " + stringFromArray(m_adapterReadBuffer));
|
||||||
|
|
||||||
while (!m_adapterReadBuffer.isEmpty())
|
while (!m_adapterReadBuffer.isEmpty()) {
|
||||||
handleAdapterMessage(extractResult(&m_adapterReadBuffer, m_serialFrame));
|
TrkResult r;
|
||||||
|
while (extractResult(&m_adapterReadBuffer, m_serialFrame, &r))
|
||||||
|
handleAdapterMessage(r);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data)
|
void TrkServer::writeToAdapter(byte command, byte token, const QByteArray &data)
|
||||||
|
@@ -50,6 +50,14 @@ TrkResult::TrkResult() :
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TrkResult::clear()
|
||||||
|
{
|
||||||
|
code = token= 0;
|
||||||
|
isDebugOutput = false;
|
||||||
|
data.clear();
|
||||||
|
cookie = QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
QString TrkResult::toString() const
|
QString TrkResult::toString() const
|
||||||
{
|
{
|
||||||
QString res = stringFromByte(code) + "[" + stringFromByte(token);
|
QString res = stringFromByte(code) + "[" + stringFromByte(token);
|
||||||
@@ -114,20 +122,20 @@ ushort isValidTrkResult(const QByteArray &buffer, bool serialFrame)
|
|||||||
return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size();
|
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);
|
const ushort len = isValidTrkResult(*buffer, serialFrame);
|
||||||
if (!len)
|
if (!len)
|
||||||
return result;
|
return false;
|
||||||
// handle receiving application output, which is not a regular command
|
// handle receiving application output, which is not a regular command
|
||||||
const int delimiterPos = serialFrame ? 4 : 0;
|
const int delimiterPos = serialFrame ? 4 : 0;
|
||||||
if (buffer->at(delimiterPos) != 0x7e) {
|
if (buffer->at(delimiterPos) != 0x7e) {
|
||||||
result.isDebugOutput = true;
|
result->isDebugOutput = true;
|
||||||
result.data = buffer->mid(delimiterPos, len);
|
result->data = buffer->mid(delimiterPos, len);
|
||||||
result.data.replace("\r\n", "\n");
|
result->data.replace("\r\n", "\n");
|
||||||
*buffer->remove(0, delimiterPos + len);
|
*buffer->remove(0, delimiterPos + len);
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
// FIXME: what happens if the length contains 0xfe?
|
// FIXME: what happens if the length contains 0xfe?
|
||||||
// Assume for now that it passes unencoded!
|
// Assume for now that it passes unencoded!
|
||||||
@@ -140,14 +148,14 @@ TrkResult extractResult(QByteArray *buffer, bool serialFrame)
|
|||||||
if (sum != 0xff)
|
if (sum != 0xff)
|
||||||
logMessage("*** CHECKSUM ERROR: " << byte(sum));
|
logMessage("*** CHECKSUM ERROR: " << byte(sum));
|
||||||
|
|
||||||
result.code = data.at(0);
|
result->code = data.at(0);
|
||||||
result.token = data.at(1);
|
result->token = data.at(1);
|
||||||
result.data = data.mid(2, data.size() - 3);
|
result->data = data.mid(2, data.size() - 3);
|
||||||
//logMessage(" REST BUF: " << stringFromArray(*buffer));
|
//logMessage(" REST BUF: " << stringFromArray(*buffer));
|
||||||
//logMessage(" CURR DATA: " << stringFromArray(data));
|
//logMessage(" CURR DATA: " << stringFromArray(data));
|
||||||
//QByteArray prefix = "READ BUF: ";
|
//QByteArray prefix = "READ BUF: ";
|
||||||
//logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data());
|
//logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data());
|
||||||
return result;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
ushort extractShort(const char *data)
|
ushort extractShort(const char *data)
|
||||||
|
@@ -172,6 +172,7 @@ struct Breakpoint
|
|||||||
struct TrkResult
|
struct TrkResult
|
||||||
{
|
{
|
||||||
TrkResult();
|
TrkResult();
|
||||||
|
void clear();
|
||||||
QString toString() const;
|
QString toString() const;
|
||||||
// 0 for no error.
|
// 0 for no error.
|
||||||
int errorCode() const;
|
int errorCode() const;
|
||||||
@@ -187,7 +188,7 @@ struct TrkResult
|
|||||||
// the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e
|
// the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e
|
||||||
QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame);
|
QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame);
|
||||||
ushort isValidTrkResult(const QByteArray &buffer, 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 errorMessage(byte code);
|
||||||
QByteArray hexNumber(uint n, int digits = 0);
|
QByteArray hexNumber(uint n, int digits = 0);
|
||||||
uint swapEndian(uint in);
|
uint swapEndian(uint in);
|
||||||
|
Reference in New Issue
Block a user