forked from qt-creator/qt-creator
Symbian/CODA: Add infrastructure for serial communication.
Add USB protocol and chunking.
This commit is contained in:
@@ -29,6 +29,7 @@
|
|||||||
|
|
||||||
#include "tcftrkdevice.h"
|
#include "tcftrkdevice.h"
|
||||||
#include "json.h"
|
#include "json.h"
|
||||||
|
#include "trkutils.h"
|
||||||
|
|
||||||
#include <QtNetwork/QAbstractSocket>
|
#include <QtNetwork/QAbstractSocket>
|
||||||
#include <QtCore/QDebug>
|
#include <QtCore/QDebug>
|
||||||
@@ -40,7 +41,62 @@
|
|||||||
|
|
||||||
enum { debug = 0 };
|
enum { debug = 0 };
|
||||||
|
|
||||||
static const char messageTerminatorC[] = "\003\001";
|
static const char wlanMessageTerminatorC[] = "\003\001";
|
||||||
|
|
||||||
|
// Serial Ping: 0xfc,0x1f
|
||||||
|
static const char serialPingC[] = "\xfc\x1f";
|
||||||
|
// Serial Pong: 0xfc,0xf1, followed by version info
|
||||||
|
static const char serialPongC[] = "\xfc\xf1";
|
||||||
|
|
||||||
|
static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]";
|
||||||
|
|
||||||
|
static const unsigned serialChunkLength = 0x400; // 1K max USB router
|
||||||
|
static const int maxSerialMessageLength = 0x10000; // give chunking scheme
|
||||||
|
|
||||||
|
// Create USB router frame
|
||||||
|
static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target)
|
||||||
|
{
|
||||||
|
target->append(char(0x01));
|
||||||
|
target->append(char(0x92)); // CODA serial message ID
|
||||||
|
appendShort(target, ushort(data.size()), trk::BigEndian);
|
||||||
|
target->append(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Split in chunks of 1K according to CODA protocol chunking
|
||||||
|
static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
|
||||||
|
{
|
||||||
|
static const int chunkSize = serialChunkLength - 2; // 2 Header bytes
|
||||||
|
const int size = dataIn.size();
|
||||||
|
QByteArray frame;
|
||||||
|
// Do we need to split?
|
||||||
|
if (size < chunkSize) { // Nope, all happy.
|
||||||
|
frame.reserve(size + 4);
|
||||||
|
encodeSerialFrame(dataIn, &frame);
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
// Split.
|
||||||
|
unsigned chunkCount = size / chunkSize;
|
||||||
|
if (size % chunkSize)
|
||||||
|
chunkCount++;
|
||||||
|
if (debug)
|
||||||
|
qDebug("Serial: Splitting message of %d bytes into %u chunks of %d", size, chunkCount, chunkSize);
|
||||||
|
|
||||||
|
frame.reserve((4 + serialChunkLength) * chunkCount);
|
||||||
|
int pos = 0;
|
||||||
|
for (unsigned c = chunkCount - 1; pos < size ; c--) {
|
||||||
|
QByteArray chunk; // chunk with long message start/continuation code
|
||||||
|
chunk.reserve(serialChunkLength);
|
||||||
|
chunk.append(pos ? char(0) : char(0xfe));
|
||||||
|
chunk.append(char(static_cast<unsigned char>(c))); // Avoid any signedness issues.
|
||||||
|
const int chunkEnd = qMin(pos + chunkSize, size);
|
||||||
|
chunk.append(dataIn.mid(pos, chunkEnd - pos));
|
||||||
|
encodeSerialFrame(chunk, &frame);
|
||||||
|
pos = chunkEnd;
|
||||||
|
}
|
||||||
|
if (debug > 1)
|
||||||
|
qDebug("Serial chunked:\n%s", qPrintable(tcftrk::formatData(frame)));
|
||||||
|
return frame;
|
||||||
|
}
|
||||||
|
|
||||||
namespace tcftrk {
|
namespace tcftrk {
|
||||||
// ------------- TcfTrkCommandError
|
// ------------- TcfTrkCommandError
|
||||||
@@ -272,11 +328,12 @@ struct TcfTrkDevicePrivate {
|
|||||||
TokenWrittenMessageMap m_writtenMessages;
|
TokenWrittenMessageMap m_writtenMessages;
|
||||||
QVector<QByteArray> m_registerNames;
|
QVector<QByteArray> m_registerNames;
|
||||||
QVector<QByteArray> m_fakeGetMRegisterValues;
|
QVector<QByteArray> m_fakeGetMRegisterValues;
|
||||||
|
bool m_serialFrame;
|
||||||
};
|
};
|
||||||
|
|
||||||
TcfTrkDevicePrivate::TcfTrkDevicePrivate() :
|
TcfTrkDevicePrivate::TcfTrkDevicePrivate() :
|
||||||
m_messageTerminator(messageTerminatorC),
|
m_messageTerminator(wlanMessageTerminatorC),
|
||||||
m_verbose(0), m_token(0)
|
m_verbose(0), m_token(0), m_serialFrame(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -380,7 +437,12 @@ void TcfTrkDevice::slotDeviceSocketStateChanged()
|
|||||||
|
|
||||||
static inline QString debugMessage(QByteArray message, const char *prefix = 0)
|
static inline QString debugMessage(QByteArray message, const char *prefix = 0)
|
||||||
{
|
{
|
||||||
message.replace('\0', '|');
|
const bool isBinary = !message.isEmpty() && message.at(0) < 0;
|
||||||
|
if (isBinary) {
|
||||||
|
message = message.toHex(); // Some serial special message
|
||||||
|
} else {
|
||||||
|
message.replace('\0', '|');
|
||||||
|
}
|
||||||
const QString messageS = QString::fromLatin1(message);
|
const QString messageS = QString::fromLatin1(message);
|
||||||
return prefix ?
|
return prefix ?
|
||||||
(QLatin1String(prefix) + messageS) : messageS;
|
(QLatin1String(prefix) + messageS) : messageS;
|
||||||
@@ -388,30 +450,101 @@ static inline QString debugMessage(QByteArray message, const char *prefix = 0)
|
|||||||
|
|
||||||
void TcfTrkDevice::slotDeviceReadyRead()
|
void TcfTrkDevice::slotDeviceReadyRead()
|
||||||
{
|
{
|
||||||
d->m_readBuffer += d->m_device->readAll();
|
const QByteArray newData = d->m_device->readAll();
|
||||||
|
d->m_readBuffer += newData;
|
||||||
|
if (debug)
|
||||||
|
qDebug("ReadBuffer: %s", qPrintable(trk::stringFromArray(newData)));
|
||||||
|
if (d->m_serialFrame) {
|
||||||
|
deviceReadyReadSerial();
|
||||||
|
} else {
|
||||||
|
deviceReadyReadWLAN();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL'
|
||||||
|
// and return message position and size.
|
||||||
|
static inline QPair<int, int> findSerialHeader(const QByteArray &in)
|
||||||
|
{
|
||||||
|
const int size = in.size();
|
||||||
|
const char header1 = 0x1;
|
||||||
|
const char header2 = char(0x92);
|
||||||
|
// Header should in theory always be at beginning of
|
||||||
|
// buffer. Warn if there are bogus data in-between.
|
||||||
|
for (int pos = 0; pos < size; ) {
|
||||||
|
if (pos + 4 < size && in.at(pos) == header1 && in.at(pos + 1) == header2) {
|
||||||
|
const int length = trk::extractShort(in.constData() + 2);
|
||||||
|
return QPair<int, int>(pos + 4, length);
|
||||||
|
}
|
||||||
|
// Find next
|
||||||
|
pos = in.indexOf(header1, pos + 1);
|
||||||
|
qWarning("Bogus data received on serial line: %s\n"
|
||||||
|
"Frame Header at: %d", qPrintable(trk::stringFromArray(in)), pos);
|
||||||
|
if (pos < 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return QPair<int, int>(-1, -1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcfTrkDevice::deviceReadyReadSerial()
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
// Extract message (pos,len)
|
||||||
|
const QPair<int, int> messagePos = findSerialHeader(d->m_readBuffer);
|
||||||
|
if (messagePos.first < 0)
|
||||||
|
break;
|
||||||
|
// Do we have the complete message?
|
||||||
|
const int messageEnd = messagePos.first + messagePos.second;
|
||||||
|
if (messageEnd > d->m_readBuffer.size())
|
||||||
|
break;
|
||||||
|
const QByteArray message = d->m_readBuffer.mid(messagePos.first, messagePos.second);
|
||||||
|
// Is thing a ping/pong response
|
||||||
|
if (debug > 1)
|
||||||
|
qDebug("Serial message: at %d (%d bytes) of %d: %s",
|
||||||
|
messagePos.first, messagePos.second, d->m_readBuffer.size(),
|
||||||
|
qPrintable(trk::stringFromArray(message)));
|
||||||
|
if (message.startsWith(serialPongC)) {
|
||||||
|
const QString version = QString::fromLatin1(message.mid(sizeof(serialPongC) - 1));
|
||||||
|
emitLogMessage(QString::fromLatin1("Serial connection from '%1'").arg(version));
|
||||||
|
emit serialPong(version);
|
||||||
|
// Answer with locator.
|
||||||
|
writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
|
||||||
|
} else {
|
||||||
|
processMessage(message);
|
||||||
|
}
|
||||||
|
d->m_readBuffer.remove(0, messageEnd);
|
||||||
|
} while (d->m_readBuffer.isEmpty());
|
||||||
|
checkSendQueue(); // Send off further messages
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcfTrkDevice::deviceReadyReadWLAN()
|
||||||
|
{
|
||||||
// Take complete message off front of readbuffer.
|
// Take complete message off front of readbuffer.
|
||||||
do {
|
do {
|
||||||
const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator);
|
const int messageEndPos = d->m_readBuffer.indexOf(d->m_messageTerminator);
|
||||||
if (messageEndPos == -1)
|
if (messageEndPos == -1)
|
||||||
break;
|
break;
|
||||||
if (messageEndPos == 0) {
|
if (messageEndPos == 0) {
|
||||||
// TCF TRK 4.0.5 emits empty messages on errors.
|
// TCF TRK 4.0.5 emits empty messages on errors.
|
||||||
emitLogMessage(QString::fromLatin1("An empty TCF TRK message has been received."));
|
emitLogMessage(QString::fromLatin1("An empty TCF TRK message has been received."));
|
||||||
} else {
|
} else {
|
||||||
const QByteArray message = d->m_readBuffer.left(messageEndPos);
|
processMessage(d->m_readBuffer.left(messageEndPos));
|
||||||
if (debug)
|
|
||||||
qDebug("Read %d bytes:\n%s", message.size(), qPrintable(formatData(message)));
|
|
||||||
if (const int errorCode = parseMessage(message)) {
|
|
||||||
emitLogMessage(QString::fromLatin1("Parse error %1 : %2").
|
|
||||||
arg(errorCode).arg(debugMessage(message)));
|
|
||||||
if (debug)
|
|
||||||
qDebug("Parse error %d for %d bytes:\n%s", errorCode,
|
|
||||||
message.size(), qPrintable(formatData(message)));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size());
|
d->m_readBuffer.remove(0, messageEndPos + d->m_messageTerminator.size());
|
||||||
} while (!d->m_readBuffer.isEmpty());
|
} while (!d->m_readBuffer.isEmpty());
|
||||||
checkSendQueue(); // Send off further message
|
checkSendQueue(); // Send off further messages
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcfTrkDevice::processMessage(const QByteArray &message)
|
||||||
|
{
|
||||||
|
if (debug)
|
||||||
|
qDebug("Read %d bytes:\n%s", message.size(), qPrintable(formatData(message)));
|
||||||
|
if (const int errorCode = parseMessage(message)) {
|
||||||
|
emitLogMessage(QString::fromLatin1("Parse error %1 : %2").
|
||||||
|
arg(errorCode).arg(debugMessage(message)));
|
||||||
|
if (debug)
|
||||||
|
qDebug("Parse error %d for %d bytes:\n%s", errorCode,
|
||||||
|
message.size(), qPrintable(formatData(message)));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Split \0-terminated message into tokens, skipping the initial type character
|
// Split \0-terminated message into tokens, skipping the initial type character
|
||||||
@@ -551,8 +684,6 @@ int TcfTrkDevice::parseTcfCommandReply(char type, const QVector<QByteArray> &tok
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]";
|
|
||||||
|
|
||||||
int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
|
int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
|
||||||
{
|
{
|
||||||
// Event: Ignore the periodical heartbeat event, answer 'Hello',
|
// Event: Ignore the periodical heartbeat event, answer 'Hello',
|
||||||
@@ -572,9 +703,10 @@ int TcfTrkDevice::parseTcfEvent(const QVector<QByteArray> &tokens)
|
|||||||
// Parse known events, emit signals
|
// Parse known events, emit signals
|
||||||
QScopedPointer<TcfTrkEvent> knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values));
|
QScopedPointer<TcfTrkEvent> knownEvent(TcfTrkEvent::parseEvent(service, tokens.at(1), values));
|
||||||
if (!knownEvent.isNull()) {
|
if (!knownEvent.isNull()) {
|
||||||
// Answer hello event.
|
// Answer hello event (WLAN)
|
||||||
if (knownEvent->type() == TcfTrkEvent::LocatorHello)
|
if (knownEvent->type() == TcfTrkEvent::LocatorHello)
|
||||||
writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
|
if (!d->m_serialFrame)
|
||||||
|
writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
|
||||||
emit tcfEvent(*knownEvent);
|
emit tcfEvent(*knownEvent);
|
||||||
}
|
}
|
||||||
emit genericTcfEvent(service, tokens.at(1), values);
|
emit genericTcfEvent(service, tokens.at(1), values);
|
||||||
@@ -600,6 +732,16 @@ unsigned TcfTrkDevice::verbose() const
|
|||||||
return d->m_verbose;
|
return d->m_verbose;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool TcfTrkDevice::serialFrame() const
|
||||||
|
{
|
||||||
|
return d->m_serialFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
void TcfTrkDevice::setSerialFrame(bool s)
|
||||||
|
{
|
||||||
|
d->m_serialFrame = s;
|
||||||
|
}
|
||||||
|
|
||||||
void TcfTrkDevice::setVerbose(unsigned v)
|
void TcfTrkDevice::setVerbose(unsigned v)
|
||||||
{
|
{
|
||||||
d->m_verbose = v;
|
d->m_verbose = v;
|
||||||
@@ -625,6 +767,17 @@ bool TcfTrkDevice::checkOpen()
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TcfTrkDevice::sendSerialPing()
|
||||||
|
{
|
||||||
|
if (!checkOpen())
|
||||||
|
return;
|
||||||
|
|
||||||
|
setSerialFrame(true);
|
||||||
|
writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false);
|
||||||
|
if (d->m_verbose)
|
||||||
|
emitLogMessage(QLatin1String("Ping..."));
|
||||||
|
}
|
||||||
|
|
||||||
void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command,
|
void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const char *command,
|
||||||
const char *commandParameters, // may contain '\0'
|
const char *commandParameters, // may contain '\0'
|
||||||
int commandParametersLength,
|
int commandParametersLength,
|
||||||
@@ -673,18 +826,29 @@ void TcfTrkDevice::sendTcfTrkMessage(MessageType mt, Services service, const cha
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Enclose in message frame and write.
|
// Enclose in message frame and write.
|
||||||
void TcfTrkDevice::writeMessage(QByteArray data)
|
void TcfTrkDevice::writeMessage(QByteArray data, bool ensureTerminating0)
|
||||||
{
|
{
|
||||||
if (!checkOpen())
|
if (!checkOpen())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
if (d->m_serialFrame && data.size() > maxSerialMessageLength) {
|
||||||
|
qCritical("Attempt to send large message (%d bytes) exceeding the "
|
||||||
|
"limit of %d bytes over serial channel. Skipping.",
|
||||||
|
data.size(), maxSerialMessageLength);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (d->m_verbose)
|
if (d->m_verbose)
|
||||||
emitLogMessage(debugMessage(data, "TCF <-"));
|
emitLogMessage(debugMessage(data, "TCF <-"));
|
||||||
|
|
||||||
// Ensure \0-termination which easily gets lost in QByteArray CT.
|
// Ensure \0-termination which easily gets lost in QByteArray CT.
|
||||||
if (!data.endsWith('\0'))
|
if (ensureTerminating0 && !data.endsWith('\0'))
|
||||||
data.append('\0');
|
data.append('\0');
|
||||||
data += d->m_messageTerminator;
|
if (d->m_serialFrame) {
|
||||||
|
data = encodeUsbSerialMessage(data);
|
||||||
|
} else {
|
||||||
|
data += d->m_messageTerminator;
|
||||||
|
}
|
||||||
|
|
||||||
if (debug > 1)
|
if (debug > 1)
|
||||||
qDebug("Writing:\n%s", qPrintable(formatData(data)));
|
qDebug("Writing:\n%s", qPrintable(formatData(data)));
|
||||||
|
|||||||
@@ -132,11 +132,20 @@ http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services
|
|||||||
* single commands. As soon as 'Registers::getm' is natively supported, all code
|
* single commands. As soon as 'Registers::getm' is natively supported, all code
|
||||||
* related to 'FakeRegisterGetm' should be removed. The workaround requires that
|
* related to 'FakeRegisterGetm' should be removed. The workaround requires that
|
||||||
* the register name is known.
|
* the register name is known.
|
||||||
*/
|
* CODA notes:
|
||||||
|
* - Commands are accepted only after receiving the Locator Hello event
|
||||||
|
* - Serial communication initiation sequence:
|
||||||
|
* Send serial ping from host sendSerialPing() -> receive pong response with
|
||||||
|
* version information -> Send Locator Hello Event -> Receive Locator Hello Event
|
||||||
|
* -> Commands are accepted.
|
||||||
|
* - WLAN communication initiation sequence:
|
||||||
|
* Receive Locator Hello Event from CODA -> Commands are accepted.
|
||||||
|
*/
|
||||||
|
|
||||||
class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject
|
class SYMBIANUTILS_EXPORT TcfTrkDevice : public QObject
|
||||||
{
|
{
|
||||||
Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose)
|
Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose)
|
||||||
|
Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
// Flags for FileSystem:open
|
// Flags for FileSystem:open
|
||||||
@@ -163,6 +172,8 @@ public:
|
|||||||
virtual ~TcfTrkDevice();
|
virtual ~TcfTrkDevice();
|
||||||
|
|
||||||
unsigned verbose() const;
|
unsigned verbose() const;
|
||||||
|
bool serialFrame() const;
|
||||||
|
void setSerialFrame(bool);
|
||||||
|
|
||||||
// Mapping of register names to indices for multi-requests.
|
// Mapping of register names to indices for multi-requests.
|
||||||
// Register names can be retrieved via 'Registers:getChildren' (requires
|
// Register names can be retrieved via 'Registers:getChildren' (requires
|
||||||
@@ -174,6 +185,9 @@ public:
|
|||||||
IODevicePtr takeDevice();
|
IODevicePtr takeDevice();
|
||||||
void setDevice(const IODevicePtr &dp);
|
void setDevice(const IODevicePtr &dp);
|
||||||
|
|
||||||
|
// Serial Only: Initiate communication. Will emit serialPong() signal with version.
|
||||||
|
void sendSerialPing();
|
||||||
|
|
||||||
// Send with parameters from string (which may contain '\0').
|
// Send with parameters from string (which may contain '\0').
|
||||||
void sendTcfTrkMessage(MessageType mt, Services service,
|
void sendTcfTrkMessage(MessageType mt, Services service,
|
||||||
const char *command,
|
const char *command,
|
||||||
@@ -338,6 +352,7 @@ public:
|
|||||||
signals:
|
signals:
|
||||||
void genericTcfEvent(int service, const QByteArray &name, const QVector<tcftrk::JsonValue> &value);
|
void genericTcfEvent(int service, const QByteArray &name, const QVector<tcftrk::JsonValue> &value);
|
||||||
void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent);
|
void tcfEvent(const tcftrk::TcfTrkEvent &knownEvent);
|
||||||
|
void serialPong(const QString &codaVersion);
|
||||||
|
|
||||||
void logMessage(const QString &);
|
void logMessage(const QString &);
|
||||||
void error(const QString &);
|
void error(const QString &);
|
||||||
@@ -351,11 +366,15 @@ private slots:
|
|||||||
void slotDeviceReadyRead();
|
void slotDeviceReadyRead();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void deviceReadyReadSerial();
|
||||||
|
void deviceReadyReadWLAN();
|
||||||
|
|
||||||
bool checkOpen();
|
bool checkOpen();
|
||||||
void checkSendQueue();
|
void checkSendQueue();
|
||||||
void writeMessage(QByteArray data);
|
void writeMessage(QByteArray data, bool ensureTerminating0 = true);
|
||||||
void emitLogMessage(const QString &);
|
void emitLogMessage(const QString &);
|
||||||
int parseMessage(const QByteArray &);
|
inline int parseMessage(const QByteArray &);
|
||||||
|
void processMessage(const QByteArray &message);
|
||||||
int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens);
|
int parseTcfCommandReply(char type, const QVector<QByteArray> &tokens);
|
||||||
int parseTcfEvent(const QVector<QByteArray> &tokens);
|
int parseTcfEvent(const QVector<QByteArray> &tokens);
|
||||||
// Send with parameters from string (which may contain '\0').
|
// Send with parameters from string (which may contain '\0').
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
DEFINES += SYMBIANUTILS_INCLUDE_PRI
|
DEFINES += SYMBIANUTILS_INCLUDE_PRI
|
||||||
|
|
||||||
|
include(../../../qtcreator.pri)
|
||||||
include(../../../src/shared/symbianutils/symbianutils.pri)
|
include(../../../src/shared/symbianutils/symbianutils.pri)
|
||||||
|
# include(../../../src/libs/3rdparty/qextserialport/qextserialport.pri)
|
||||||
|
|
||||||
QT += core gui network
|
QT += core gui network
|
||||||
TARGET = codaclient
|
TARGET = codaclient
|
||||||
|
|||||||
@@ -29,6 +29,10 @@
|
|||||||
|
|
||||||
#include "codaclientapplication.h"
|
#include "codaclientapplication.h"
|
||||||
|
|
||||||
|
#ifdef HAS_SERIALPORT
|
||||||
|
# include <qextserialport/qextserialport.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "tcftrkdevice.h"
|
#include "tcftrkdevice.h"
|
||||||
#include <QtNetwork/QTcpSocket>
|
#include <QtNetwork/QTcpSocket>
|
||||||
#include <QtCore/QFile>
|
#include <QtCore/QFile>
|
||||||
@@ -255,31 +259,27 @@ bool CodaClientApplication::start()
|
|||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
case Launch: {
|
case Launch: {
|
||||||
const QString args = m_launchArgs.join(QString(QLatin1Char(' ')));
|
const QString args = m_launchArgs.join(QString(QLatin1Char(' ')));
|
||||||
std::printf("Launching 0x%x '%s '%s' on %s:%hu (debug: %d)\n",
|
std::printf("Launching 0x%x '%s '%s' (debug: %d)\n",
|
||||||
m_launchUID, qPrintable(m_launchBinary),
|
m_launchUID, qPrintable(m_launchBinary),
|
||||||
qPrintable(args), qPrintable(m_address), m_port,
|
qPrintable(args), m_launchDebug);
|
||||||
m_launchDebug);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case Install:
|
case Install:
|
||||||
std::printf("Installing '%s' to '%s' on %s:%hu\n",
|
std::printf("Installing '%s' to '%s'\n",
|
||||||
qPrintable(m_installSisFile), qPrintable(m_installTargetDrive),
|
qPrintable(m_installSisFile), qPrintable(m_installTargetDrive));
|
||||||
qPrintable(m_address), m_port);
|
|
||||||
break;
|
break;
|
||||||
case Put:
|
case Put:
|
||||||
std::printf("Copying '%s' to '%s' on %s:%hu in chunks of %lluKB\n",
|
std::printf("Copying '%s' to '%s' in chunks of %lluKB\n",
|
||||||
qPrintable(m_putLocalFile), qPrintable(m_putRemoteFile),
|
qPrintable(m_putLocalFile), qPrintable(m_putRemoteFile),
|
||||||
qPrintable(m_address), m_port, m_putChunkSize / 1024);
|
m_putChunkSize / 1024);
|
||||||
break;
|
break;
|
||||||
case Stat:
|
case Stat:
|
||||||
std::printf("Retrieving attributes of '%s' from %s:%hu\n",
|
std::printf("Retrieving attributes of '%s'\n", qPrintable(m_statRemoteFile));
|
||||||
qPrintable(m_statRemoteFile), qPrintable(m_address), m_port);
|
|
||||||
break;
|
break;
|
||||||
case Invalid:
|
case Invalid:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// Start connection
|
// Start connection
|
||||||
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
|
|
||||||
m_trkDevice.reset(new tcftrk::TcfTrkDevice);
|
m_trkDevice.reset(new tcftrk::TcfTrkDevice);
|
||||||
m_trkDevice->setVerbose(m_verbose);
|
m_trkDevice->setVerbose(m_verbose);
|
||||||
connect(m_trkDevice.data(), SIGNAL(error(QString)),
|
connect(m_trkDevice.data(), SIGNAL(error(QString)),
|
||||||
@@ -288,9 +288,48 @@ bool CodaClientApplication::start()
|
|||||||
this, SLOT(slotTrkLogMessage(QString)));
|
this, SLOT(slotTrkLogMessage(QString)));
|
||||||
connect(m_trkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)),
|
connect(m_trkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)),
|
||||||
this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
|
this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
|
||||||
m_trkDevice->setDevice(tcfTrkSocket);
|
if (m_address.startsWith(QLatin1String("/dev"))
|
||||||
tcfTrkSocket->connectToHost(m_address, m_port);
|
|| m_address.startsWith(QLatin1String("com"), Qt::CaseInsensitive)
|
||||||
std::printf("Connecting...\n");
|
|| m_address.startsWith(QLatin1Char('\\'))) {
|
||||||
|
#ifdef HAS_SERIALPORT
|
||||||
|
// Serial
|
||||||
|
#ifdef Q_OS_WIN
|
||||||
|
const QString fullPort = QextSerialPort::fullPortNameWin(m_address);
|
||||||
|
#else
|
||||||
|
const QString fullPort = m_address;
|
||||||
|
#endif
|
||||||
|
const QSharedPointer<QextSerialPort>
|
||||||
|
serialPort(new QextSerialPort(fullPort, QextSerialPort::EventDriven));
|
||||||
|
std::printf("Opening port %s...\n", qPrintable(fullPort));
|
||||||
|
|
||||||
|
// Magic USB serial parameters
|
||||||
|
serialPort->setTimeout(2000);
|
||||||
|
serialPort->setBaudRate(BAUD115200);
|
||||||
|
serialPort->setFlowControl(FLOW_OFF);
|
||||||
|
serialPort->setParity(PAR_NONE);
|
||||||
|
serialPort->setDataBits(DATA_8);
|
||||||
|
serialPort->setStopBits(STOP_1);
|
||||||
|
|
||||||
|
m_trkDevice->setSerialFrame(true);
|
||||||
|
m_trkDevice->setDevice(serialPort); // Grab all data from start
|
||||||
|
if (!serialPort->open(QIODevice::ReadWrite|QIODevice::Unbuffered)) {
|
||||||
|
std::fprintf(stderr, "Cannot open port: %s", qPrintable(serialPort->errorString()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
// Initiate communication
|
||||||
|
m_trkDevice->sendSerialPing();
|
||||||
|
serialPort->flush();
|
||||||
|
#else
|
||||||
|
std::fprintf(stderr, "Not implemented\n");
|
||||||
|
return false;
|
||||||
|
#endif
|
||||||
|
} else {
|
||||||
|
// TCP/IP
|
||||||
|
const QSharedPointer<QTcpSocket> tcfTrkSocket(new QTcpSocket);
|
||||||
|
m_trkDevice->setDevice(tcfTrkSocket);
|
||||||
|
tcfTrkSocket->connectToHost(m_address, m_port);
|
||||||
|
std::printf("Connecting to %s:%hu...\n", qPrintable(m_address), m_port);
|
||||||
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -399,8 +438,7 @@ void CodaClientApplication::handleFileSystemFStat(const tcftrk::TcfTrkCommandRes
|
|||||||
} else {
|
} else {
|
||||||
std::fprintf(stderr, "FStat failed: %s\n", qPrintable(result.toString()));
|
std::fprintf(stderr, "FStat failed: %s\n", qPrintable(result.toString()));
|
||||||
}
|
}
|
||||||
m_trkDevice->sendFileSystemCloseCommand(tcftrk::TcfTrkCallback(this, &CodaClientApplication::handleFileSystemClose),
|
closeRemoteFile();
|
||||||
m_remoteFileHandle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CodaClientApplication::handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result)
|
void CodaClientApplication::handleFileSystemClose(const tcftrk::TcfTrkCommandResult &result)
|
||||||
@@ -490,12 +528,14 @@ void CodaClientApplication::doExit(int ex)
|
|||||||
|
|
||||||
if (!m_trkDevice.isNull()) {
|
if (!m_trkDevice.isNull()) {
|
||||||
const QSharedPointer<QIODevice> dev = m_trkDevice->device();
|
const QSharedPointer<QIODevice> dev = m_trkDevice->device();
|
||||||
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(dev.data())) {
|
if (!dev.isNull()) {
|
||||||
if (socket->state() == QAbstractSocket::ConnectedState)
|
if (QAbstractSocket *socket = qobject_cast<QAbstractSocket *>(dev.data())) {
|
||||||
socket->disconnectFromHost();
|
if (socket->state() == QAbstractSocket::ConnectedState)
|
||||||
} else {
|
socket->disconnectFromHost();
|
||||||
if (dev->isOpen())
|
} else {
|
||||||
dev->close();
|
if (dev->isOpen())
|
||||||
|
dev->close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
std::printf("Exiting (%d)\n", ex);
|
std::printf("Exiting (%d)\n", ex);
|
||||||
|
|||||||
Reference in New Issue
Block a user