summaryrefslogtreecommitdiff
path: root/src/shared
diff options
context:
space:
mode:
Diffstat (limited to 'src/shared')
-rw-r--r--src/shared/json/json_global.h2
-rw-r--r--src/shared/proparser/spec_post.prf7
-rw-r--r--src/shared/symbianutils/callback.h149
-rw-r--r--src/shared/symbianutils/codadevice.cpp1479
-rw-r--r--src/shared/symbianutils/codadevice.h432
-rw-r--r--src/shared/symbianutils/codamessage.cpp592
-rw-r--r--src/shared/symbianutils/codamessage.h327
-rw-r--r--src/shared/symbianutils/codautils.cpp591
-rw-r--r--src/shared/symbianutils/codautils.h158
-rw-r--r--src/shared/symbianutils/codautils_p.h51
-rw-r--r--src/shared/symbianutils/symbiandevicemanager.cpp804
-rw-r--r--src/shared/symbianutils/symbiandevicemanager.h208
-rw-r--r--src/shared/symbianutils/symbianutils.pri42
-rw-r--r--src/shared/symbianutils/symbianutils_global.h44
-rw-r--r--src/shared/symbianutils/virtualserialdevice.cpp78
-rw-r--r--src/shared/symbianutils/virtualserialdevice.h115
-rw-r--r--src/shared/symbianutils/virtualserialdevice_posix.cpp338
-rw-r--r--src/shared/symbianutils/virtualserialdevice_win.cpp362
18 files changed, 1 insertions, 5778 deletions
diff --git a/src/shared/json/json_global.h b/src/shared/json/json_global.h
index 93caeaac87..910bb0948b 100644
--- a/src/shared/json/json_global.h
+++ b/src/shared/json/json_global.h
@@ -41,4 +41,4 @@
# define JSON_EXPORT Q_DECL_IMPORT
#endif
-#endif // SYMBIANUTILS_GLOBAL_H
+#endif // JSON_GLOBAL_H
diff --git a/src/shared/proparser/spec_post.prf b/src/shared/proparser/spec_post.prf
index 7560f95c41..fcc7314ce5 100644
--- a/src/shared/proparser/spec_post.prf
+++ b/src/shared/proparser/spec_post.prf
@@ -15,11 +15,6 @@ isEmpty(QMAKE_PLATFORM) {
|equals(MAKEFILE_GENERATOR, XCODE)) {
} else:equals(MAKEFILE_GENERATOR, GBUILD) {
TARGET_PLATFORM = unix
- } else:if(equals(MAKEFILE_GENERATOR, SYMBIAN_ABLD) \
- |equals(MAKEFILE_GENERATOR, SYMBIAN_SBSV2) \
- |equals(MAKEFILE_GENERATOR, SYMBIAN_UNIX) \
- |equals(MAKEFILE_GENERATOR, SYMBIAN_MINGW)) {
- TARGET_PLATFORM = symbian
} else {
error("Qmake spec sets an invalid MAKEFILE_GENERATOR.")
}
@@ -30,8 +25,6 @@ isEmpty(QMAKE_PLATFORM) {
QMAKE_PLATFORM = mac macx unix
else:equals(TARGET_PLATFORM, win32): \
QMAKE_PLATFORM = win32
- else:equals(TARGET_PLATFORM, symbian): \
- QMAKE_PLATFORM = symbian unix
else: \
error("Qmake spec sets an invalid TARGET_PLATFORM.")
}
diff --git a/src/shared/symbianutils/callback.h b/src/shared/symbianutils/callback.h
deleted file mode 100644
index 40a8676925..0000000000
--- a/src/shared/symbianutils/callback.h
+++ /dev/null
@@ -1,149 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef DEBUGGER_CALLBACK_H
-#define DEBUGGER_CALLBACK_H
-
-#include "symbianutils_global.h"
-
-namespace Coda {
-namespace Internal {
-
-/* Helper class for the 1-argument functor:
- * Cloneable base class for the implementation which is
- * invokeable with the argument. */
-template <class Argument>
-class CallbackImplBase
-{
- Q_DISABLE_COPY(CallbackImplBase)
-public:
- CallbackImplBase() {}
- virtual CallbackImplBase *clone() const = 0;
- virtual void invoke(Argument a) = 0;
- virtual ~CallbackImplBase() {}
-};
-
-/* Helper class for the 1-argument functor: Implementation for
- * a class instance with a member function pointer. */
-template <class Class, class Argument>
-class CallbackMemberPtrImpl : public CallbackImplBase<Argument>
-{
-public:
- typedef void (Class::*MemberFuncPtr)(Argument);
-
- CallbackMemberPtrImpl(Class *instance,
- MemberFuncPtr memberFunc) :
- m_instance(instance),
- m_memberFunc(memberFunc) {}
-
- virtual CallbackImplBase<Argument> *clone() const
- {
- return new CallbackMemberPtrImpl<Class, Argument>(m_instance, m_memberFunc);
- }
-
- virtual void invoke(Argument a)
- { (m_instance->*m_memberFunc)(a); }
-private:
- Class *m_instance;
- MemberFuncPtr m_memberFunc;
-};
-
-} // namespace Internal
-
-/* Default-constructible, copyable 1-argument functor providing an
- * operator()(Argument) that invokes a member function of a class:
- * \code
-class Foo {
-public:
- void print(const std::string &);
-};
-...
-Foo foo;
-Callback<const std::string &> f1(&foo, &Foo::print);
-f1("test");
-\endcode */
-
-template <class Argument>
-class Callback
-{
-public:
- Callback() : m_impl(0) {}
-
- template <class Class>
- Callback(Class *instance, void (Class::*memberFunc)(Argument)) :
- m_impl(new Internal::CallbackMemberPtrImpl<Class,Argument>(instance, memberFunc))
- {}
-
- ~Callback()
- {
- clean();
- }
-
- Callback(const Callback &rhs) :
- m_impl(0)
- {
- if (rhs.m_impl)
- m_impl = rhs.m_impl->clone();
- }
-
- Callback &operator=(const Callback &rhs)
- {
- if (this != &rhs) {
- clean();
- if (rhs.m_impl)
- m_impl = rhs.m_impl->clone();
- }
- return *this;
- }
-
- bool isNull() const { return m_impl == 0; }
- operator bool() const { return !isNull(); }
-
- void operator()(Argument a)
- {
- if (m_impl)
- m_impl->invoke(a);
- }
-
-private:
- void clean()
- {
- if (m_impl) {
- delete m_impl;
- m_impl = 0;
- }
- }
-
- Internal::CallbackImplBase<Argument> *m_impl;
-};
-
-} // namespace Coda
-
-#endif // DEBUGGER_CALLBACK_H
diff --git a/src/shared/symbianutils/codadevice.cpp b/src/shared/symbianutils/codadevice.cpp
deleted file mode 100644
index 3a22ec9ae1..0000000000
--- a/src/shared/symbianutils/codadevice.cpp
+++ /dev/null
@@ -1,1479 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "codadevice.h"
-#include "json.h"
-#include "codautils.h"
-
-#include <QAbstractSocket>
-#include <QDebug>
-#include <QVector>
-#include <QQueue>
-#include <QTextStream>
-#include <QDateTime>
-#include <QFileInfo>
-
-enum { debug = 0 };
-
-static const char tcpMessageTerminatorC[] = "\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\"]";
-
-/* Serial messages > (1K - 2) have to chunked in order to pass the USB
- * router as '0xfe char(chunkCount - 1) data' ... '0x0 char(chunkCount - 2) data'
- * ... '0x0 0x0 last-data' */
-static const unsigned serialChunkLength = 0x400; // 1K max USB router
-static const int maxSerialMessageLength = 0x10000; // given chunking scheme
-
-static const char validProtocolIdStart = (char)0x90;
-static const char validProtocolIdEnd = (char)0x95;
-static const char codaProtocolId = (char)0x92;
-static const unsigned char serialChunkingStart = 0xfe;
-static const unsigned char serialChunkingContinuation = 0x0;
-enum { SerialChunkHeaderSize = 2 };
-
-// Create USB router frame
-static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target, char protocolId)
-{
- target->append(char(0x01));
- target->append(protocolId);
- appendShort(target, ushort(data.size()), Coda::BigEndian);
- target->append(data);
-}
-
-// Split in chunks of 1K according to CODA protocol chunking
-static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
-{
- // Reserve 2 header bytes
- static const int chunkSize = serialChunkLength - SerialChunkHeaderSize;
- 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, codaProtocolId);
- 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 ? serialChunkingContinuation : serialChunkingStart);
- 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, codaProtocolId);
- pos = chunkEnd;
- }
- if (debug > 1)
- qDebug("Serial chunked:\n%s", qPrintable(Coda::formatData(frame)));
- return frame;
-}
-
-using namespace Json;
-namespace Coda {
-// ------------- CodaCommandError
-
-CodaCommandError::CodaCommandError() : timeMS(0), code(0), alternativeCode(0)
-{
-}
-
-void CodaCommandError::clear()
-{
- timeMS = 0;
- code = alternativeCode = 0;
- format.clear();
- alternativeOrganization.clear();
-}
-
-QDateTime CodaCommandResult::codaTimeToQDateTime(quint64 codaTimeMS)
-{
- const QDateTime time(QDate(1970, 1, 1));
- return time.addMSecs(codaTimeMS);
-}
-
-void CodaCommandError::write(QTextStream &str) const
-{
- if (isError()) {
- if (debug && timeMS)
- str << CodaCommandResult::codaTimeToQDateTime(timeMS).toString(Qt::ISODate) << ": ";
- str << "'" << format << '\'' //for symbian the format is the real error message
- << " Code: " << code;
- if (!alternativeOrganization.isEmpty())
- str << " ('" << alternativeOrganization << "', code: " << alternativeCode << ')';
- } else{
- str << "<No error>";
- }
-}
-
-QString CodaCommandError::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- write(str);
- return rc;
-}
-
-bool CodaCommandError::isError() const
-{
- return timeMS != 0 || code != 0 || !format.isEmpty() || alternativeCode != 0;
-}
-
-/* {"Time":1277459762255,"Code":1,"AltCode":-6,"AltOrg":"POSIX","Format":"Unknown error: -6"} */
-bool CodaCommandError::parse(const QVector<JsonValue> &values)
-{
- // Parse an arbitrary hash (that could as well be a command response)
- // and check for error elements. It looks like sometimes errors are appended
- // to other values.
- unsigned errorKeyCount = 0;
- clear();
- do {
- if (values.isEmpty())
- break;
- // Errors are mostly appended, except for FileSystem::open, in which case
- // a string "null" file handle (sic!) follows the error.
- const int last = values.size() - 1;
- const int checkIndex = last == 1 && values.at(last).data() == "null" ?
- last - 1 : last;
- if (values.at(checkIndex).type() != JsonValue::Object)
- break;
- foreach (const JsonValue &c, values.at(checkIndex).children()) {
- if (c.name() == "Time") {
- timeMS = c.data().toULongLong();
- errorKeyCount++;
- } else if (c.name() == "Code") {
- code = c.data().toLongLong();
- errorKeyCount++;
- } else if (c.name() == "Format") {
- format = c.data();
- errorKeyCount++;
- } else if (c.name() == "AltCode") {
- alternativeCode = c.data().toULongLong();
- errorKeyCount++;
- } else if (c.name() == "AltOrg") {
- alternativeOrganization = c.data();
- errorKeyCount++;
- }
- }
- } while (false);
- const bool errorFound = errorKeyCount >= 2u; // Should be at least 'Time', 'Code'.
- if (!errorFound)
- clear();
- if (debug) {
- qDebug("CodaCommandError::parse: Found error %d (%u): ", errorFound, errorKeyCount);
- if (!values.isEmpty())
- qDebug() << values.back().toString();
- }
- return errorFound;
-}
-
-// ------------ CodaCommandResult
-
-CodaCommandResult::CodaCommandResult(Type t) :
- type(t), service(LocatorService)
-{
-}
-
-CodaCommandResult::CodaCommandResult(char typeChar, Services s,
- const QByteArray &r,
- const QVector<JsonValue> &v,
- const QVariant &ck) :
- type(FailReply), service(s), request(r), values(v), cookie(ck)
-{
- switch (typeChar) {
- case 'N':
- type = FailReply;
- break;
- case 'P':
- type = ProgressReply;
- break;
- case 'R':
- type = commandError.parse(values) ? CommandErrorReply : SuccessReply;
- break;
- default:
- qWarning("Unknown CODA's reply type '%c'", typeChar);
- }
-}
-
-QString CodaCommandResult::errorString() const
-{
- QString rc;
- QTextStream str(&rc);
-
- switch (type) {
- case SuccessReply:
- case ProgressReply:
- str << "<No error>";
- return rc;
- case FailReply:
- str << "NAK";
- return rc;
- case CommandErrorReply:
- commandError.write(str);
- break;
- }
- if (debug) {
- // Append the failed command for reference
- str << " (Command was: '";
- QByteArray printableRequest = request;
- printableRequest.replace('\0', '|');
- str << printableRequest << "')";
- }
- return rc;
-}
-
-QString CodaCommandResult::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- str << "Command answer ";
- switch (type) {
- case SuccessReply:
- str << "[success]";
- break;
- case CommandErrorReply:
- str << "[command error]";
- break;
- case FailReply:
- str << "[fail (NAK)]";
- break;
- case ProgressReply:
- str << "[progress]";
- break;
- }
- str << ", " << values.size() << " values(s) to request: '";
- QByteArray printableRequest = request;
- printableRequest.replace('\0', '|');
- str << printableRequest << "' ";
- if (cookie.isValid())
- str << " cookie: " << cookie.toString();
- str << '\n';
- for (int i = 0, count = values.size(); i < count; i++)
- str << '#' << i << ' ' << values.at(i).toString() << '\n';
- if (type == CommandErrorReply)
- str << "Error: " << errorString();
- return rc;
-}
-
-CodaStatResponse::CodaStatResponse() : size(0)
-{
-}
-
-struct CodaSendQueueEntry
-{
- typedef CodaDevice::MessageType MessageType;
-
- explicit CodaSendQueueEntry(MessageType mt,
- int tok,
- Services s,
- const QByteArray &d,
- const CodaCallback &cb= CodaCallback(),
- const QVariant &ck = QVariant()) :
- messageType(mt), service(s), data(d), token(tok), cookie(ck), callback(cb) {}
-
- MessageType messageType;
- Services service;
- QByteArray data;
- int token;
- QVariant cookie;
- CodaCallback callback;
- unsigned specialHandling;
-};
-
-struct CodaDevicePrivate {
- typedef CodaDevice::IODevicePtr IODevicePtr;
- typedef QHash<int, CodaSendQueueEntry> TokenWrittenMessageMap;
-
- CodaDevicePrivate();
-
- const QByteArray m_tcpMessageTerminator;
-
- IODevicePtr m_device;
- unsigned m_verbose;
- QByteArray m_readBuffer;
- QByteArray m_serialBuffer; // for chunked messages
- int m_token;
- QQueue<CodaSendQueueEntry> m_sendQueue;
- TokenWrittenMessageMap m_writtenMessages;
- QVector<QByteArray> m_registerNames;
- QVector<QByteArray> m_fakeGetMRegisterValues;
- bool m_serialFrame;
- bool m_serialPingOnly;
-};
-
-CodaDevicePrivate::CodaDevicePrivate() :
- m_tcpMessageTerminator(tcpMessageTerminatorC),
- m_verbose(0), m_token(0), m_serialFrame(false), m_serialPingOnly(false)
-{
-}
-
-CodaDevice::CodaDevice(QObject *parent) :
- QObject(parent), d(new CodaDevicePrivate)
-{
- if (debug) setVerbose(true);
-}
-
-CodaDevice::~CodaDevice()
-{
- delete d;
-}
-
-QVector<QByteArray> CodaDevice::registerNames() const
-{
- return d->m_registerNames;
-}
-
-void CodaDevice::setRegisterNames(const QVector<QByteArray>& n)
-{
- d->m_registerNames = n;
- if (d->m_verbose) {
- QString msg;
- QTextStream str(&msg);
- const int count = n.size();
- str << "Registers (" << count << "): ";
- for (int i = 0; i < count; i++)
- str << '#' << i << '=' << n.at(i) << ' ';
- emitLogMessage(msg);
- }
-}
-
-CodaDevice::IODevicePtr CodaDevice::device() const
-{
- return d->m_device;
-}
-
-CodaDevice::IODevicePtr CodaDevice::takeDevice()
-{
- const IODevicePtr old = d->m_device;
- if (!old.isNull()) {
- old.data()->disconnect(this);
- d->m_device = IODevicePtr();
- }
- d->m_readBuffer.clear();
- d->m_token = 0;
- d->m_sendQueue.clear();
- return old;
-}
-
-void CodaDevice::setDevice(const IODevicePtr &dp)
-{
- if (dp.data() == d->m_device.data())
- return;
- if (dp.isNull()) {
- emitLogMessage(QLatin1String("Internal error: Attempt to set NULL device."));
- return;
- }
- takeDevice();
- d->m_device = dp;
- connect(dp.data(), SIGNAL(readyRead()), this, SLOT(slotDeviceReadyRead()));
- if (QAbstractSocket *s = qobject_cast<QAbstractSocket *>(dp.data())) {
- connect(s, SIGNAL(error(QAbstractSocket::SocketError)), this, SLOT(slotDeviceError()));
- connect(s, SIGNAL(stateChanged(QAbstractSocket::SocketState)), this, SLOT(slotDeviceSocketStateChanged()));
- }
-}
-
-void CodaDevice::slotDeviceError()
-{
- const QString message = d->m_device->errorString();
- emitLogMessage(message);
- emit error(message);
-}
-
-void CodaDevice::slotDeviceSocketStateChanged()
-{
- if (const QAbstractSocket *s = qobject_cast<const QAbstractSocket *>(d->m_device.data())) {
- const QAbstractSocket::SocketState st = s->state();
- switch (st) {
- case QAbstractSocket::UnconnectedState:
- emitLogMessage(QLatin1String("Unconnected"));
- break;
- case QAbstractSocket::HostLookupState:
- emitLogMessage(QLatin1String("HostLookupState"));
- break;
- case QAbstractSocket::ConnectingState:
- emitLogMessage(QLatin1String("Connecting"));
- break;
- case QAbstractSocket::ConnectedState:
- emitLogMessage(QLatin1String("Connected"));
- break;
- case QAbstractSocket::ClosingState:
- emitLogMessage(QLatin1String("Closing"));
- break;
- default:
- emitLogMessage(QString::fromLatin1("State %1").arg(st));
- break;
- }
- }
-}
-
-static inline QString debugMessage(QByteArray message, const char *prefix = 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);
- return prefix ?
- (QLatin1String(prefix) + messageS) : messageS;
-}
-
-void CodaDevice::slotDeviceReadyRead()
-{
- const QByteArray newData = d->m_device->readAll();
- d->m_readBuffer += newData;
- if (debug)
- qDebug("ReadBuffer: %s", qPrintable(Coda::stringFromArray(newData)));
- if (d->m_serialFrame) {
- deviceReadyReadSerial();
- } else {
- deviceReadyReadTcp();
- }
-}
-
-// Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL'
-// and return message position and size.
-QPair<int, int> CodaDevice::findSerialHeader(QByteArray &in)
-{
- static const char header1 = 0x1;
- // Header should in theory always be at beginning of
- // buffer. Warn if there are bogus data in-between.
-
- while (in.size() >= 4) {
- if (in.at(0) == header1 && in.at(1) == codaProtocolId) {
- // Good packet
- const int length = Coda::extractShort(in.constData() + 2);
- return QPair<int, int>(4, length);
- } else if (in.at(0) == header1 && in.at(1) >= validProtocolIdStart && in.at(1) <= validProtocolIdEnd) {
- // We recognise it but it's not a CODA message - emit it for any interested party to handle
- const int length = Coda::extractShort(in.constData() + 2);
- if (4 + length <= in.size()) {
- // We have all the data
- QByteArray data(in.mid(4, length));
- emit unknownEvent(in.at(1), data);
- in.remove(0, 4+length);
- // and continue
- } else {
- // If we don't have all this packet, there can't be any data following it, so return now
- // and wait for more data
- return QPair<int, int>(-1, -1);
- }
- } else {
- // Bad data - log it, remove it, and go round again
- int nextHeader = in.indexOf(header1, 1);
- QByteArray bad = in.mid(0, nextHeader);
- qWarning("Bogus data received on serial line: %s\n"
- "Frame Header at: %d", qPrintable(Coda::stringFromArray(bad)), nextHeader);
- in.remove(0, bad.length());
- // and continue
- }
- }
- return QPair<int, int>(-1, -1); // No more data, or not enough for a complete header
-}
-
-void CodaDevice::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;
- processSerialMessage(d->m_readBuffer.mid(messagePos.first, messagePos.second));
- d->m_readBuffer.remove(0, messageEnd);
- } while (!d->m_readBuffer.isEmpty());
- checkSendQueue(); // Send off further messages
-}
-
-void CodaDevice::processSerialMessage(const QByteArray &message)
-{
- if (debug > 1)
- qDebug("Serial message: %s",qPrintable(Coda::stringFromArray(message)));
- if (message.isEmpty())
- return;
- // Is thing a ping/pong response
- const int size = message.size();
- 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.
- if (!d->m_serialPingOnly)
- writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
- return;
- }
- // Check for long message (see top, '0xfe #number, data' or '0x0 #number, data')
- // TODO: This is currently untested.
- const unsigned char *dataU = reinterpret_cast<const unsigned char *>(message.constData());
- const bool isLongMessageStart = size > SerialChunkHeaderSize
- && *dataU == serialChunkingStart;
- const bool isLongMessageContinuation = size > SerialChunkHeaderSize
- && *dataU == serialChunkingContinuation;
- if (isLongMessageStart || isLongMessageContinuation) {
- const unsigned chunkNumber = *++dataU;
- if (isLongMessageStart) { // Start new buffer
- d->m_serialBuffer.clear();
- d->m_serialBuffer.reserve( (chunkNumber + 1) * serialChunkLength);
- }
- d->m_serialBuffer.append(message.mid(SerialChunkHeaderSize, size - SerialChunkHeaderSize));
- // Last chunk? - Process
- if (!chunkNumber) {
- processMessage(d->m_serialBuffer);
- d->m_serialBuffer.clear();
- d->m_serialBuffer.squeeze();
- }
- } else {
- processMessage(message); // Normal, unchunked message
- }
-}
-
-void CodaDevice::deviceReadyReadTcp()
-{
- // Take complete message off front of readbuffer.
- do {
- const int messageEndPos = d->m_readBuffer.indexOf(d->m_tcpMessageTerminator);
- if (messageEndPos == -1)
- break;
- if (messageEndPos == 0) {
- // CODA 4.0.5 emits empty messages on errors.
- emitLogMessage(QString::fromLatin1("An empty CODA message has been received."));
- } else {
- processMessage(d->m_readBuffer.left(messageEndPos));
- }
- d->m_readBuffer.remove(0, messageEndPos + d->m_tcpMessageTerminator.size());
- } while (!d->m_readBuffer.isEmpty());
- checkSendQueue(); // Send off further messages
-}
-
-void CodaDevice::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
-static inline QVector<QByteArray> splitMessage(const QByteArray &message)
-{
- QVector<QByteArray> tokens;
- tokens.reserve(7);
- const int messageSize = message.size();
- for (int pos = 2; pos < messageSize; ) {
- const int nextPos = message.indexOf('\0', pos);
- if (nextPos == -1)
- break;
- tokens.push_back(message.mid(pos, nextPos - pos));
- pos = nextPos + 1;
- }
- return tokens;
-}
-
-int CodaDevice::parseMessage(const QByteArray &message)
-{
- if (d->m_verbose)
- emitLogMessage(debugMessage(message, "CODA ->"));
- // Special JSON parse error message or protocol format error.
- // The port is usually closed after receiving it.
- // "\3\2{"Time":1276096098255,"Code":3,"Format": "Protocol format error"}"
- if (message.startsWith("\003\002")) {
- QByteArray text = message.mid(2);
- const QString errorMessage = QString::fromLatin1("Parse error received: %1").arg(QString::fromAscii(text));
- emit error(errorMessage);
- return 0;
- }
- if (message.size() < 4 || message.at(1) != '\0')
- return 1;
- // Split into tokens
- const char type = message.at(0);
- const QVector<QByteArray> tokens = splitMessage(message);
- switch (type) {
- case 'E':
- return parseCodaEvent(tokens);
- case 'R': // Command replies
- case 'N':
- case 'P':
- return parseCodaCommandReply(type, tokens);
- default:
- emitLogMessage(QString::fromLatin1("Unhandled message type: %1").arg(debugMessage(message)));
- return 756;
- }
- return 0;
-}
-
-int CodaDevice::parseCodaCommandReply(char type, const QVector<QByteArray> &tokens)
-{
- typedef CodaDevicePrivate::TokenWrittenMessageMap::iterator TokenWrittenMessageMapIterator;
- // Find the corresponding entry in the written messages hash.
- const int tokenCount = tokens.size();
- if (tokenCount < 1)
- return 234;
- bool tokenOk;
- const int token = tokens.at(0).toInt(&tokenOk);
- if (!tokenOk)
- return 235;
- const TokenWrittenMessageMapIterator it = d->m_writtenMessages.find(token);
- if (it == d->m_writtenMessages.end()) {
- qWarning("CodaDevice: Internal error: token %d not found for '%s'",
- token, qPrintable(joinByteArrays(tokens)));
- return 236;
- }
-
- CodaSendQueueEntry entry = it.value(); // FIXME: const?
- d->m_writtenMessages.erase(it);
-
- // No callback: remove entry from map, happy
- const unsigned specialHandling = entry.specialHandling;
- if (!entry.callback && specialHandling == 0u)
- return 0;
-
- // Parse values into JSON
- QVector<JsonValue> values;
- values.reserve(tokenCount);
- for (int i = 1; i < tokenCount; i++) {
- if (!tokens.at(i).isEmpty()) { // Strange: Empty tokens occur.
- const JsonValue value(tokens.at(i));
- if (value.isValid()) {
- values.push_back(value);
- } else {
- qWarning("JSON parse error for reply to command token %d: #%d '%s'",
- token, i, tokens.at(i).constData());
- return -1;
- }
- }
- }
- // Construct result and invoke callback, remove entry from map.
- CodaCommandResult result(type, entry.service, entry.data, values, entry.cookie);
- if (entry.callback)
- entry.callback(result);
-
- return 0;
-}
-
-int CodaDevice::parseCodaEvent(const QVector<QByteArray> &tokens)
-{
- // Event: Ignore the periodical heartbeat event, answer 'Hello',
- // emit signal for the rest
- if (tokens.size() < 3)
- return 433;
- const Services service = serviceFromName(tokens.at(0).constData());
- if (service == LocatorService && tokens.at(1) == "peerHeartBeat")
- return 0;
- QVector<JsonValue> values;
- for (int i = 2; i < tokens.size(); i++) {
- const JsonValue value(tokens.at(i));
- if (!value.isValid())
- return 434;
- values.push_back(value);
- }
- // Parse known events, emit signals
- QScopedPointer<CodaEvent> knownEvent(CodaEvent::parseEvent(service, tokens.at(1), values));
- if (!knownEvent.isNull()) {
- // Answer hello event (WLAN)
- if (knownEvent->type() == CodaEvent::LocatorHello)
- if (!d->m_serialFrame)
- writeMessage(QByteArray(locatorAnswerC, sizeof(locatorAnswerC)));
- emit codaEvent(*knownEvent);
- }
- emit genericCodaEvent(service, tokens.at(1), values);
-
- if (debug || d->m_verbose) {
- QString msg;
- QTextStream str(&msg);
- if (knownEvent.isNull()) {
- str << "Event: " << tokens.at(0) << ' ' << tokens.at(1) << '\n';
- foreach(const JsonValue &val, values)
- str << " " << val.toString() << '\n';
- } else {
- str << knownEvent->toString();
- }
- emitLogMessage(msg);
- }
-
- return 0;
-}
-
-unsigned CodaDevice::verbose() const
-{
- return d->m_verbose;
-}
-
-bool CodaDevice::serialFrame() const
-{
- return d->m_serialFrame;
-}
-
-void CodaDevice::setSerialFrame(bool s)
-{
- d->m_serialFrame = s;
-}
-
-void CodaDevice::setVerbose(unsigned v)
-{
- d->m_verbose = v;
-}
-
-void CodaDevice::emitLogMessage(const QString &m)
-{
- if (debug)
- qWarning("%s", qPrintable(m));
- emit logMessage(m);
-}
-
-bool CodaDevice::checkOpen()
-{
- if (d->m_device.isNull()) {
- emitLogMessage(QLatin1String("Internal error: No device set on CodaDevice."));
- return false;
- }
- if (!d->m_device->isOpen()) {
- emitLogMessage(QLatin1String("Internal error: Device not open in CodaDevice."));
- return false;
- }
- return true;
-}
-
-void CodaDevice::sendSerialPing(bool pingOnly)
-{
- if (!checkOpen())
- return;
-
- d->m_serialPingOnly = pingOnly;
- setSerialFrame(true);
- writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false);
- if (d->m_verbose)
- emitLogMessage(QLatin1String("Ping..."));
-}
-
-void CodaDevice::sendCodaMessage(MessageType mt, Services service, const char *command,
- const char *commandParameters, // may contain '\0'
- int commandParametersLength,
- const CodaCallback &callBack,
- const QVariant &cookie)
-
-{
- if (!checkOpen())
- return;
- // Format the message
- const int token = d->m_token++;
- QByteArray data;
- data.reserve(30 + commandParametersLength);
- data.append('C');
- data.append('\0');
- data.append(QByteArray::number(token));
- data.append('\0');
- data.append(serviceName(service));
- data.append('\0');
- data.append(command);
- data.append('\0');
- if (commandParametersLength)
- data.append(commandParameters, commandParametersLength);
- const CodaSendQueueEntry entry(mt, token, service, data, callBack, cookie);
- d->m_sendQueue.enqueue(entry);
- checkSendQueue();
-}
-
-void CodaDevice::sendCodaMessage(MessageType mt, Services service, const char *command,
- const QByteArray &commandParameters,
- const CodaCallback &callBack,
- const QVariant &cookie)
-{
- sendCodaMessage(mt, service, command, commandParameters.constData(), commandParameters.size(),
- callBack, cookie);
-}
-
-// Enclose in message frame and write.
-void CodaDevice::writeMessage(QByteArray data, bool ensureTerminating0)
-{
- if (!checkOpen())
- 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)
- emitLogMessage(debugMessage(data, "CODA <-"));
-
- // Ensure \0-termination which easily gets lost in QByteArray CT.
- if (ensureTerminating0 && !data.endsWith('\0'))
- data.append('\0');
- if (d->m_serialFrame) {
- data = encodeUsbSerialMessage(data);
- } else {
- data += d->m_tcpMessageTerminator;
- }
-
- if (debug > 1)
- qDebug("Writing:\n%s", qPrintable(formatData(data)));
-
- int result = d->m_device->write(data);
- if (result < data.length())
- qWarning("Failed to write all data! result=%d", result);
- if (QAbstractSocket *as = qobject_cast<QAbstractSocket *>(d->m_device.data()))
- as->flush();
-}
-
-void CodaDevice::writeCustomData(char protocolId, const QByteArray &data)
-{
- if (!checkOpen())
- return;
-
- if (!d->m_serialFrame) {
- qWarning("Ignoring request to send data to non-serial CodaDevice");
- return;
- }
- if (data.length() > 0xFFFF) {
- qWarning("Ignoring request to send too large packet, of size %d", data.length());
- return;
- }
- QByteArray framedData;
- encodeSerialFrame(data, &framedData, protocolId);
- device()->write(framedData);
-}
-
-void CodaDevice::checkSendQueue()
-{
- // Fire off messages or invoke noops until a message with reply is found
- // and an entry to writtenMessages is made.
- while (d->m_writtenMessages.empty()) {
- if (d->m_sendQueue.isEmpty())
- break;
- CodaSendQueueEntry entry = d->m_sendQueue.dequeue();
- switch (entry.messageType) {
- case MessageWithReply:
- d->m_writtenMessages.insert(entry.token, entry);
- writeMessage(entry.data);
- break;
- case MessageWithoutReply:
- writeMessage(entry.data);
- break;
- case NoopMessage: // Invoke the noop-callback for synchronization
- if (entry.callback) {
- CodaCommandResult noopResult(CodaCommandResult::SuccessReply);
- noopResult.cookie = entry.cookie;
- entry.callback(noopResult);
- }
- break;
- }
- }
-}
-
-// Fix slashes
-static inline QString fixFileName(QString in)
-{
- in.replace(QLatin1Char('/'), QLatin1Char('\\'));
- return in;
-}
-
-// Start a process (consisting of a non-reply setSettings and start).
-void CodaDevice::sendProcessStartCommand(const CodaCallback &callBack,
- const QString &binaryIn,
- unsigned uid,
- QStringList arguments,
- QString workingDirectory,
- bool debugControl,
- const QStringList &additionalLibraries,
- const QVariant &cookie)
-{
- // Obtain the bin directory, expand by c:/sys/bin if missing
- const QChar backSlash('\\');
- int slashPos = binaryIn.lastIndexOf(QLatin1Char('/'));
- if (slashPos == -1)
- slashPos = binaryIn.lastIndexOf(backSlash);
- const QString sysBin = QLatin1String("c:/sys/bin");
- const QString binaryFileName = slashPos == -1 ? binaryIn : binaryIn.mid(slashPos + 1);
-
- if (workingDirectory.isEmpty())
- workingDirectory = sysBin;
-
- // Format settings with empty dummy parameter
- QByteArray setData;
- JsonInputStream setStr(setData);
- setStr << "" << '\0'
- << '[' << "exeToLaunch" << ',' << "addExecutables" << ',' << "addLibraries" << ',' << "logUserTraces" << ',' << "attachAllWithLibraries" << ']'
- << '\0' << '['
- << binaryFileName << ','
- << '{' << binaryFileName << ':' << QString::number(uid, 16) << '}' << ','
- << additionalLibraries << ',' << true << ',' << false
- << ']';
- sendCodaMessage(
-#if 1
- MessageWithReply, // CODA 4.0.5 onwards
-#else
- MessageWithoutReply, // CODA 4.0.2
-#endif
- SettingsService, "set", setData);
-
- QByteArray startData;
- JsonInputStream startStr(startData);
- startStr << "" //We don't really know the drive of the working dir
- << '\0' << binaryFileName << '\0' << arguments << '\0'
- << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard)
- << debugControl;
- sendCodaMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie);
-}
-
-void CodaDevice::sendRunProcessCommand(const CodaCallback &callBack,
- const QString &processName,
- QStringList arguments,
- const QVariant &cookie)
-{
- QByteArray startData;
- JsonInputStream startStr(startData);
- startStr << "" //We don't really know the drive of the working dir
- << '\0' << processName << '\0' << arguments << '\0'
- << QStringList() << '\0' // Env is an array ["PATH=value"] (non-standard)
- << false; // Don't attach debugger
- sendCodaMessage(MessageWithReply, ProcessesService, "start", startData, callBack, cookie);
-}
-
-void CodaDevice::sendSettingsEnableLogCommand()
-{
-
- QByteArray setData;
- JsonInputStream setStr(setData);
- setStr << "" << '\0'
- << '[' << "logUserTraces" << ']'
- << '\0' << '['
- << true
- << ']';
- sendCodaMessage(
-#if 1
- MessageWithReply, // CODA 4.0.5 onwards
-#else
- MessageWithoutReply, // CODA 4.0.2
-#endif
- SettingsService, "set", setData);
-}
-
-void CodaDevice::sendProcessTerminateCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << id;
- sendCodaMessage(MessageWithReply, ProcessesService, "terminate", data, callBack, cookie);
-}
-
-void CodaDevice::sendRunControlTerminateCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << id;
- sendCodaMessage(MessageWithReply, RunControlService, "terminate", data, callBack, cookie);
-}
-
-// Non-standard: Remove executable from settings
-void CodaDevice::sendSettingsRemoveExecutableCommand(const QString &binaryIn,
- unsigned uid,
- const QStringList &additionalLibraries,
- const QVariant &cookie)
-{
- QByteArray setData;
- JsonInputStream setStr(setData);
- setStr << "" << '\0'
- << '[' << "removedExecutables" << ',' << "removedLibraries" << ']'
- << '\0' << '['
- << '{' << QFileInfo(binaryIn).fileName() << ':' << QString::number(uid, 16) << '}' << ','
- << additionalLibraries
- << ']';
- sendCodaMessage(MessageWithoutReply, SettingsService, "set", setData, CodaCallback(), cookie);
-}
-
-void CodaDevice::sendRunControlResumeCommand(const CodaCallback &callBack,
- const QByteArray &id,
- RunControlResumeMode mode,
- unsigned count,
- quint64 rangeStart,
- quint64 rangeEnd,
- const QVariant &cookie)
-{
- QByteArray resumeData;
- JsonInputStream str(resumeData);
- str << id << '\0' << int(mode) << '\0' << count;
- switch (mode) {
- case RM_STEP_OVER_RANGE:
- case RM_STEP_INTO_RANGE:
- case RM_REVERSE_STEP_OVER_RANGE:
- case RM_REVERSE_STEP_INTO_RANGE:
- str << '\0' << '{' << "RANGE_START" << ':' << rangeStart
- << ',' << "RANGE_END" << ':' << rangeEnd << '}';
- break;
- default:
- break;
- }
- sendCodaMessage(MessageWithReply, RunControlService, "resume", resumeData, callBack, cookie);
-}
-
-void CodaDevice::sendRunControlSuspendCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << id;
- sendCodaMessage(MessageWithReply, RunControlService, "suspend", data, callBack, cookie);
-}
-
-void CodaDevice::sendRunControlResumeCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie)
-{
- sendRunControlResumeCommand(callBack, id, RM_RESUME, 1, 0, 0, cookie);
-}
-
-void CodaDevice::sendBreakpointsAddCommand(const CodaCallback &callBack,
- const Breakpoint &bp,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << bp;
- sendCodaMessage(MessageWithReply, BreakpointsService, "add", data, callBack, cookie);
-}
-
-void CodaDevice::sendBreakpointsRemoveCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie)
-{
- sendBreakpointsRemoveCommand(callBack, QVector<QByteArray>(1, id), cookie);
-}
-
-void CodaDevice::sendBreakpointsRemoveCommand(const CodaCallback &callBack,
- const QVector<QByteArray> &ids,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << ids;
- sendCodaMessage(MessageWithReply, BreakpointsService, "remove", data, callBack, cookie);
-}
-
-void CodaDevice::sendBreakpointsEnableCommand(const CodaCallback &callBack,
- const QByteArray &id,
- bool enable,
- const QVariant &cookie)
-{
- sendBreakpointsEnableCommand(callBack, QVector<QByteArray>(1, id), enable, cookie);
-}
-
-void CodaDevice::sendBreakpointsEnableCommand(const CodaCallback &callBack,
- const QVector<QByteArray> &ids,
- bool enable,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << ids;
- sendCodaMessage(MessageWithReply, BreakpointsService,
- enable ? "enable" : "disable",
- data, callBack, cookie);
-}
-
-void CodaDevice::sendMemorySetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- quint64 start, const QByteArray& data,
- const QVariant &cookie)
-{
- QByteArray getData;
- JsonInputStream str(getData);
- // start/word size/mode. Mode should ideally be 1 (continue on error?)
- str << contextId << '\0' << start << '\0' << 1 << '\0' << data.size() << '\0' << 1
- << '\0' << data.toBase64();
- sendCodaMessage(MessageWithReply, MemoryService, "set", getData, callBack, cookie);
-}
-
-void CodaDevice::sendMemoryGetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- quint64 start, quint64 size,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- // start/word size/mode. Mode should ideally be 1 (continue on error?)
- str << contextId << '\0' << start << '\0' << 1 << '\0' << size << '\0' << 1;
- sendCodaMessage(MessageWithReply, MemoryService, "get", data, callBack, cookie);
-}
-
-QByteArray CodaDevice::parseMemoryGet(const CodaCommandResult &r)
-{
- if (r.type != CodaCommandResult::SuccessReply || r.values.size() < 1)
- return QByteArray();
- const JsonValue &memoryV = r.values.front();
-
- if (memoryV.type() != JsonValue::String || memoryV.data().size() < 2
- || !memoryV.data().endsWith('='))
- return QByteArray();
- // Catch errors reported as hash:
- // R.4."TlVMTA==".{"Time":1276786871255,"Code":1,"AltCode":-38,"AltOrg":"POSIX","Format":"BadDescriptor"}
- // Not sure what to make of it.
- if (r.values.size() >= 2 && r.values.at(1).type() == JsonValue::Object)
- qWarning("CodaDevice::parseMemoryGet(): Error retrieving memory: %s", r.values.at(1).toString(false).constData());
- // decode
- const QByteArray memory = QByteArray::fromBase64(memoryV.data());
- if (memory.isEmpty())
- qWarning("Base64 decoding of %s failed.", memoryV.data().constData());
- if (debug)
- qDebug("CodaDevice::parseMemoryGet: received %d bytes", memory.size());
- return memory;
-}
-
-// Parse register children (array of names)
-QVector<QByteArray> CodaDevice::parseRegisterGetChildren(const CodaCommandResult &r)
-{
- QVector<QByteArray> rc;
- if (!r || r.values.size() < 1 || r.values.front().type() != JsonValue::Array)
- return rc;
- const JsonValue &front = r.values.front();
- rc.reserve(front.childCount());
- foreach(const JsonValue &v, front.children())
- rc.push_back(v.data());
- return rc;
-}
-
-CodaStatResponse CodaDevice::parseStat(const CodaCommandResult &r)
-{
- CodaStatResponse rc;
- if (!r || r.values.size() < 1 || r.values.front().type() != JsonValue::Object)
- return rc;
- foreach(const JsonValue &v, r.values.front().children()) {
- if (v.name() == "Size") {
- rc.size = v.data().toULongLong();
- } else if (v.name() == "ATime") {
- if (const quint64 atime = v.data().toULongLong())
- rc.accessTime = CodaCommandResult::codaTimeToQDateTime(atime);
- } else if (v.name() == "MTime") {
- if (const quint64 mtime = v.data().toULongLong())
- rc.modTime = CodaCommandResult::codaTimeToQDateTime(mtime);
- }
- }
- return rc;
-}
-
-void CodaDevice::sendRegistersGetChildrenCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << contextId;
- sendCodaMessage(MessageWithReply, RegistersService, "getChildren", data, callBack, cookie);
-}
-
-// Format id of register get request (needs contextId containing process and thread)
-static inline QByteArray registerId(const QByteArray &contextId, QByteArray id)
-{
- QByteArray completeId = contextId;
- if (!completeId.isEmpty())
- completeId.append('.');
- completeId.append(id);
- return completeId;
-}
-
-// Format parameters of register get request
-static inline QByteArray registerGetData(const QByteArray &contextId, QByteArray id)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << registerId(contextId, id);
- return data;
-}
-
-void CodaDevice::sendRegistersGetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- QByteArray id,
- const QVariant &cookie)
-{
- sendCodaMessage(MessageWithReply, RegistersService, "get",
- registerGetData(contextId, id), callBack, cookie);
-}
-
-void CodaDevice::sendRegistersGetMCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- const QVector<QByteArray> &ids,
- const QVariant &cookie)
-{
- // Format the register ids as a JSON list
- QByteArray data;
- JsonInputStream str(data);
- str << '[';
- const int count = ids.size();
- for (int r = 0; r < count; r++) {
- if (r)
- str << ',';
- // TODO: When 8-byte floating-point registers are supported, query for register length based on register id
- str << '[' << registerId(contextId, ids.at(r)) << ',' << '0' << ',' << '4' << ']';
- }
- str << ']';
- sendCodaMessage(MessageWithReply, RegistersService, "getm", data, callBack, cookie);
-}
-
-void CodaDevice::sendRegistersGetMRangeCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- unsigned start, unsigned count)
-{
- const unsigned end = start + count;
- if (end > (unsigned)d->m_registerNames.size()) {
- qWarning("CodaDevice: No register name set for index %u (size: %d).", end, d->m_registerNames.size());
- return;
- }
-
- QVector<QByteArray> ids;
- ids.reserve(count);
- for (unsigned i = start; i < end; ++i)
- ids.push_back(d->m_registerNames.at(i));
- sendRegistersGetMCommand(callBack, contextId, ids, QVariant(start));
-}
-
-// Set register
-void CodaDevice::sendRegistersSetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- QByteArray id,
- const QByteArray &value,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- if (!contextId.isEmpty()) {
- id.prepend('.');
- id.prepend(contextId);
- }
- str << id << '\0' << value.toBase64();
- sendCodaMessage(MessageWithReply, RegistersService, "set", data, callBack, cookie);
-}
-
-// Set register
-void CodaDevice::sendRegistersSetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- unsigned registerNumber,
- const QByteArray &value,
- const QVariant &cookie)
-{
- if (registerNumber >= (unsigned)d->m_registerNames.size()) {
- qWarning("CodaDevice: No register name set for index %u (size: %d).", registerNumber, d->m_registerNames.size());
- return;
- }
- sendRegistersSetCommand(callBack, contextId,
- d->m_registerNames[registerNumber],
- value, cookie);
-}
-
-static const char outputListenerIDC[] = "ProgramOutputConsoleLogger";
-
-void CodaDevice::sendLoggingAddListenerCommand(const CodaCallback &callBack,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << outputListenerIDC;
- sendCodaMessage(MessageWithReply, LoggingService, "addListener", data, callBack, cookie);
-}
-
-void CodaDevice::sendSymbianUninstallCommand(const Coda::CodaCallback &callBack,
- const quint32 package,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- QString string = QString::number(package, 16);
- str << string;
- sendCodaMessage(MessageWithReply, SymbianInstallService, "uninstall", data, callBack, cookie);
-}
-
-void CodaDevice::sendSymbianOsDataGetThreadsCommand(const CodaCallback &callBack,
- const QVariant &cookie)
-{
- QByteArray data;
- sendCodaMessage(MessageWithReply, SymbianOSData, "getThreads", data, callBack, cookie);
-}
-
-void CodaDevice::sendSymbianOsDataFindProcessesCommand(const CodaCallback &callBack,
- const QByteArray &processName,
- const QByteArray &uid,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << processName << '\0' << uid;
- sendCodaMessage(MessageWithReply, SymbianOSData, "findRunningProcesses", data, callBack, cookie);
-}
-
-void CodaDevice::sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack,
- const QVariant &cookie)
-{
- sendCodaMessage(MessageWithReply, SymbianOSData, "getQtVersion", QByteArray(), callBack, cookie);
-}
-
-void CodaDevice::sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack,
- const QVariant &cookie)
-{
- sendCodaMessage(MessageWithReply, SymbianOSData, "getRomInfo", QByteArray(), callBack, cookie);
-}
-
-void CodaDevice::sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack,
- const QStringList &keys,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << '[';
- for (int i = 0; i < keys.count(); ++i) {
- if (i)
- str << ',';
- str << keys[i];
- }
- str << ']';
- sendCodaMessage(MessageWithReply, SymbianOSData, "getHalInfo", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendFileSystemOpenCommand(const Coda::CodaCallback &callBack,
- const QByteArray &name,
- unsigned flags,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << name << '\0' << flags << '\0' << '{' << '}';
- sendCodaMessage(MessageWithReply, FileSystemService, "open", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendFileSystemFstatCommand(const CodaCallback &callBack,
- const QByteArray &handle,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << handle;
- sendCodaMessage(MessageWithReply, FileSystemService, "fstat", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendFileSystemWriteCommand(const Coda::CodaCallback &callBack,
- const QByteArray &handle,
- const QByteArray &dataIn,
- unsigned offset,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << handle << '\0' << offset << '\0' << dataIn.toBase64();
- sendCodaMessage(MessageWithReply, FileSystemService, "write", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendFileSystemCloseCommand(const Coda::CodaCallback &callBack,
- const QByteArray &handle,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << handle;
- sendCodaMessage(MessageWithReply, FileSystemService, "close", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendSymbianInstallSilentInstallCommand(const Coda::CodaCallback &callBack,
- const QByteArray &file,
- const QByteArray &targetDrive,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << file << '\0' << targetDrive;
- sendCodaMessage(MessageWithReply, SymbianInstallService, "install", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendSymbianInstallUIInstallCommand(const Coda::CodaCallback &callBack,
- const QByteArray &file,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << file;
- sendCodaMessage(MessageWithReply, SymbianInstallService, "installWithUI", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack,
- const QList<quint32> &packages,
- const QVariant &cookie)
-{
- QByteArray data;
- JsonInputStream str(data);
- str << '[';
- for (int i = 0; i < packages.count(); ++i) {
- if (i)
- str << ',';
- QString pkgString;
- pkgString.setNum(packages[i], 16);
- str << pkgString;
- }
- str << ']';
- sendCodaMessage(MessageWithReply, SymbianInstallService, "getPackageInfo", data, callBack, cookie);
-}
-
-void Coda::CodaDevice::sendDebugSessionControlSessionStartCommand(const Coda::CodaCallback &callBack,
- const QVariant &cookie)
-{
- sendCodaMessage(MessageWithReply, DebugSessionControl, "sessionStart", QByteArray(), callBack, cookie);
-}
-
-void Coda::CodaDevice::sendDebugSessionControlSessionEndCommand(const Coda::CodaCallback &callBack,
- const QVariant &cookie)
-{
- sendCodaMessage(MessageWithReply, DebugSessionControl, "sessionEnd ", QByteArray(), callBack, cookie);
-}
-
-} // namespace Coda
diff --git a/src/shared/symbianutils/codadevice.h b/src/shared/symbianutils/codadevice.h
deleted file mode 100644
index 9a49cd527c..0000000000
--- a/src/shared/symbianutils/codadevice.h
+++ /dev/null
@@ -1,432 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef CODAENGINE_H
-#define CODAENGINE_H
-
-#include "symbianutils_global.h"
-#include "codamessage.h"
-#include "callback.h"
-#include "json.h"
-
-#include <QObject>
-#include <QSharedPointer>
-#include <QVector>
-#include <QVariant>
-#include <QStringList>
-#include <QDateTime>
-
-QT_BEGIN_NAMESPACE
-class QIODevice;
-class QTextStream;
-QT_END_NAMESPACE
-
-namespace Coda {
-
-struct CodaDevicePrivate;
-struct Breakpoint;
-
-/* Command error handling in CODA:
- * 1) 'Severe' errors (JSON format, parameter format): Coda emits a
- * nonstandard message (\3\2 error parameters) and closes the connection.
- * 2) Protocol errors: 'N' without error message is returned.
- * 3) Errors in command execution: 'R' with a CODA error hash is returned
- * (see CodaCommandError). */
-
-/* Error code return in 'R' reply to command
- * (see top of 'Services' documentation). */
-struct SYMBIANUTILS_EXPORT CodaCommandError {
- CodaCommandError();
- void clear();
- bool isError() const;
- operator bool() const { return isError(); }
- QString toString() const;
- void write(QTextStream &str) const;
- bool parse(const QVector<Json::JsonValue> &values);
-
- quint64 timeMS; // Since 1.1.1970
- qint64 code;
- QByteArray format; // message
- // 'Alternative' meaning, like altOrg="POSIX"/altCode=<some errno>
- QByteArray alternativeOrganization;
- qint64 alternativeCode;
-};
-
-/* Answer to a CODA command passed to the callback. */
-struct SYMBIANUTILS_EXPORT CodaCommandResult {
- enum Type
- {
- SuccessReply, // 'R' and no error -> all happy.
- CommandErrorReply, // 'R' with CodaCommandError received
- ProgressReply, // 'P', progress indicator
- FailReply // 'N' Protocol NAK, severe error
- };
-
- explicit CodaCommandResult(Type t = SuccessReply);
- explicit CodaCommandResult(char typeChar, Services service,
- const QByteArray &request,
- const QVector<Json::JsonValue> &values,
- const QVariant &cookie);
-
- QString toString() const;
- QString errorString() const;
- operator bool() const { return type == SuccessReply || type == ProgressReply; }
-
- static QDateTime codaTimeToQDateTime(quint64 codaTimeMS);
-
- Type type;
- Services service;
- QByteArray request;
- CodaCommandError commandError;
- QVector<Json::JsonValue> values;
- QVariant cookie;
-};
-
-// Response to stat/fstat
-struct SYMBIANUTILS_EXPORT CodaStatResponse
-{
- CodaStatResponse();
-
- quint64 size;
- QDateTime modTime;
- QDateTime accessTime;
-};
-
-typedef Coda::Callback<const CodaCommandResult &> CodaCallback;
-
-/* CodaDevice: CODA communication helper using an asynchronous QIODevice
- * implementing the CODA protocol according to:
-http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Specification.html
-http://dev.eclipse.org/svnroot/dsdp/org.eclipse.tm.tcf/trunk/docs/TCF%20Services.html
- * Commands can be sent along with callbacks that are passed a
- * CodaCommandResult and an opaque QVariant cookie. In addition, events are emitted.
- *
- * 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 CodaDevice : public QObject
-{
- Q_PROPERTY(unsigned verbose READ verbose WRITE setVerbose)
- Q_PROPERTY(bool serialFrame READ serialFrame WRITE setSerialFrame)
- Q_OBJECT
-public:
- // Flags for FileSystem:open
- enum FileSystemOpenFlags
- {
- FileSystem_TCF_O_READ = 0x00000001,
- FileSystem_TCF_O_WRITE = 0x00000002,
- FileSystem_TCF_O_APPEND = 0x00000004,
- FileSystem_TCF_O_CREAT = 0x00000008,
- FileSystem_TCF_O_TRUNC = 0x00000010,
- FileSystem_TCF_O_EXCL = 0x00000020
- };
-
- enum MessageType
- {
- MessageWithReply,
- MessageWithoutReply, /* Non-standard: "Settings:set" command does not reply */
- NoopMessage
- };
-
- typedef QSharedPointer<QIODevice> IODevicePtr;
-
- explicit CodaDevice(QObject *parent = 0);
- virtual ~CodaDevice();
-
- unsigned verbose() const;
- bool serialFrame() const;
- void setSerialFrame(bool);
-
- // Mapping of register names to indices for multi-requests.
- // Register names can be retrieved via 'Registers:getChildren' (requires
- // context id to be stripped).
- QVector<QByteArray> registerNames() const;
- void setRegisterNames(const QVector<QByteArray>& n);
-
- IODevicePtr device() const;
- IODevicePtr takeDevice();
- void setDevice(const IODevicePtr &dp);
-
- // Serial Only: Initiate communication. Will emit serialPong() signal with version.
- void sendSerialPing(bool pingOnly = false);
-
- // Send with parameters from string (which may contain '\0').
- void sendCodaMessage(MessageType mt, Services service, const char *command,
- const char *commandParameters, int commandParametersLength,
- const CodaCallback &callBack = CodaCallback(),
- const QVariant &cookie = QVariant());
-
- void sendCodaMessage(MessageType mt, Services service, const char *command,
- const QByteArray &commandParameters,
- const CodaCallback &callBack = CodaCallback(),
- const QVariant &cookie = QVariant());
-
- // Convenience messages: Start a process
- void sendProcessStartCommand(const CodaCallback &callBack,
- const QString &binary,
- unsigned uid,
- QStringList arguments = QStringList(),
- QString workingDirectory = QString(),
- bool debugControl = true,
- const QStringList &additionalLibraries = QStringList(),
- const QVariant &cookie = QVariant());
-
- // Just launch a process, don't attempt to attach the debugger to it
- void sendRunProcessCommand(const CodaCallback &callBack,
- const QString &processName,
- QStringList arguments = QStringList(),
- const QVariant &cookie = QVariant());
-
- // Preferred over Processes:Terminate by CODA.
- void sendRunControlTerminateCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie = QVariant());
-
- // TODO: In CODA 4.1.13 the Terminate option does order CODA to kill
- // a process and CODA reports contextRemoved but does not kill the process
- void sendProcessTerminateCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie = QVariant());
-
- // Non-standard: Remove executable from settings.
- // Probably needs to be called after stopping. This command has no response.
- void sendSettingsRemoveExecutableCommand(const QString &binaryIn,
- unsigned uid,
- const QStringList &additionalLibraries = QStringList(),
- const QVariant &cookie = QVariant());
-
- void sendRunControlSuspendCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie = QVariant());
-
- // Resume / Step (see RunControlResumeMode).
- void sendRunControlResumeCommand(const CodaCallback &callBack,
- const QByteArray &id,
- RunControlResumeMode mode,
- unsigned count /* = 1, currently ignored. */,
- quint64 rangeStart, quint64 rangeEnd,
- const QVariant &cookie = QVariant());
-
- // Convenience to resume a suspended process
- void sendRunControlResumeCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie = QVariant());
-
- void sendBreakpointsAddCommand(const CodaCallback &callBack,
- const Breakpoint &b,
- const QVariant &cookie = QVariant());
-
- void sendBreakpointsRemoveCommand(const CodaCallback &callBack,
- const QByteArray &id,
- const QVariant &cookie = QVariant());
-
- void sendBreakpointsRemoveCommand(const CodaCallback &callBack,
- const QVector<QByteArray> &id,
- const QVariant &cookie = QVariant());
-
- void sendBreakpointsEnableCommand(const CodaCallback &callBack,
- const QByteArray &id,
- bool enable,
- const QVariant &cookie = QVariant());
-
- void sendBreakpointsEnableCommand(const CodaCallback &callBack,
- const QVector<QByteArray> &id,
- bool enable,
- const QVariant &cookie = QVariant());
-
-
- void sendMemoryGetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- quint64 start, quint64 size,
- const QVariant &cookie = QVariant());
-
- void sendMemorySetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- quint64 start, const QByteArray& data,
- const QVariant &cookie = QVariant());
-
- // Get register names (children of context).
- // It is possible to recurse from thread id down to single registers.
- void sendRegistersGetChildrenCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- const QVariant &cookie = QVariant());
-
- // Register get
- void sendRegistersGetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- QByteArray id,
- const QVariant &cookie);
-
- void sendRegistersGetMCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- const QVector<QByteArray> &ids,
- const QVariant &cookie = QVariant());
-
- // Convenience to get a range of register "R0" .. "R<n>".
- // Cookie will be an int containing "start".
- void sendRegistersGetMRangeCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- unsigned start, unsigned count);
-
- // Set register
- void sendRegistersSetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- QByteArray ids,
- const QByteArray &value, // binary value
- const QVariant &cookie = QVariant());
- // Set register
- void sendRegistersSetCommand(const CodaCallback &callBack,
- const QByteArray &contextId,
- unsigned registerNumber,
- const QByteArray &value, // binary value
- const QVariant &cookie = QVariant());
-
- // File System
- void sendFileSystemOpenCommand(const CodaCallback &callBack,
- const QByteArray &name,
- unsigned flags = FileSystem_TCF_O_READ,
- const QVariant &cookie = QVariant());
-
- void sendFileSystemFstatCommand(const CodaCallback &callBack,
- const QByteArray &handle,
- const QVariant &cookie = QVariant());
-
- void sendFileSystemWriteCommand(const CodaCallback &callBack,
- const QByteArray &handle,
- const QByteArray &data,
- unsigned offset = 0,
- const QVariant &cookie = QVariant());
-
- void sendFileSystemCloseCommand(const CodaCallback &callBack,
- const QByteArray &handle,
- const QVariant &cookie = QVariant());
-
- // Symbian Install
- void sendSymbianInstallSilentInstallCommand(const CodaCallback &callBack,
- const QByteArray &file,
- const QByteArray &targetDrive,
- const QVariant &cookie = QVariant());
-
- void sendSymbianInstallUIInstallCommand(const CodaCallback &callBack,
- const QByteArray &file,
- const QVariant &cookie = QVariant());
-
- void sendSymbianInstallGetPackageInfoCommand(const Coda::CodaCallback &callBack,
- const QList<quint32> &packages,
- const QVariant &cookie = QVariant());
-
- void sendLoggingAddListenerCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- void sendSymbianUninstallCommand(const Coda::CodaCallback &callBack,
- const quint32 package,
- const QVariant &cookie = QVariant());
-
- // SymbianOs Data
- void sendSymbianOsDataGetThreadsCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- void sendSymbianOsDataFindProcessesCommand(const CodaCallback &callBack,
- const QByteArray &processName,
- const QByteArray &uid,
- const QVariant &cookie = QVariant());
-
- void sendSymbianOsDataGetQtVersionCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- void sendSymbianOsDataGetRomInfoCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- void sendSymbianOsDataGetHalInfoCommand(const CodaCallback &callBack,
- const QStringList &keys = QStringList(),
- const QVariant &cookie = QVariant());
-
- // DebugSessionControl
- void sendDebugSessionControlSessionStartCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- void sendDebugSessionControlSessionEndCommand(const CodaCallback &callBack,
- const QVariant &cookie = QVariant());
-
- // Settings
- void sendSettingsEnableLogCommand();
-
- void writeCustomData(char protocolId, const QByteArray &aData);
-
- static QByteArray parseMemoryGet(const CodaCommandResult &r);
- static QVector<QByteArray> parseRegisterGetChildren(const CodaCommandResult &r);
- static CodaStatResponse parseStat(const CodaCommandResult &r);
-
-signals:
- void genericCodaEvent(int service, const QByteArray &name, const QVector<Json::JsonValue> &value);
- void codaEvent(const Coda::CodaEvent &knownEvent);
- void unknownEvent(uchar protocolId, const QByteArray& data);
- void serialPong(const QString &codaVersion);
-
- void logMessage(const QString &);
- void error(const QString &);
-
-public slots:
- void setVerbose(unsigned v);
-
-private slots:
- void slotDeviceError();
- void slotDeviceSocketStateChanged();
- void slotDeviceReadyRead();
-
-private:
- void deviceReadyReadSerial();
- void deviceReadyReadTcp();
-
- bool checkOpen();
- void checkSendQueue();
- void writeMessage(QByteArray data, bool ensureTerminating0 = true);
- void emitLogMessage(const QString &);
- inline int parseMessage(const QByteArray &);
- void processMessage(const QByteArray &message);
- inline void processSerialMessage(const QByteArray &message);
- int parseCodaCommandReply(char type, const QVector<QByteArray> &tokens);
- int parseCodaEvent(const QVector<QByteArray> &tokens);
-
-private:
- QPair<int, int> findSerialHeader(QByteArray &in);
- CodaDevicePrivate *d;
-};
-
-} // namespace Coda
-
-#endif // CODAENGINE_H
diff --git a/src/shared/symbianutils/codamessage.cpp b/src/shared/symbianutils/codamessage.cpp
deleted file mode 100644
index e680eb5ed8..0000000000
--- a/src/shared/symbianutils/codamessage.cpp
+++ /dev/null
@@ -1,592 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "codamessage.h"
-#include "json.h"
-
-#include <QString>
-#include <QTextStream>
-
-// Names matching the enum
-static const char *serviceNamesC[] =
-{ "Locator", "RunControl", "Processes", "Memory", "Settings", "Breakpoints",
- "Registers", "Logging", "FileSystem", "SymbianInstall", "SymbianOSData",
- "DebugSessionControl",
- "UnknownService"};
-
-using namespace Json;
-namespace Coda {
-
-SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep)
-{
- QString rc;
- const int count = a.size();
- for (int i = 0; i < count; i++) {
- if (i)
- rc += QLatin1Char(sep);
- rc += QString::fromUtf8(a.at(i));
- }
- return rc;
-}
-
-static inline bool jsonToBool(const JsonValue& js)
-{
- return js.type() == JsonValue::Boolean && js.data() == "true";
-}
-
-SYMBIANUTILS_EXPORT const char *serviceName(Services s)
-{
- return serviceNamesC[s];
-}
-
-SYMBIANUTILS_EXPORT Services serviceFromName(const char *n)
-{
- const int count = sizeof(serviceNamesC)/sizeof(char *);
- for (int i = 0; i < count; i++)
- if (!qstrcmp(serviceNamesC[i], n))
- return static_cast<Services>(i);
- return UnknownService;
-}
-
-SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a)
-{
- const int columns = 16;
- QString rc;
- QTextStream str(&rc);
- str.setIntegerBase(16);
- str.setPadChar(QLatin1Char('0'));
- const unsigned char *start = reinterpret_cast<const unsigned char *>(a.constData());
- const unsigned char *end = start + a.size();
- for (const unsigned char *p = start; p < end ; ) {
- str << "0x";
- str.setFieldWidth(4);
- str << (p - start);
- str.setFieldWidth(0);
- str << ' ';
- QString asc;
- int c = 0;
- for ( ; c < columns && p < end; c++, p++) {
- const unsigned u = *p;
- str.setFieldWidth(2);
- str << u;
- str.setFieldWidth(0);
- str << ' ';
- switch (u) {
- case '\n':
- asc += QLatin1String("\\n");
- break;
- case '\r':
- asc += QLatin1String("\\r");
- break;
- case '\t':
- asc += QLatin1String("\\t");
- break;
- default:
- if (u >= 32 && u < 128) {
- asc += QLatin1Char(' ');
- asc += QLatin1Char(u);
- } else {
- asc += QLatin1String(" .");
- }
- break;
- }
- }
- if (const int remainder = columns - c)
- str << QString(3 * remainder, QLatin1Char(' '));
- str << ' ' << asc << '\n';
- }
- return rc;
-}
-
-// ----------- RunControlContext
-RunControlContext::RunControlContext() :
- flags(0), resumeFlags(0)
-{
-}
-
-void RunControlContext::clear()
-{
- flags =0;
- resumeFlags = 0;
- id.clear();
- osid.clear();
- parentId.clear();
-}
-
-RunControlContext::Type RunControlContext::typeFromCodaId(const QByteArray &id)
-{
- // "p12" or "p12.t34"?
- return id.contains(".t") ? Thread : Process;
-}
-
-unsigned RunControlContext::processId() const
-{
- return processIdFromTcdfId(id);
-}
-
-unsigned RunControlContext::threadId() const
-{
- return threadIdFromTcdfId(id);
-}
-
-unsigned RunControlContext::processIdFromTcdfId(const QByteArray &id)
-{
- // Cut out process id from "p12" or "p12.t34"?
- if (!id.startsWith('p'))
- return 0;
- const int dotPos = id.indexOf('.');
- const int pLen = dotPos == -1 ? id.size() : dotPos;
- return id.mid(1, pLen - 1).toUInt();
-}
-
-unsigned RunControlContext::threadIdFromTcdfId(const QByteArray &id)
-{
- const int tPos = id.indexOf(".t");
- return tPos != -1 ? id.mid(tPos + 2).toUInt() : uint(0);
-}
-
-QByteArray RunControlContext::codaId(unsigned processId, unsigned threadId /* = 0 */)
-{
- QByteArray rc("p");
- rc += QByteArray::number(processId);
- if (threadId) {
- rc += ".t";
- rc += QByteArray::number(threadId);
- }
- return rc;
-}
-
-RunControlContext::Type RunControlContext::type() const
-{
- return RunControlContext::typeFromCodaId(id);
-}
-
-bool RunControlContext::parse(const JsonValue &val)
-{
- clear();
- if (val.type() != JsonValue::Object)
- return false;
- foreach(const JsonValue &c, val.children()) {
- if (c.name() == "ID") {
- id = c.data();
- } else if (c.name() == "OSID") {
- osid = c.data();
- } else if (c.name() == "ParentID") {
- parentId = c.data();
- } else if (c.name() == "IsContainer") {
- if (jsonToBool(c))
- flags |= Container;
- } else if (c.name() == "CanTerminate") {
- if (jsonToBool(c))
- flags |= CanTerminate;
- } else if (c.name() == "CanResume") {
- resumeFlags = c.data().toUInt();
- } else if (c.name() == "HasState") {
- if (jsonToBool(c))
- flags |= HasState;
- } else if (c.name() == "CanSuspend") {
- if (jsonToBool(c))
- flags |= CanSuspend;
- }
- }
- return true;
-}
-
-QString RunControlContext::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- format(str);
- return rc;
-}
-
-void RunControlContext::format(QTextStream &str) const
-{
- str << " id='" << id << "' osid='" << osid
- << "' parentId='" << parentId <<"' ";
- if (flags & Container)
- str << "[container] ";
- if (flags & HasState)
- str << "[has state] ";
- if (flags & CanSuspend)
- str << "[can suspend] ";
- if (flags & CanSuspend)
- str << "[can terminate] ";
- str.setIntegerBase(16);
- str << " resume_flags: 0x" << resumeFlags;
- str.setIntegerBase(10);
-}
-
-// ------ ModuleLoadEventInfo
-ModuleLoadEventInfo::ModuleLoadEventInfo() :
- loaded(false), codeAddress(0), dataAddress(0), requireResume(false)
-{
-}
-
-void ModuleLoadEventInfo::clear()
-{
- loaded = requireResume = false;
- codeAddress = dataAddress =0;
-}
-
-bool ModuleLoadEventInfo::parse(const JsonValue &val)
-{
- clear();
- if (val.type() != JsonValue::Object)
- return false;
- foreach(const JsonValue &c, val.children()) {
- if (c.name() == "Name") {
- name = c.data();
- } else if (c.name() == "File") {
- file = c.data();
- } else if (c.name() == "CodeAddress") {
- codeAddress = c.data().toULongLong();
- } else if (c.name() == "DataAddress") {
- dataAddress = c.data().toULongLong();
- } else if (c.name() == "Loaded") {
- loaded = jsonToBool(c);
- } else if (c.name() == "RequireResume") {
- requireResume =jsonToBool(c);
- }
- }
- return true;
-}
-void ModuleLoadEventInfo::format(QTextStream &str) const
-{
- str << "name='" << name << "' file='" << file << "' " <<
- (loaded ? "[loaded] " : "[not loaded] ");
- if (requireResume)
- str << "[requires resume] ";
- str.setIntegerBase(16);
- str << " code: 0x" << codeAddress << " data: 0x" << dataAddress;
- str.setIntegerBase(10);
-}
-
-// ---------------------- Breakpoint
-
-// Types matching enum
-static const char *breakPointTypesC[] = {"Software", "Hardware", "Auto"};
-
-Breakpoint::Breakpoint(quint64 loc) :
- type(Auto), enabled(true), ignoreCount(0), location(loc), size(1), thumb(true)
-{
- if (loc)
- id = idFromLocation(location);
-}
-
-void Breakpoint::setContextId(unsigned processId, unsigned threadId)
-{
- contextIds = QVector<QByteArray>(1, RunControlContext::codaId(processId, threadId));
-}
-
-QByteArray Breakpoint::idFromLocation(quint64 loc)
-{
- return QByteArray("BP_0x") + QByteArray::number(loc, 16);
-}
-
-QString Breakpoint::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- str.setIntegerBase(16);
- str << "Breakpoint '" << id << "' " << breakPointTypesC[type] << " for contexts '"
- << joinByteArrays(contextIds, ',') << "' at 0x" << location;
- str.setIntegerBase(10);
- str << " size " << size;
- if (enabled)
- str << " [enabled]";
- if (thumb)
- str << " [thumb]";
- if (ignoreCount)
- str << " IgnoreCount " << ignoreCount;
- return rc;
-}
-
-JsonInputStream &operator<<(JsonInputStream &str, const Breakpoint &b)
-{
- if (b.contextIds.isEmpty())
- qWarning("Coda::Breakpoint: No context ids specified");
-
- str << '{' << "ID" << ':' << QString::fromUtf8(b.id) << ','
- << "BreakpointType" << ':' << breakPointTypesC[b.type] << ','
- << "Enabled" << ':' << b.enabled << ','
- << "IgnoreCount" << ':' << b.ignoreCount << ','
- << "ContextIds" << ':' << b.contextIds << ','
- << "Location" << ':' << QString::number(b.location) << ','
- << "Size" << ':' << b.size << ','
- << "THUMB_BREAKPOINT" << ':' << b.thumb
- << '}';
- return str;
-}
-
-// --- Events
-CodaEvent::CodaEvent(Type type) : m_type(type)
-{
-}
-
-CodaEvent::~CodaEvent()
-{
-}
-
-CodaEvent::Type CodaEvent::type() const
-{
- return m_type;
-}
-
-QString CodaEvent::toString() const
-{
- return QString();
-}
-
-static const char sharedLibrarySuspendReasonC[] = "Shared Library";
-
-CodaEvent *CodaEvent::parseEvent(Services s, const QByteArray &nameBA, const QVector<JsonValue> &values)
-{
- switch (s) {
- case LocatorService:
- if (nameBA == "Hello" && values.size() == 1 && values.front().type() == JsonValue::Array) {
- QStringList services;
- foreach (const JsonValue &jv, values.front().children())
- services.push_back(QString::fromUtf8(jv.data()));
- return new CodaLocatorHelloEvent(services);
- }
- break;
- case RunControlService:
- if (values.empty())
- return 0;
- // "id/PC/Reason/Data"
- if (nameBA == "contextSuspended" && values.size() == 4) {
- const QByteArray idBA = values.at(0).data();
- const quint64 pc = values.at(1).data().toULongLong();
- const QByteArray reasonBA = values.at(2).data();
- QByteArray messageBA;
- // Module load: Special
- if (reasonBA == sharedLibrarySuspendReasonC) {
- ModuleLoadEventInfo info;
- if (!info.parse(values.at(3)))
- return 0;
- return new CodaRunControlModuleLoadContextSuspendedEvent(idBA, reasonBA, pc, info);
- } else {
- // hash containing a 'message'-key with a verbose crash message.
- if (values.at(3).type() == JsonValue::Object && values.at(3).childCount()
- && values.at(3).children().at(0).type() == JsonValue::String)
- messageBA = values.at(3).children().at(0).data();
- }
- return new CodaRunControlContextSuspendedEvent(idBA, reasonBA, messageBA, pc);
- } // "contextSuspended"
- if (nameBA == "contextAdded")
- return CodaRunControlContextAddedEvent::parseEvent(values);
- if (nameBA == "contextRemoved" && values.front().type() == JsonValue::Array) {
- QVector<QByteArray> ids;
- foreach(const JsonValue &c, values.front().children())
- ids.push_back(c.data());
- return new CodaRunControlContextRemovedEvent(ids);
- }
- break;
- case LoggingService:
- if ((nameBA == "writeln" || nameBA == "write" /*not yet used*/) && values.size() >= 2)
- return new CodaLoggingWriteEvent(values.at(0).data(), values.at(1).data());
- break;
- case ProcessesService:
- if (nameBA == "exited" && values.size() >= 2)
- return new CodaProcessExitedEvent(values.at(0).data());
- break;
- default:
- break;
- }
- return 0;
-}
-
-// -------------- CodaServiceHelloEvent
-CodaLocatorHelloEvent::CodaLocatorHelloEvent(const QStringList &s) :
- CodaEvent(LocatorHello),
- m_services(s)
-{
-}
-
-QString CodaLocatorHelloEvent::toString() const
-{
- return QLatin1String("ServiceHello: ") + m_services.join(QLatin1String(", "));
-}
-
-// -------------- Logging event
-
-CodaLoggingWriteEvent::CodaLoggingWriteEvent(const QByteArray &console, const QByteArray &message) :
- CodaEvent(LoggingWriteEvent), m_console(console), m_message(message)
-{
-}
-
-QString CodaLoggingWriteEvent::toString() const
-{
- return QString::fromUtf8(m_message);
-}
-
-// -------------- CodaIdEvent
-CodaIdEvent::CodaIdEvent(Type t, const QByteArray &id) :
- CodaEvent(t), m_id(id)
-{
-}
-
-// ---------- CodaIdsEvent
-CodaIdsEvent::CodaIdsEvent(Type t, const QVector<QByteArray> &ids) :
- CodaEvent(t), m_ids(ids)
-{
-}
-
-QString CodaIdsEvent::joinedIdString(const char sep) const
-{
- return joinByteArrays(m_ids, sep);
-}
-
-// ---------------- CodaRunControlContextAddedEvent
-CodaRunControlContextAddedEvent::CodaRunControlContextAddedEvent(const RunControlContexts &c) :
- CodaEvent(RunControlContextAdded), m_contexts(c)
-{
-}
-
-CodaRunControlContextAddedEvent
- *CodaRunControlContextAddedEvent::parseEvent(const QVector<JsonValue> &values)
-{
- // Parse array of contexts
- if (values.size() < 1 || values.front().type() != JsonValue::Array)
- return 0;
-
- RunControlContexts contexts;
- foreach (const JsonValue &v, values.front().children()) {
- RunControlContext context;
- if (context.parse(v))
- contexts.push_back(context);
- }
- return new CodaRunControlContextAddedEvent(contexts);
-}
-
-QString CodaRunControlContextAddedEvent::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- str << "RunControl: " << m_contexts.size() << " context(s) "
- << (type() == RunControlContextAdded ? "added" : "removed")
- << '\n';
- foreach (const RunControlContext &c, m_contexts) {
- c.format(str);
- str << '\n';
- }
- return rc;
-}
-
-// --------------- CodaRunControlContextRemovedEvent
-CodaRunControlContextRemovedEvent::CodaRunControlContextRemovedEvent(const QVector<QByteArray> &ids) :
- CodaIdsEvent(RunControlContextRemoved, ids)
-{
-}
-
-QString CodaRunControlContextRemovedEvent::toString() const
-{
- return QLatin1String("RunControl: Removed contexts '") + joinedIdString() + ("'.");
-}
-
-// --------------- CodaRunControlContextSuspendedEvent
-CodaRunControlContextSuspendedEvent::CodaRunControlContextSuspendedEvent(const QByteArray &id,
- const QByteArray &reason,
- const QByteArray &message,
- quint64 pc) :
- CodaIdEvent(RunControlSuspended, id), m_pc(pc), m_reason(reason), m_message(message)
-{
-}
-
-CodaRunControlContextSuspendedEvent::CodaRunControlContextSuspendedEvent(Type t,
- const QByteArray &id,
- const QByteArray &reason,
- quint64 pc) :
- CodaIdEvent(t, id), m_pc(pc), m_reason(reason)
-{
-}
-
-void CodaRunControlContextSuspendedEvent::format(QTextStream &str) const
-{
- str.setIntegerBase(16);
- str << "RunControl: '" << idString() << "' suspended at 0x"
- << m_pc << ": '" << m_reason << "'.";
- str.setIntegerBase(10);
- if (!m_message.isEmpty())
- str << " (" <<m_message << ')';
-}
-
-QString CodaRunControlContextSuspendedEvent::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- format(str);
- return rc;
-}
-
-CodaRunControlContextSuspendedEvent::Reason CodaRunControlContextSuspendedEvent::reason() const
-{
- if (m_reason == sharedLibrarySuspendReasonC)
- return ModuleLoad;
- if (m_reason == "Breakpoint")
- return BreakPoint;
- // 'Data abort exception'/'Thread has panicked' ... unfortunately somewhat unspecific.
- if (m_reason.contains("Exception") || m_reason.contains("panick"))
- return Crash;
- return Other;
-}
-
-CodaRunControlModuleLoadContextSuspendedEvent::CodaRunControlModuleLoadContextSuspendedEvent(const QByteArray &id,
- const QByteArray &reason,
- quint64 pc,
- const ModuleLoadEventInfo &mi) :
- CodaRunControlContextSuspendedEvent(RunControlModuleLoadSuspended, id, reason, pc),
- m_mi(mi)
-{
-}
-
-QString CodaRunControlModuleLoadContextSuspendedEvent::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- CodaRunControlContextSuspendedEvent::format(str);
- str << ' ';
- m_mi.format(str);
- return rc;
-}
-
-// -------------- CodaIdEvent
-CodaProcessExitedEvent::CodaProcessExitedEvent(const QByteArray &id) :
- CodaEvent(ProcessExitedEvent), m_id(id)
-{
-}
-
-QString CodaProcessExitedEvent::toString() const
-{
- return QString("Process \"%1\" exited").arg(idString());
-}
-
-} // namespace Coda
diff --git a/src/shared/symbianutils/codamessage.h b/src/shared/symbianutils/codamessage.h
deleted file mode 100644
index 27a106c239..0000000000
--- a/src/shared/symbianutils/codamessage.h
+++ /dev/null
@@ -1,327 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef CODAMESSAGE_H
-#define CODAMESSAGE_H
-
-#include "symbianutils_global.h"
-#include "json_global.h"
-
-#include <QStringList>
-#include <QVector>
-
-QT_BEGIN_NAMESPACE
-class QTextStream;
-QT_END_NAMESPACE
-
-namespace Json {
-class JsonValue;
-class JsonInputStream;
-}
-
-namespace Coda {
-
-enum Services {
- LocatorService,
- RunControlService,
- ProcessesService,
- MemoryService,
- SettingsService, // non-standard, CODA specific
- BreakpointsService,
- RegistersService,
- LoggingService, // non-standard, CODA specific
- FileSystemService,
- SymbianInstallService, // non-standard, CODA specific
- SymbianOSData, // non-standard, CODA specific
- DebugSessionControl, // non-standard, CODA specific
- UnknownService
-}; // Note: Check string array 'serviceNamesC' of same size when modifying this.
-
-// Modes of RunControl/'Resume' (see EDF documentation).
-// As of 24.6.2010, RM_RESUME, RM_STEP_OVER, RM_STEP_INTO,
-// RM_STEP_OVER_RANGE, RM_STEP_INTO_RANGE are supported with
-// RANG_START/RANGE_END parameters.
-enum RunControlResumeMode {
- RM_RESUME = 0,
- RM_STEP_OVER = 1, RM_STEP_INTO = 2,
- RM_STEP_OVER_LINE = 3, RM_STEP_INTO_LINE = 4,
- RM_STEP_OUT = 5, RM_REVERSE_RESUME = 6,
- RM_REVERSE_STEP_OVER = 7, RM_REVERSE_STEP_INTO = 8,
- RM_REVERSE_STEP_OVER_LINE = 9, RM_REVERSE_STEP_INTO_LINE = 10,
- RM_REVERSE_STEP_OUT = 11, RM_STEP_OVER_RANGE = 12,
- RM_STEP_INTO_RANGE = 13, RM_REVERSE_STEP_OVER_RANGE = 14,
- RM_REVERSE_STEP_INTO_RANGE = 15
-};
-
-SYMBIANUTILS_EXPORT const char *serviceName(Services s);
-SYMBIANUTILS_EXPORT Services serviceFromName(const char *);
-
-// Debug helpers
-SYMBIANUTILS_EXPORT QString formatData(const QByteArray &a);
-SYMBIANUTILS_EXPORT QString joinByteArrays(const QVector<QByteArray> &a, char sep = ',');
-
-// Context used in 'RunControl contextAdded' events and in reply
-// to 'Processes start'. Could be thread or process.
-struct SYMBIANUTILS_EXPORT RunControlContext {
- enum Flags {
- Container = 0x1, HasState = 0x2, CanSuspend = 0x4,
- CanTerminate = 0x8
- };
- enum Type { Process, Thread };
-
- RunControlContext();
- Type type() const;
- unsigned processId() const;
- unsigned threadId() const;
-
- void clear();
- bool parse(const Json::JsonValue &v);
- void format(QTextStream &str) const;
- QString toString() const;
-
- // Helper for converting the CODA ids ("p12" or "p12.t34")
- static Type typeFromCodaId(const QByteArray &id);
- static unsigned processIdFromTcdfId(const QByteArray &id);
- static unsigned threadIdFromTcdfId(const QByteArray &id);
- static QByteArray codaId(unsigned processId, unsigned threadId = 0);
-
- unsigned flags;
- unsigned resumeFlags;
- QByteArray id; // "p434.t699"
- QByteArray osid; // Non-standard: Process or thread id
- QByteArray parentId; // Parent process id of a thread.
-};
-
-// Module load information occurring with 'RunControl contextSuspended' events
-struct SYMBIANUTILS_EXPORT ModuleLoadEventInfo {
- ModuleLoadEventInfo();
- void clear();
- bool parse(const Json::JsonValue &v);
- void format(QTextStream &str) const;
-
- QByteArray name;
- QByteArray file;
- bool loaded;
- quint64 codeAddress;
- quint64 dataAddress;
- bool requireResume;
-};
-
-// Breakpoint as supported by Coda source June 2010
-// TODO: Add watchpoints,etc once they are implemented
-struct SYMBIANUTILS_EXPORT Breakpoint {
- enum Type { Software, Hardware, Auto };
-
- explicit Breakpoint(quint64 loc = 0);
- void setContextId(unsigned processId, unsigned threadId = 0);
- QString toString() const;
-
- static QByteArray idFromLocation(quint64 loc); // Automagically determine from location
-
- Type type;
- bool enabled;
- int ignoreCount;
- QVector<QByteArray> contextIds; // Process or thread ids.
- QByteArray id; // Id of the breakpoint;
- quint64 location;
- unsigned size;
- bool thumb;
-};
-
-Json::JsonInputStream &operator<<(Json::JsonInputStream &str, const Breakpoint &b);
-
-// Event hierarchy
-class SYMBIANUTILS_EXPORT CodaEvent
-{
- Q_DISABLE_COPY(CodaEvent)
-
-public:
- enum Type { None,
- LocatorHello,
- RunControlContextAdded,
- RunControlContextRemoved,
- RunControlSuspended,
- RunControlBreakpointSuspended,
- RunControlModuleLoadSuspended,
- RunControlResumed,
- LoggingWriteEvent, // Non-standard
- ProcessExitedEvent // Non-standard
- };
-
- virtual ~CodaEvent();
-
- Type type() const;
- virtual QString toString() const;
-
- static CodaEvent *parseEvent(Services s, const QByteArray &name, const QVector<Json::JsonValue> &val);
-
-protected:
- explicit CodaEvent(Type type = None);
-
-private:
- const Type m_type;
-};
-
-// ServiceHello
-class SYMBIANUTILS_EXPORT CodaLocatorHelloEvent : public CodaEvent {
-public:
- explicit CodaLocatorHelloEvent(const QStringList &);
-
- const QStringList &services() const { return m_services; }
- virtual QString toString() const;
-
-private:
- QStringList m_services;
-};
-
-// Logging event (non-standard, CODA specific)
-class SYMBIANUTILS_EXPORT CodaLoggingWriteEvent : public CodaEvent {
-public:
- explicit CodaLoggingWriteEvent(const QByteArray &console, const QByteArray &message);
-
- QByteArray message() const { return m_message; }
- QByteArray console() const { return m_console; }
-
- virtual QString toString() const;
-
-private:
- const QByteArray m_console;
- const QByteArray m_message;
-};
-
-// Base for events that just have one id as parameter
-// (simple suspend)
-class SYMBIANUTILS_EXPORT CodaIdEvent : public CodaEvent {
-protected:
- explicit CodaIdEvent(Type t, const QByteArray &id);
-public:
- QByteArray id() const { return m_id; }
- QString idString() const { return QString::fromUtf8(m_id); }
-
-private:
- const QByteArray m_id;
-};
-
-// Base for events that just have some ids as parameter
-// (context removed)
-class SYMBIANUTILS_EXPORT CodaIdsEvent : public CodaEvent {
-protected:
- explicit CodaIdsEvent(Type t, const QVector<QByteArray> &ids);
-
-public:
- QVector<QByteArray> ids() const { return m_ids; }
- QString joinedIdString(const char sep = ',') const;
-
-private:
- const QVector<QByteArray> m_ids;
-};
-
-// RunControlContextAdded
-class SYMBIANUTILS_EXPORT CodaRunControlContextAddedEvent : public CodaEvent {
-public:
- typedef QVector<RunControlContext> RunControlContexts;
-
- explicit CodaRunControlContextAddedEvent(const RunControlContexts &c);
-
- const RunControlContexts &contexts() const { return m_contexts; }
- virtual QString toString() const;
-
- static CodaRunControlContextAddedEvent *parseEvent(const QVector<Json::JsonValue> &val);
-
-private:
- const RunControlContexts m_contexts;
-};
-
-// RunControlContextRemoved
-class SYMBIANUTILS_EXPORT CodaRunControlContextRemovedEvent : public CodaIdsEvent {
-public:
- explicit CodaRunControlContextRemovedEvent(const QVector<QByteArray> &id);
- virtual QString toString() const;
-};
-
-// Simple RunControlContextSuspended (process/thread)
-class SYMBIANUTILS_EXPORT CodaRunControlContextSuspendedEvent : public CodaIdEvent {
-public:
- enum Reason { BreakPoint, ModuleLoad, Crash, Other } ;
-
- explicit CodaRunControlContextSuspendedEvent(const QByteArray &id,
- const QByteArray &reason,
- const QByteArray &message,
- quint64 pc = 0);
- virtual QString toString() const;
-
- quint64 pc() const { return m_pc; }
- QByteArray reasonID() const { return m_reason; }
- Reason reason() const;
- QByteArray message() const { return m_message; }
-
-protected:
- explicit CodaRunControlContextSuspendedEvent(Type t,
- const QByteArray &id,
- const QByteArray &reason,
- quint64 pc = 0);
- void format(QTextStream &str) const;
-
-private:
- const quint64 m_pc;
- const QByteArray m_reason;
- const QByteArray m_message;
-};
-
-// RunControlContextSuspended due to module load
-class SYMBIANUTILS_EXPORT CodaRunControlModuleLoadContextSuspendedEvent : public CodaRunControlContextSuspendedEvent {
-public:
- explicit CodaRunControlModuleLoadContextSuspendedEvent(const QByteArray &id,
- const QByteArray &reason,
- quint64 pc,
- const ModuleLoadEventInfo &mi);
-
- virtual QString toString() const;
- const ModuleLoadEventInfo &info() const { return m_mi; }
-
-private:
- const ModuleLoadEventInfo m_mi;
-};
-
-// Process exited event
-class SYMBIANUTILS_EXPORT CodaProcessExitedEvent : public CodaEvent {
-public:
- explicit CodaProcessExitedEvent(const QByteArray &id);
-
- QByteArray id() const { return m_id; }
- QString idString() const { return QString::fromUtf8(m_id); }
- virtual QString toString() const;
-
-private:
- const QByteArray m_id;
-};
-
-} // namespace Coda
-#endif // CODAMESSAGE_H
diff --git a/src/shared/symbianutils/codautils.cpp b/src/shared/symbianutils/codautils.cpp
deleted file mode 100644
index b8588542ea..0000000000
--- a/src/shared/symbianutils/codautils.cpp
+++ /dev/null
@@ -1,591 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "codautils.h"
-#include <ctype.h>
-
-#include <QCoreApplication>
-#include <QDebug>
-#include <QDate>
-#include <QDateTime>
-#include <QTime>
-
-#define logMessage(s) do { qDebug() << "CODACLIENT: " << s; } while (0)
-
-namespace Coda {
-
-Library::Library() : codeseg(0), dataseg(0), pid(0)
-{
-}
-
-Library::Library(const CodaResult &result) : codeseg(0), dataseg(0), pid(0)
-{
- if (result.data.size() < 20) {
- qWarning("Invalid CODA creation notification received.");
- return;
- }
-
- const char *data = result.data.constData();
- pid = extractInt(data + 2);
- codeseg = extractInt(data + 10);
- dataseg = extractInt(data + 14);
- const uint len = extractShort(data + 18);
- name = result.data.mid(20, len);
-}
-
-CodaAppVersion::CodaAppVersion()
-{
- reset();
-}
-
-void CodaAppVersion::reset()
-{
- codaMajor = codaMinor = protocolMajor = protocolMinor = 0;
-}
-
-Session::Session()
-{
- reset();
-}
-
-void Session::reset()
-{
- cpuMajor = 0;
- cpuMinor = 0;
- bigEndian = 0;
- defaultTypeSize = 0;
- fpTypeSize = 0;
- extended1TypeSize = 0;
- extended2TypeSize = 0;
- pid = 0;
- mainTid = 0;
- tid = 0;
- codeseg = 0;
- dataseg = 0;
-
- libraries.clear();
- codaAppVersion.reset();
-}
-
-static QString formatCpu(int major, int minor)
-{
- //: CPU description of an S60 device
- //: %1 major verison, %2 minor version
- //: %3 real name of major verison, %4 real name of minor version
- const QString str = QCoreApplication::translate("Coda::Session", "CPU: v%1.%2%3%4");
- QString majorStr;
- QString minorStr;
- switch (major) {
- case 0x04:
- majorStr = " ARM";
- break;
- }
- switch (minor) {
- case 0x00:
- minorStr = " 920T";
- break;
- }
- return str.arg(major).arg(minor).arg(majorStr).arg(minorStr);
- }
-
-QString formatCodaVersion(const CodaAppVersion &version)
-{
- QString str = QCoreApplication::translate("Coda::Session",
- "CODA: v%1.%2 CODA protocol: v%3.%4");
- str = str.arg(version.codaMajor).arg(version.codaMinor);
- return str.arg(version.protocolMajor).arg(version.protocolMinor);
-}
-
-QString Session::deviceDescription(unsigned verbose) const
-{
- if (!cpuMajor)
- return QString();
-
- //: s60description
- //: description of an S60 device
- //: %1 CPU description, %2 endianness
- //: %3 default type size (if any), %4 float size (if any)
- //: %5 Coda version
- QString msg = QCoreApplication::translate("Coda::Session", "%1, %2%3%4, %5");
- QString endianness = bigEndian
- ? QCoreApplication::translate("Coda::Session", "big endian")
- : QCoreApplication::translate("Coda::Session", "little endian");
- msg = msg.arg(formatCpu(cpuMajor, cpuMinor)).arg(endianness);
- QString defaultTypeSizeStr;
- QString fpTypeSizeStr;
- if (verbose && defaultTypeSize)
- //: will be inserted into s60description
- defaultTypeSizeStr = QCoreApplication::translate("Coda::Session", ", type size: %1").arg(defaultTypeSize);
- if (verbose && fpTypeSize)
- //: will be inserted into s60description
- fpTypeSizeStr = QCoreApplication::translate("Coda::Session", ", float size: %1").arg(fpTypeSize);
- msg = msg.arg(defaultTypeSizeStr).arg(fpTypeSizeStr);
- return msg.arg(formatCodaVersion(codaAppVersion));
-}
-
-QByteArray Session::gdbLibraryList() const
-{
- const int count = libraries.size();
- QByteArray response = "l<library-list>";
- for (int i = 0; i != count; ++i) {
- const Coda::Library &lib = libraries.at(i);
- response += "<library name=\"";
- response += lib.name;
- response += "\">";
- response += "<section address=\"0x";
- response += Coda::hexNumber(lib.codeseg);
- response += "\"/>";
- response += "<section address=\"0x";
- response += Coda::hexNumber(lib.dataseg);
- response += "\"/>";
- response += "<section address=\"0x";
- response += Coda::hexNumber(lib.dataseg);
- response += "\"/>";
- response += "</library>";
- }
- response += "</library-list>";
- return response;
-}
-
-QByteArray Session::gdbQsDllInfo(int start, int count) const
-{
- // Happens with gdb 6.4.50.20060226-cvs / CodeSourcery.
- // Never made it into FSF gdb that got qXfer:libraries:read instead.
- // http://sourceware.org/ml/gdb/2007-05/msg00038.html
- // Name=hexname,TextSeg=textaddr[,DataSeg=dataaddr]
- const int libraryCount = libraries.size();
- const int end = count < 0 ? libraryCount : qMin(libraryCount, start + count);
- QByteArray response(1, end == libraryCount ? 'l' : 'm');
- for (int i = start; i < end; ++i) {
- if (i != start)
- response += ';';
- const Library &lib = libraries.at(i);
- response += "Name=";
- response += lib.name.toHex();
- response += ",TextSeg=";
- response += hexNumber(lib.codeseg);
- response += ",DataSeg=";
- response += hexNumber(lib.dataseg);
- }
- return response;
-}
-
-QString Session::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- str << "Session: " << deviceDescription(false) << '\n'
- << "pid: " << pid << "main thread: " << mainTid
- << " current thread: " << tid << ' ';
- str.setIntegerBase(16);
- str << " code: 0x" << codeseg << " data: 0x" << dataseg << '\n';
- if (const int libCount = libraries.size()) {
- str << "Libraries:\n";
- for (int i = 0; i < libCount; i++)
- str << " #" << i << ' ' << libraries.at(i).name
- << " code: 0x" << libraries.at(i).codeseg
- << " data: 0x" << libraries.at(i).dataseg << '\n';
- }
- if (const int moduleCount = modules.size()) {
- str << "Modules:\n";
- for (int i = 0; i < moduleCount; i++)
- str << " #" << i << ' ' << modules.at(i) << '\n';
- }
- str.setIntegerBase(10);
- if (!addressToBP.isEmpty()) {
- typedef QHash<uint, uint>::const_iterator BP_ConstIterator;
- str << "Breakpoints:\n";
- const BP_ConstIterator cend = addressToBP.constEnd();
- for (BP_ConstIterator it = addressToBP.constBegin(); it != cend; ++it) {
- str.setIntegerBase(16);
- str << " 0x" << it.key();
- str.setIntegerBase(10);
- str << ' ' << it.value() << '\n';
- }
- }
-
- return rc;
-}
-
-// --------------
-
-QByteArray decode7d(const QByteArray &ba)
-{
- QByteArray res;
- res.reserve(ba.size());
- for (int i = 0; i < ba.size(); ++i) {
- byte c = byte(ba.at(i));
- if (c == 0x7d) {
- ++i;
- c = 0x20 ^ byte(ba.at(i));
- }
- res.append(c);
- }
- return res;
-}
-
-QByteArray encode7d(const QByteArray &ba)
-{
- QByteArray res;
- res.reserve(ba.size() + 2);
- for (int i = 0; i < ba.size(); ++i) {
- byte c = byte(ba.at(i));
- if (c == 0x7e || c == 0x7d) {
- res.append(0x7d);
- res.append(0x20 ^ c);
- } else {
- res.append(c);
- }
- }
- return res;
-}
-
-// FIXME: Use the QByteArray based version below?
-static inline QString stringFromByte(byte c)
-{
- return QString::fromLatin1("%1").arg(c, 2, 16, QChar('0'));
-}
-
-SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen)
-{
- QString str;
- QString ascii;
- const int size = maxLen == -1 ? ba.size() : qMin(ba.size(), maxLen);
- for (int i = 0; i < size; ++i) {
- const int c = byte(ba.at(i));
- str += QString::fromAscii("%1 ").arg(c, 2, 16, QChar('0'));
- ascii += QChar(c).isPrint() ? QChar(c) : QChar('.');
- }
- if (size != ba.size()) {
- str += QLatin1String("...");
- ascii += QLatin1String("...");
- }
- return str + QLatin1String(" ") + ascii;
-}
-
-SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits)
-{
- QByteArray ba = QByteArray::number(n, 16);
- if (digits == 0 || ba.size() == digits)
- return ba;
- return QByteArray(digits - ba.size(), '0') + ba;
-}
-
-SYMBIANUTILS_EXPORT QByteArray hexxNumber(uint n, int digits)
-{
- return "0x" + hexNumber(n, digits);
-}
-
-CodaResult::CodaResult() :
- code(0),
- token(0),
- isDebugOutput(false)
-{
-}
-
-void CodaResult::clear()
-{
- code = token= 0;
- isDebugOutput = false;
- data.clear();
- cookie = QVariant();
-}
-
-QString CodaResult::toString() const
-{
- QString res = stringFromByte(code);
- res += QLatin1String(" [");
- res += stringFromByte(token);
- res += QLatin1Char(']');
- res += QLatin1Char(' ');
- res += stringFromArray(data);
- return res;
-}
-
-QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame)
-{
- byte s = command + token;
- for (int i = 0; i != data.size(); ++i)
- s += data.at(i);
- byte checksum = 255 - (s & 0xff);
- //int x = s + ~s;
- //logMessage("check: " << s << checksum << x;
-
- QByteArray response;
- response.reserve(data.size() + 3);
- response.append(char(command));
- response.append(char(token));
- response.append(data);
- response.append(char(checksum));
-
- QByteArray encodedData = encode7d(response);
-
- QByteArray ba;
- ba.reserve(encodedData.size() + 6);
- if (serialFrame) {
- ba.append(char(0x01));
- ba.append(char(0x90));
- const ushort encodedSize = encodedData.size() + 2; // 2 x 0x7e
- appendShort(&ba, encodedSize, BigEndian);
- }
- ba.append(char(0x7e));
- ba.append(encodedData);
- ba.append(char(0x7e));
-
- return ba;
-}
-
-/* returns 0 if array doesn't represent a result,
-otherwise returns the length of the result data */
-ushort isValidCodaResult(const QByteArray &buffer, bool serialFrame, ushort& mux)
-{
- if (serialFrame) {
- // Serial protocol with length info
- if (buffer.length() < 4)
- return 0;
- mux = extractShort(buffer.data());
- const ushort len = extractShort(buffer.data() + 2);
- return (buffer.size() >= len + 4) ? len : ushort(0);
- }
- // Frameless protocol without length info
- const char delimiter = char(0x7e);
- const int firstDelimiterPos = buffer.indexOf(delimiter);
- // Regular message delimited by 0x7e..0x7e
- if (firstDelimiterPos == 0) {
- mux = MuxCoda;
- const int endPos = buffer.indexOf(delimiter, firstDelimiterPos + 1);
- return endPos != -1 ? endPos + 1 - firstDelimiterPos : 0;
- }
- // Some ASCII log message up to first delimiter or all
- return firstDelimiterPos != -1 ? firstDelimiterPos : buffer.size();
-}
-
-bool extractResult(QByteArray *buffer, bool serialFrame, CodaResult *result, bool &linkEstablishmentMode, QByteArray *rawData)
-{
- result->clear();
- if(rawData)
- rawData->clear();
- ushort len = isValidCodaResult(*buffer, serialFrame, result->multiplex);
- // handle receiving application output, which is not a regular command
- const int delimiterPos = serialFrame ? 4 : 0;
- if (linkEstablishmentMode) {
- //when "hot connecting" a device, we can receive partial frames.
- //this code resyncs by discarding data until a CODA frame is found
- while (buffer->length() > delimiterPos
- && result->multiplex != MuxTextTrace
- && !(result->multiplex == MuxCoda && buffer->at(delimiterPos) == 0x7e)) {
- buffer->remove(0,1);
- len = isValidCodaResult(*buffer, serialFrame, result->multiplex);
- }
- }
- if (!len)
- return false;
- if (buffer->at(delimiterPos) != 0x7e) {
- result->isDebugOutput = true;
- result->data = buffer->mid(delimiterPos, len);
- buffer->remove(0, delimiterPos + len);
- return true;
- }
- // 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;
- for (int i = 0; i < data.size(); ++i) // 3 = 2 * 0xfe + sum
- sum += byte(data.at(i));
- if (sum != 0xff)
- logMessage("*** CHECKSUM ERROR: " << byte(sum));
-
- result->code = data.at(0);
- result->token = data.at(1);
- result->data = data.mid(2, data.size() - 3);
- //logMessage(" REST BUF: " << stringFromArray(*buffer));
- //logMessage(" CURR DATA: " << stringFromArray(data));
- //QByteArray prefix = "READ BUF: ";
- //logMessage((prefix + "HEADER: " + stringFromArray(header).toLatin1()).data());
- linkEstablishmentMode = false; //have received a good CODA packet, therefore in sync
- return true;
-}
-
-SYMBIANUTILS_EXPORT ushort extractShort(const char *data)
-{
- return byte(data[0]) * 256 + byte(data[1]);
-}
-
-SYMBIANUTILS_EXPORT uint extractInt(const char *data)
-{
- uint res = byte(data[0]);
- res *= 256; res += byte(data[1]);
- res *= 256; res += byte(data[2]);
- res *= 256; res += byte(data[3]);
- return res;
-}
-
-SYMBIANUTILS_EXPORT quint64 extractInt64(const char *data)
-{
- quint64 res = byte(data[0]);
- res <<= 8; res += byte(data[1]);
- res <<= 8; res += byte(data[2]);
- res <<= 8; res += byte(data[3]);
- res <<= 8; res += byte(data[4]);
- res <<= 8; res += byte(data[5]);
- res <<= 8; res += byte(data[6]);
- res <<= 8; res += byte(data[7]);
- return res;
-}
-
-SYMBIANUTILS_EXPORT QString quoteUnprintableLatin1(const QByteArray &ba)
-{
- QString res;
- char buf[10];
- for (int i = 0, n = ba.size(); i != n; ++i) {
- const byte c = ba.at(i);
- if (isprint(c)) {
- res += c;
- } else {
- qsnprintf(buf, sizeof(buf) - 1, "\\%x", int(c));
- res += buf;
- }
- }
- return res;
-}
-
-SYMBIANUTILS_EXPORT void appendShort(QByteArray *ba, ushort s, Endianness endian)
-{
- if (endian == BigEndian) {
- ba->append(s / 256);
- ba->append(s % 256);
- } else {
- ba->append(s % 256);
- ba->append(s / 256);
- }
-}
-
-SYMBIANUTILS_EXPORT void appendInt(QByteArray *ba, uint i, Endianness endian)
-{
- const uchar b3 = i % 256; i /= 256;
- const uchar b2 = i % 256; i /= 256;
- const uchar b1 = i % 256; i /= 256;
- const uchar b0 = i;
- ba->reserve(ba->size() + 4);
- if (endian == BigEndian) {
- ba->append(b0);
- ba->append(b1);
- ba->append(b2);
- ba->append(b3);
- } else {
- ba->append(b3);
- ba->append(b2);
- ba->append(b1);
- ba->append(b0);
- }
-}
-
-void appendString(QByteArray *ba, const QByteArray &str, Endianness endian, bool appendNullTerminator)
-{
- const int fullSize = str.size() + (appendNullTerminator ? 1 : 0);
- appendShort(ba, fullSize, endian); // count the terminating \0
- ba->append(str);
- if (appendNullTerminator)
- ba->append('\0');
-}
-
-void appendDateTime(QByteArray *ba, QDateTime dateTime, Endianness endian)
-{
- // convert the QDateTime to UTC and append its representation to QByteArray
- // format is the same as in FAT file system
- dateTime = dateTime.toUTC();
- const QTime utcTime = dateTime.time();
- const QDate utcDate = dateTime.date();
- uint fatDateTime = (utcTime.hour() << 11 | utcTime.minute() << 5 | utcTime.second()/2) << 16;
- fatDateTime |= (utcDate.year()-1980) << 9 | utcDate.month() << 5 | utcDate.day();
- appendInt(ba, fatDateTime, endian);
-}
-
-QByteArray errorMessage(byte code)
-{
- switch (code) {
- case 0x00: return "No error";
- case 0x01: return "Generic error in CWDS message";
- case 0x02: return "Unexpected packet size in send msg";
- case 0x03: return "Internal error occurred in CWDS";
- case 0x04: return "Escape followed by frame flag";
- case 0x05: return "Bad FCS in packet";
- case 0x06: return "Packet too long";
- case 0x07: return "Sequence ID not expected (gap in sequence)";
-
- case 0x10: return "Command not supported";
- case 0x11: return "Command param out of range";
- case 0x12: return "An option was not supported";
- case 0x13: return "Read/write to invalid memory";
- case 0x14: return "Read/write invalid registers";
- case 0x15: return "Exception occurred in CWDS";
- case 0x16: return "Targeted system or thread is running";
- case 0x17: return "Breakpoint resources (HW or SW) exhausted";
- case 0x18: return "Requested breakpoint conflicts with existing one";
-
- case 0x20: return "General OS-related error";
- case 0x21: return "Request specified invalid process";
- case 0x22: return "Request specified invalid thread";
- }
- return "Unknown error";
-}
-
-uint swapEndian(uint in)
-{
- return (in>>24) | ((in<<8) & 0x00FF0000) | ((in>>8) & 0x0000FF00) | (in<<24);
-}
-
-int CodaResult::errorCode() const
-{
- // NAK means always error, else data sized 1 with a non-null element
- const bool isNAK = code == 0xff;
- if (data.size() != 1 && !isNAK)
- return 0;
- if (const int errorCode = data.at(0))
- return errorCode;
- return isNAK ? 0xff : 0;
-}
-
-QString CodaResult::errorString() const
-{
- // NAK means always error, else data sized 1 with a non-null element
- if (code == 0xff)
- return "NAK";
- if (data.size() < 1)
- return "Unknown error packet";
- return errorMessage(data.at(0));
-}
-
-} // namespace Coda
-
diff --git a/src/shared/symbianutils/codautils.h b/src/shared/symbianutils/codautils.h
deleted file mode 100644
index c1f1d86243..0000000000
--- a/src/shared/symbianutils/codautils.h
+++ /dev/null
@@ -1,158 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef DEBUGGER_CODA_UTILS
-#define DEBUGGER_CODA_UTILS
-
-#include "symbianutils_global.h"
-
-#include <QByteArray>
-#include <QHash>
-#include <QStringList>
-#include <QVariant>
-
-QT_BEGIN_NAMESPACE
-class QDateTime;
-QT_END_NAMESPACE
-
-namespace Coda {
-
-typedef unsigned char byte;
-struct CodaResult;
-
-enum SerialMultiplexor {
- MuxRaw = 0,
- MuxTextTrace = 0x0102,
- MuxCoda = 0x0190
-};
-
-inline byte extractByte(const char *data) { return *data; }
-SYMBIANUTILS_EXPORT ushort extractShort(const char *data);
-SYMBIANUTILS_EXPORT uint extractInt(const char *data);
-SYMBIANUTILS_EXPORT quint64 extractInt64(const char *data);
-
-SYMBIANUTILS_EXPORT QString quoteUnprintableLatin1(const QByteArray &ba);
-
-// produces "xx xx xx "
-SYMBIANUTILS_EXPORT QString stringFromArray(const QByteArray &ba, int maxLen = - 1);
-
-enum Endianness
-{
- LittleEndian,
- BigEndian,
- TargetByteOrder = BigEndian
-};
-
-SYMBIANUTILS_EXPORT void appendShort(QByteArray *ba, ushort s, Endianness = TargetByteOrder);
-SYMBIANUTILS_EXPORT void appendInt(QByteArray *ba, uint i, Endianness = TargetByteOrder);
-SYMBIANUTILS_EXPORT void appendString(QByteArray *ba, const QByteArray &str, Endianness = TargetByteOrder, bool appendNullTerminator = true);
-
-struct SYMBIANUTILS_EXPORT Library
-{
- Library();
- explicit Library(const CodaResult &r);
-
- QByteArray name;
- uint codeseg;
- uint dataseg;
- //library addresses are valid for a given process (depending on memory model, they might be loaded at the same address in all processes or not)
- uint pid;
-};
-
-struct SYMBIANUTILS_EXPORT CodaAppVersion
-{
- CodaAppVersion();
- void reset();
-
- int codaMajor;
- int codaMinor;
- int protocolMajor;
- int protocolMinor;
-};
-
-struct SYMBIANUTILS_EXPORT Session
-{
- Session();
- void reset();
- QString deviceDescription(unsigned verbose) const;
- QString toString() const;
- // Answer to qXfer::libraries
- QByteArray gdbLibraryList() const;
- // Answer to qsDllInfo, can be sent chunk-wise.
- QByteArray gdbQsDllInfo(int start = 0, int count = -1) const;
-
- // CODA feedback
- byte cpuMajor;
- byte cpuMinor;
- byte bigEndian;
- byte defaultTypeSize;
- byte fpTypeSize;
- byte extended1TypeSize;
- byte extended2TypeSize;
- CodaAppVersion codaAppVersion;
- uint pid;
- uint mainTid;
- uint tid;
- uint codeseg;
- uint dataseg;
- QHash<uint, uint> addressToBP;
-
- typedef QList<Library> Libraries;
- Libraries libraries;
-
- // Gdb request
- QStringList modules;
-};
-
-struct SYMBIANUTILS_EXPORT CodaResult
-{
- CodaResult();
- void clear();
- QString toString() const;
- // 0 for no error.
- int errorCode() const;
- QString errorString() const;
-
- ushort multiplex;
- byte code;
- byte token;
- QByteArray data;
- QVariant cookie;
- bool isDebugOutput;
-};
-
-SYMBIANUTILS_EXPORT QByteArray errorMessage(byte code);
-SYMBIANUTILS_EXPORT QByteArray hexNumber(uint n, int digits = 0);
-SYMBIANUTILS_EXPORT QByteArray hexxNumber(uint n, int digits = 0); // prepends '0x', too
-SYMBIANUTILS_EXPORT uint swapEndian(uint in);
-
-} // namespace Coda
-
-#endif // DEBUGGER_CODA_UTILS
diff --git a/src/shared/symbianutils/codautils_p.h b/src/shared/symbianutils/codautils_p.h
deleted file mode 100644
index 8466ba314b..0000000000
--- a/src/shared/symbianutils/codautils_p.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef DEBUGGER_CODA_PRIVATE_UTILS
-#define DEBUGGER_CODA_PRIVATE_UTILS
-
-#include "codautils.h"
-#include "symbianutils_global.h"
-
-QT_BEGIN_NAMESPACE
-class QDateTime;
-QT_END_NAMESPACE
-
-namespace Coda {
-
-void appendDateTime(QByteArray *ba, QDateTime dateTime, Endianness = TargetByteOrder);
-// returns a QByteArray containing optionally
-// the serial frame [0x01 0x90 <len>] and 0x7e encoded7d(ba) 0x7e
-QByteArray frameMessage(byte command, byte token, const QByteArray &data, bool serialFrame);
-bool extractResult(QByteArray *buffer, bool serialFrame, CodaResult *r, bool& linkEstablishmentMode, QByteArray *rawData = 0);
-
-} // namespace Coda
-
-#endif // DEBUGGER_CODA_PRIVATE_UTILS
diff --git a/src/shared/symbianutils/symbiandevicemanager.cpp b/src/shared/symbianutils/symbiandevicemanager.cpp
deleted file mode 100644
index dca77825ef..0000000000
--- a/src/shared/symbianutils/symbiandevicemanager.cpp
+++ /dev/null
@@ -1,804 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "symbiandevicemanager.h"
-#include "codadevice.h"
-#include "virtualserialdevice.h"
-
-#include <QCoreApplication>
-#include <QEvent>
-#include <QSettings>
-#include <QStringList>
-#include <QFileInfo>
-#include <QDebug>
-#include <QTextStream>
-#include <QSharedData>
-#include <QScopedPointer>
-#include <QSignalMapper>
-#include <QThread>
-#include <QWaitCondition>
-#include <QTimer>
-
-#ifdef Q_OS_MACX
-#include <CoreFoundation/CoreFoundation.h>
-#include <IOKit/IOKitLib.h>
-#include <IOKit/serial/IOSerialKeys.h>
-#include <IOKit/usb/USBSpec.h>
-
-// 10.5 doesn't have kUSBProductString or kUSBVendorString
-#ifndef kUSBProductString
-#define kUSBProductString "USB Product Name"
-#endif
-#ifndef kUSBVendorString
-#define kUSBVendorString "USB Vendor Name"
-#endif
-
-#if defined(MAC_OS_X_VERSION_10_3) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_3)
-#include <IOKit/serial/ioss.h>
-#endif
-#include <IOKit/IOBSD.h>
-#endif
-
-namespace SymbianUtils {
-
-enum { debug = 0 };
-
-static const char REGKEY_CURRENT_CONTROL_SET[] = "HKEY_LOCAL_MACHINE\\SYSTEM\\CurrentControlSet";
-static const char USBSER[] = "Services/usbser/Enum";
-
-const char *SymbianDeviceManager::linuxBlueToothDeviceRootC = "/dev/rfcomm";
-
-// ------------- SymbianDevice
-class SymbianDeviceData : public QSharedData {
-public:
- SymbianDeviceData();
- ~SymbianDeviceData();
-
- bool isOpen() const;
- void forcedClose();
-
- QString portName;
- QString friendlyName;
- QString deviceDesc;
- QString manufacturer;
- QString additionalInformation;
-
- DeviceCommunicationType type;
- QSharedPointer<Coda::CodaDevice> codaDevice;
- int deviceAcquired;
-};
-
-SymbianDeviceData::SymbianDeviceData() :
- type(SerialPortCommunication),
- deviceAcquired(0)
-{
-}
-
-bool SymbianDeviceData::isOpen() const
-{
- return codaDevice && codaDevice->device()->isOpen();
-}
-
-SymbianDeviceData::~SymbianDeviceData()
-{
- forcedClose();
-}
-
-void SymbianDeviceData::forcedClose()
-{
- // Close the device when unplugging. Should devices be in 'acquired' state,
- // their owners should hit on write failures.
- // Apart from the <shared item> destructor, also called by the devicemanager
- // to ensure it also happens if other shared instances are still around.
- if (isOpen()) {
- if (deviceAcquired)
- qWarning("Device on '%s' unplugged while an operation is in progress.",
- qPrintable(portName));
- codaDevice->device()->close();
- }
-}
-
-SymbianDevice::SymbianDevice(SymbianDeviceData *data) :
- m_data(data)
-{
-}
-
-SymbianDevice::SymbianDevice() :
- m_data(new SymbianDeviceData)
-{
-}
-SymbianDevice::SymbianDevice(const SymbianDevice &rhs) :
- m_data(rhs.m_data)
-{
-}
-
-SymbianDevice &SymbianDevice::operator=(const SymbianDevice &rhs)
-{
- if (this != &rhs)
- m_data = rhs.m_data;
- return *this;
-}
-
-SymbianDevice::~SymbianDevice()
-{
-}
-
-void SymbianDevice::forcedClose()
-{
- m_data->forcedClose();
-}
-
-QString SymbianDevice::portName() const
-{
- return m_data->portName;
-}
-
-QString SymbianDevice::friendlyName() const
-{
- return m_data->friendlyName;
-}
-
-QString SymbianDevice::additionalInformation() const
-{
- return m_data->additionalInformation;
-}
-
-void SymbianDevice::setAdditionalInformation(const QString &a)
-{
- m_data->additionalInformation = a;
-}
-
-QString SymbianDevice::deviceDesc() const
-{
- return m_data->deviceDesc;
-}
-
-QString SymbianDevice::manufacturer() const
-{
- return m_data->manufacturer;
-}
-
-DeviceCommunicationType SymbianDevice::type() const
-{
- return m_data->type;
-}
-
-bool SymbianDevice::isNull() const
-{
- return m_data->portName.isEmpty();
-}
-
-bool SymbianDevice::isOpen() const
-{
- return m_data->isOpen();
-}
-
-QString SymbianDevice::toString() const
-{
- QString rc;
- QTextStream str(&rc);
- format(str);
- return rc;
-}
-
-void SymbianDevice::format(QTextStream &str) const
-{
- str << (m_data->type == BlueToothCommunication ? "Bluetooth: " : "Serial: ")
- << m_data->portName;
- if (!m_data->friendlyName.isEmpty()) {
- str << " (" << m_data->friendlyName;
- if (!m_data->deviceDesc.isEmpty())
- str << " / " << m_data->deviceDesc;
- str << ')';
- }
- if (!m_data->manufacturer.isEmpty())
- str << " [" << m_data->manufacturer << ']';
-}
-
-// Compare by port and friendly name
-int SymbianDevice::compare(const SymbianDevice &rhs) const
-{
- if (const int prc = m_data->portName.compare(rhs.m_data->portName))
- return prc;
- if (const int frc = m_data->friendlyName.compare(rhs.m_data->friendlyName))
- return frc;
- return 0;
-}
-
-SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &cd)
-{
- d.nospace() << cd.toString();
- return d;
-}
-
-// ------------- SymbianDeviceManagerPrivate
-struct SymbianDeviceManagerPrivate {
- SymbianDeviceManagerPrivate() :
- m_initialized(false),
- m_devicesLock(QMutex::Recursive)
- {
-#ifdef Q_OS_MACX
- m_deviceListChangedNotification = 0;
-#endif
- }
-
- bool m_initialized;
- SymbianDeviceManager::SymbianDeviceList m_devices;
- QMutex m_devicesLock; // Used for protecting access to m_devices and serialising getCodaDevice/delayedClosePort
- // The following 2 variables are needed to manage requests for a CODA port not coming from the main thread
- int m_constructCodaPortEventType;
- QMutex m_codaPortWaitMutex;
-#ifdef Q_OS_MACX
- IONotificationPortRef m_deviceListChangedNotification;
-#endif
-};
-
-class QConstructCodaPortEvent : public QEvent
-{
-public:
- QConstructCodaPortEvent(QEvent::Type eventId, const QString &portName, CodaDevicePtr *device, QWaitCondition *waiter) :
- QEvent(eventId), m_portName(portName), m_device(device), m_waiter(waiter)
- {}
-
- QString m_portName;
- CodaDevicePtr* m_device;
- QWaitCondition *m_waiter;
-};
-
-
-SymbianDeviceManager::SymbianDeviceManager(QObject *parent) :
- QObject(parent),
- d(new SymbianDeviceManagerPrivate)
-{
- d->m_constructCodaPortEventType = QEvent::registerEventType();
-}
-
-SymbianDeviceManager::~SymbianDeviceManager()
-{
-#ifdef Q_OS_MACX
- if (d && d->m_deviceListChangedNotification)
- IONotificationPortDestroy(d->m_deviceListChangedNotification);
-#endif
- delete d;
-}
-
-SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::devices() const
-{
- ensureInitialized();
- QMutexLocker lock(&d->m_devicesLock);
- return d->m_devices;
-}
-
-QString SymbianDeviceManager::toString() const
-{
- QMutexLocker lock(&d->m_devicesLock);
- QString rc;
- QTextStream str(&rc);
- str << d->m_devices.size() << " devices:\n";
- const int count = d->m_devices.size();
- for (int i = 0; i < count; i++) {
- str << '#' << i << ' ';
- d->m_devices.at(i).format(str);
- str << '\n';
- }
- return rc;
-}
-
-int SymbianDeviceManager::findByPortName(const QString &p) const
-{
- ensureInitialized();
- const int count = d->m_devices.size();
- for (int i = 0; i < count; i++)
- if (d->m_devices.at(i).portName() == p)
- return i;
- return -1;
-}
-
-QString SymbianDeviceManager::friendlyNameForPort(const QString &port) const
-{
- QMutexLocker lock(&d->m_devicesLock);
- const int idx = findByPortName(port);
- return idx == -1 ? QString() : d->m_devices.at(idx).friendlyName();
-}
-
-CodaDevicePtr SymbianDeviceManager::getCodaDevice(const QString &port)
-{
- ensureInitialized();
- QMutexLocker lock(&d->m_devicesLock);
- const int idx = findByPortName(port);
- if (idx == -1) {
- qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port));
- if (debug)
- qDebug() << *this;
- return CodaDevicePtr();
- }
- SymbianDevice& device = d->m_devices[idx];
- CodaDevicePtr& devicePtr = device.m_data->codaDevice;
- if (devicePtr.isNull() || !devicePtr->device()->isOpen()) {
- // Check we instanciate in the correct thread - we can't afford to create the CodaDevice (and more specifically, open the VirtualSerialDevice) in a thread that isn't guaranteed to be long-lived.
- // Therefore, if we're not in SymbianDeviceManager's thread, rejig things so it's opened in the main thread
- if (QThread::currentThread() != thread()) {
- // SymbianDeviceManager is owned by the main thread
- d->m_codaPortWaitMutex.lock();
- QWaitCondition waiter;
- QCoreApplication::postEvent(this, new QConstructCodaPortEvent((QEvent::Type)d->m_constructCodaPortEventType, port, &devicePtr, &waiter));
- waiter.wait(&d->m_codaPortWaitMutex);
- // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the CodaDevice will be fully set up
- d->m_codaPortWaitMutex.unlock();
- } else {
- // We're in the main thread, just set it up directly
- constructCodaPort(devicePtr, port);
- }
- // We still carry on in the case we failed to open so the client can access the IODevice's errorString()
- }
- if (devicePtr->device()->isOpen())
- device.m_data->deviceAcquired++;
- return devicePtr;
-}
-
-void SymbianDeviceManager::constructCodaPort(CodaDevicePtr& device, const QString& portName)
-{
- QMutexLocker locker(&d->m_codaPortWaitMutex);
- if (device.isNull()) {
- device = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
- const QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(portName));
- device->setSerialFrame(true);
- device->setDevice(serialDevice);
- }
- if (!device->device()->isOpen()) {
- bool ok = device->device().staticCast<SymbianUtils::VirtualSerialDevice>()->open(QIODevice::ReadWrite);
- if (!ok && debug) {
- qDebug("SymbianDeviceManager: Failed to open port %s", qPrintable(portName));
- }
- }
-}
-
-void SymbianDeviceManager::customEvent(QEvent *event)
-{
- if (event->type() == d->m_constructCodaPortEventType) {
- QConstructCodaPortEvent* constructEvent = static_cast<QConstructCodaPortEvent*>(event);
- constructCodaPort(*constructEvent->m_device, constructEvent->m_portName);
- constructEvent->m_waiter->wakeAll(); // Should only ever be one thing waiting on this
- }
-}
-
-void SymbianDeviceManager::releaseCodaDevice(CodaDevicePtr &port)
-{
- if (port) {
- QMutexLocker(&d->m_devicesLock);
- // Check if this was the last reference to the port, if so close it after a short delay
- foreach (const SymbianDevice& device, d->m_devices) {
- if (device.m_data->codaDevice.data() == port.data()) {
- if (device.m_data->deviceAcquired > 0)
- device.m_data->deviceAcquired--;
- if (device.m_data->deviceAcquired == 0) {
- if (debug)
- qDebug("Starting timer to close port %s", qPrintable(device.m_data->portName));
- QTimer::singleShot(1000, this, SLOT(delayedClosePort()));
- }
- break;
- }
- }
- port.clear();
- }
-}
-
-void SymbianDeviceManager::delayedClosePort()
-{
- // Find any coda ports that are still open but have a reference count of zero, and delete them
- QMutexLocker(&d->m_devicesLock);
- foreach (const SymbianDevice& device, d->m_devices) {
- Coda::CodaDevice* codaDevice = device.m_data->codaDevice.data();
- if (codaDevice && device.m_data->deviceAcquired == 0 && codaDevice->device()->isOpen()) {
- if (debug)
- qDebug("Closing device %s", qPrintable(device.m_data->portName));
- device.m_data->codaDevice->device()->close();
- }
- }
-}
-
-void SymbianDeviceManager::update()
-{
- update(true);
-}
-
-void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai)
-{
- const int idx = findByPortName(port);
- if (idx != -1)
- d->m_devices[idx].setAdditionalInformation(ai);
-}
-
-void SymbianDeviceManager::ensureInitialized() const
-{
- if (!d->m_initialized) // Flag is set in update()
- const_cast<SymbianDeviceManager*>(this)->update(false);
-}
-
-void SymbianDeviceManager::update(bool emitSignals)
-{
- QMutexLocker lock(&d->m_devicesLock);
-
- static int n = 0;
- typedef SymbianDeviceList::iterator SymbianDeviceListIterator;
-
- if (debug)
- qDebug(">SerialDeviceLister::update(#%d, signals=%d)\n%s", n++, int(emitSignals),
- qPrintable(toString()));
-
- d->m_initialized = true;
- // Get ordered new list
- SymbianDeviceList newDevices = serialPorts() + blueToothDevices();
- if (newDevices.size() > 1)
- qStableSort(newDevices.begin(), newDevices.end());
- if (d->m_devices == newDevices) { // Happy, nothing changed.
- if (debug)
- qDebug("<SerialDeviceLister::update: unchanged\n");
- return;
- }
- // Merge the lists and emit the respective added/removed signals, assuming
- // no one can plug a different device on the same port at the speed of lightning
- SymbianDeviceList removedDevices;
- if (!d->m_devices.isEmpty()) {
- // Find deleted devices
- for (SymbianDeviceListIterator oldIt = d->m_devices.begin(); oldIt != d->m_devices.end(); ) {
- if (newDevices.contains(*oldIt)) {
- ++oldIt;
- } else {
- SymbianDevice toBeDeleted = *oldIt;
- toBeDeleted.forcedClose();
- oldIt = d->m_devices.erase(oldIt);
- removedDevices.append(toBeDeleted);
- }
- }
- }
- SymbianDeviceList addedDevices;
- if (!newDevices.isEmpty()) {
- // Find new devices and insert in order
- foreach(const SymbianDevice &newDevice, newDevices) {
- if (!d->m_devices.contains(newDevice)) {
- d->m_devices.append(newDevice);
- addedDevices.append(newDevice);
- }
- }
- if (d->m_devices.size() > 1)
- qStableSort(d->m_devices.begin(), d->m_devices.end());
- }
-
- lock.unlock();
- if (emitSignals) {
- foreach (const SymbianDevice &device, removedDevices) {
- emit deviceRemoved(device);
- }
- foreach (const SymbianDevice &device, addedDevices) {
- emit deviceAdded(device);
- }
- emit updated();
- }
-
- if (debug)
- qDebug("<SerialDeviceLister::update\n%s\n", qPrintable(toString()));
-}
-
-#ifdef Q_OS_MACX
-QString CFStringToQString(CFStringRef cfstring)
-{
- QString result;
- int len = CFStringGetLength(cfstring);
- result.resize(len);
- CFStringGetCharacters(cfstring, CFRangeMake(0, len), reinterpret_cast<UniChar *>(result.data()));
- return result;
-}
-
-void deviceListChanged(void *refCon, io_iterator_t iter)
-{
- // The way we're structured, it's easier to rescan rather than take advantage of the finer-grained device addition and removal info that OS X gives us
- io_object_t obj;
- while ((obj = IOIteratorNext(iter))) IOObjectRelease(obj);
- static_cast<SymbianDeviceManager *>(refCon)->update();
-}
-
-#endif
-
-SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::serialPorts() const
-{
- SymbianDeviceList rc;
-#if defined(Q_OS_WIN)
- const QSettings registry(REGKEY_CURRENT_CONTROL_SET, QSettings::NativeFormat);
- const QString usbSerialRootKey = QLatin1String(USBSER) + QLatin1Char('/');
- const int count = registry.value(usbSerialRootKey + QLatin1String("Count")).toInt();
- for (int i = 0; i < count; ++i) {
- QString driver = registry.value(usbSerialRootKey + QString::number(i)).toString();
- if (driver.contains(QLatin1String("JAVACOMM"))) {
- driver.replace(QLatin1Char('\\'), QLatin1Char('/'));
- const QString driverRootKey = QLatin1String("Enum/") + driver + QLatin1Char('/');
- if (debug > 1)
- qDebug() << "SerialDeviceLister::serialPorts(): Checking " << i << count
- << REGKEY_CURRENT_CONTROL_SET << usbSerialRootKey << driverRootKey;
- QScopedPointer<SymbianDeviceData> device(new SymbianDeviceData);
- device->type = SerialPortCommunication;
- device->friendlyName = registry.value(driverRootKey + QLatin1String("FriendlyName")).toString();
- device->portName = registry.value(driverRootKey + QLatin1String("Device Parameters/PortName")).toString();
- device->deviceDesc = registry.value(driverRootKey + QLatin1String("DeviceDesc")).toString();
- device->manufacturer = registry.value(driverRootKey + QLatin1String("Mfg")).toString();
- rc.append(SymbianDevice(device.take()));
- }
- }
-#elif defined(Q_OS_MACX)
- CFMutableDictionaryRef classesToMatch = IOServiceMatching(kIOSerialBSDServiceValue);
- if (!classesToMatch) return rc;
-
- CFDictionarySetValue(classesToMatch,
- CFSTR(kIOSerialBSDTypeKey),
- CFSTR(kIOSerialBSDAllTypes));
-
- // Setup notifier if necessary
- if (d->m_deviceListChangedNotification == 0) {
- d->m_deviceListChangedNotification = IONotificationPortCreate(kIOMasterPortDefault);
- if (d->m_deviceListChangedNotification) {
- CFRunLoopSourceRef runloopSource = IONotificationPortGetRunLoopSource(d->m_deviceListChangedNotification);
- CFRunLoopAddSource(CFRunLoopGetCurrent(), runloopSource, kCFRunLoopDefaultMode);
- // IOServiceAddMatchingNotification eats a reference each time we call it, so make sure it's still valid for the IOServiceGetMatchingServices later
- CFRetain(classesToMatch);
- CFRetain(classesToMatch);
- io_iterator_t devicesAddedIterator;
- io_iterator_t devicesRemovedIterator;
- IOServiceAddMatchingNotification(d->m_deviceListChangedNotification, kIOMatchedNotification, classesToMatch, &deviceListChanged, (void*)this, &devicesAddedIterator);
- IOServiceAddMatchingNotification(d->m_deviceListChangedNotification, kIOTerminatedNotification, classesToMatch, &deviceListChanged, (void*)this, &devicesRemovedIterator);
- // Arm the iterators - we're not interested in the lists at this point, and the API rather expects that we will be
- io_object_t obj;
- while ((obj = IOIteratorNext(devicesAddedIterator))) IOObjectRelease(obj);
- while ((obj = IOIteratorNext(devicesRemovedIterator))) IOObjectRelease(obj);
- }
- }
- io_iterator_t matchingServices;
- kern_return_t kernResult = IOServiceGetMatchingServices(kIOMasterPortDefault, classesToMatch, &matchingServices);
- if (kernResult != KERN_SUCCESS) {
- if (debug)
- qDebug("IOServiceGetMatchingServices returned %d", kernResult);
- return rc;
- }
-
- io_object_t serialPort;
- kernResult = KERN_FAILURE;
- while ((serialPort = IOIteratorNext(matchingServices))) {
- // Check if it's Bluetooth or USB, and if so we can apply additional filters to weed out things that definitely aren't valid ports
- io_object_t parent, grandparent;
- kernResult = IORegistryEntryGetParentEntry(serialPort, kIOServicePlane, &parent);
- bool match = true;
- DeviceCommunicationType deviceType = SerialPortCommunication;
- CFStringRef name = NULL;
- if (kernResult == KERN_SUCCESS) {
- kernResult = IORegistryEntryGetParentEntry(parent, kIOServicePlane, &grandparent);
- if (kernResult == KERN_SUCCESS) {
- CFStringRef className = IOObjectCopyClass(grandparent);
- if (CFStringCompare(className, CFSTR("IOBluetoothSerialClient"), 0) == 0) {
- // CODA doesn't support bluetooth
- match = false;
- }
- else if (CFStringCompare(className, CFSTR("AppleUSBCDCACMData"), 0) == 0) {
- match = false;
- CFNumberRef interfaceNumber = (CFNumberRef)IORegistryEntrySearchCFProperty(grandparent, kIOServicePlane, CFSTR(kUSBInterfaceNumber), kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
- if (interfaceNumber) {
- int val;
- if (CFNumberGetValue(interfaceNumber, kCFNumberIntType, &val) && val == 4) match = true;
- CFRelease(interfaceNumber);
- }
- if (match) {
- CFStringRef deviceName = (CFStringRef)IORegistryEntrySearchCFProperty(grandparent, kIOServicePlane, CFSTR(kUSBProductString), kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
- CFStringRef vendorName = (CFStringRef)IORegistryEntrySearchCFProperty(grandparent, kIOServicePlane, CFSTR(kUSBVendorString), kCFAllocatorDefault, kIORegistryIterateParents | kIORegistryIterateRecursively);
- if (deviceName && vendorName) name = CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%@ %@"), vendorName, deviceName);
- if (deviceName) CFRelease(deviceName);
- if (vendorName) CFRelease(vendorName);
- }
- }
- else {
- // We don't expect CODA on any other type of serial port
- match = false;
- }
- CFRelease(className);
- IOObjectRelease(grandparent);
- }
- IOObjectRelease(parent);
- }
-
- if (match) {
- CFStringRef devPath = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIODialinDeviceKey), kCFAllocatorDefault, 0);
- if (name == NULL)
- name = (CFStringRef)IORegistryEntryCreateCFProperty(serialPort, CFSTR(kIOTTYBaseNameKey), kCFAllocatorDefault, 0);
- QScopedPointer<SymbianDeviceData> device(new SymbianDeviceData);
- device->type = deviceType;
- device->friendlyName = CFStringToQString(name);
- device->portName = CFStringToQString(devPath);
-
- CFRelease(devPath);
- CFRelease(name);
- rc.append(SymbianDevice(device.take()));
- }
- IOObjectRelease(serialPort);
- }
- IOObjectRelease(matchingServices);
-#endif
- return rc;
-}
-
-SymbianDeviceManager::SymbianDeviceList SymbianDeviceManager::blueToothDevices() const
-{
- SymbianDeviceList rc;
-#if defined(Q_OS_UNIX) && !defined(Q_OS_MAC)
- // Bluetooth devices are created on connection. List the existing ones
- // or at least the first one.
- const QString prefix = QLatin1String(linuxBlueToothDeviceRootC);
- const QString blueToothfriendlyFormat = QLatin1String("Bluetooth device (%1)");
- for (int d = 0; d < 4; d++) {
- QScopedPointer<SymbianDeviceData> device(new SymbianDeviceData);
- device->type = BlueToothCommunication;
- device->portName = prefix + QString::number(d);
- if (d == 0 || QFileInfo(device->portName).exists()) {
- device->friendlyName = blueToothfriendlyFormat.arg(device->portName);
- rc.push_back(SymbianDevice(device.take()));
- }
- }
- // New kernel versions support /dev/ttyUSB0, /dev/ttyUSB1.
- static const char *usbTtyDevices[] = {
- "/dev/ttyUSB3", "/dev/ttyUSB2", "/dev/ttyUSB1", "/dev/ttyUSB0",
- "/dev/ttyACM3", "/dev/ttyACM2", "/dev/ttyACM1", "/dev/ttyACM0"};
- const int usbTtyCount = sizeof(usbTtyDevices)/sizeof(const char *);
- for (int d = 0; d < usbTtyCount; d++) {
- const QString ttyUSBDevice = QLatin1String(usbTtyDevices[d]);
- if (QFileInfo(ttyUSBDevice).exists()) {
- SymbianDeviceData *device = new SymbianDeviceData;
- device->type = SerialPortCommunication;
- device->portName = ttyUSBDevice;
- device->friendlyName = QString::fromLatin1("USB/Serial device (%1)").arg(device->portName);
- rc.push_back(SymbianDevice(device));
- }
- }
-#endif
- return rc;
-}
-
-Q_GLOBAL_STATIC(SymbianDeviceManager, symbianDeviceManager)
-
-SymbianDeviceManager *SymbianDeviceManager::instance()
-{
- return symbianDeviceManager();
-}
-
-SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &sdm)
-{
- d.nospace() << sdm.toString();
- return d;
-}
-
-OstChannel *SymbianDeviceManager::getOstChannel(const QString &port, uchar channelId)
-{
- CodaDevicePtr coda = getCodaDevice(port);
- if (coda.isNull() || !coda->device()->isOpen())
- return 0;
- return new OstChannel(coda, channelId);
-}
-
-struct OstChannelPrivate
-{
- CodaDevicePtr m_codaPtr;
- QByteArray m_dataBuffer;
- uchar m_channelId;
- bool m_hasReceivedData;
-};
-
-OstChannel::OstChannel(const CodaDevicePtr &codaPtr, uchar channelId)
- : d(new OstChannelPrivate)
-{
- d->m_codaPtr = codaPtr;
- d->m_channelId = channelId;
- d->m_hasReceivedData = false;
- connect(codaPtr.data(), SIGNAL(unknownEvent(uchar,QByteArray)), this, SLOT(ostDataReceived(uchar,QByteArray)));
- connect(codaPtr->device().data(), SIGNAL(aboutToClose()), this, SLOT(deviceAboutToClose()));
- QIODevice::open(ReadWrite|Unbuffered);
-}
-
-void OstChannel::close()
-{
- QIODevice::close();
- if (d && d->m_codaPtr.data()) {
- disconnect(d->m_codaPtr.data(), 0, this, 0);
- SymbianDeviceManager::instance()->releaseCodaDevice(d->m_codaPtr);
- }
-}
-
-OstChannel::~OstChannel()
-{
- close();
- delete d;
-}
-
-void OstChannel::flush()
-{
- //TODO d->m_codaPtr->device()-
-}
-
-qint64 OstChannel::bytesAvailable() const
-{
- return d->m_dataBuffer.size();
-}
-
-bool OstChannel::isSequential() const
-{
- return true;
-}
-
-qint64 OstChannel::readData(char *data, qint64 maxSize)
-{
- qint64 amount = qMin(maxSize, (qint64)d->m_dataBuffer.size());
- qMemCopy(data, d->m_dataBuffer.constData(), amount);
- d->m_dataBuffer.remove(0, amount);
- return amount;
-}
-
-qint64 OstChannel::writeData(const char *data, qint64 maxSize)
-{
- static const qint64 KMaxOstPayload = 1024;
- // If necessary, split the packet up
- qint64 remainder = maxSize;
- while (remainder) {
- QByteArray dataBuf = QByteArray::fromRawData(data, qMin(KMaxOstPayload, remainder));
- d->m_codaPtr->writeCustomData(d->m_channelId, dataBuf);
- data += dataBuf.length();
- remainder -= dataBuf.length();
- }
- return maxSize;
-}
-
-void OstChannel::ostDataReceived(uchar channelId, const QByteArray &aData)
-{
- if (channelId == d->m_channelId) {
- d->m_hasReceivedData = true;
- d->m_dataBuffer.append(aData);
- emit readyRead();
- }
-}
-
-Coda::CodaDevice& OstChannel::codaDevice() const
-{
- return *d->m_codaPtr;
-}
-
-bool OstChannel::hasReceivedData() const
-{
- return isOpen() && d->m_hasReceivedData;
-}
-
-void OstChannel::deviceAboutToClose()
-{
- close();
-}
-
-} // namespace SymbianUtils
diff --git a/src/shared/symbianutils/symbiandevicemanager.h b/src/shared/symbianutils/symbiandevicemanager.h
deleted file mode 100644
index e3d257e439..0000000000
--- a/src/shared/symbianutils/symbiandevicemanager.h
+++ /dev/null
@@ -1,208 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef SYMBIANDEVICEMANAGER_H
-#define SYMBIANDEVICEMANAGER_H
-
-#include "symbianutils_global.h"
-
-#include <QIODevice>
-#include <QExplicitlySharedDataPointer>
-#include <QSharedPointer>
-
-QT_BEGIN_NAMESPACE
-class QDebug;
-class QTextStream;
-QT_END_NAMESPACE
-
-namespace Coda {
- class CodaDevice;
-}
-
-namespace SymbianUtils {
-
-struct SymbianDeviceManagerPrivate;
-class SymbianDeviceData;
-class OstChannel;
-
-enum DeviceCommunicationType {
- SerialPortCommunication = 0,
- BlueToothCommunication = 1
-};
-
-typedef QSharedPointer<Coda::CodaDevice> CodaDevicePtr;
-
-// SymbianDevice: Explicitly shared device data and a CodaDevice
-// instance that can be acquired (exclusively) for use.
-// A device removal from the manager will result in the
-// device being closed.
-class SYMBIANUTILS_EXPORT SymbianDevice {
- explicit SymbianDevice(SymbianDeviceData *data);
- friend class SymbianDeviceManager;
-
-public:
- SymbianDevice();
- SymbianDevice(const SymbianDevice &rhs);
- SymbianDevice &operator=(const SymbianDevice &rhs);
- ~SymbianDevice();
- int compare(const SymbianDevice &rhs) const;
-
- DeviceCommunicationType type() const;
- bool isNull() const;
- QString portName() const;
- QString friendlyName() const;
- QString additionalInformation() const;
- void setAdditionalInformation(const QString &);
-
- bool isOpen() const;
-
- // Windows only.
- QString deviceDesc() const;
- QString manufacturer() const;
-
- void format(QTextStream &str) const;
- QString toString() const;
-
-private:
- void forcedClose();
-
- QExplicitlySharedDataPointer<SymbianDeviceData> m_data;
-};
-
-SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDevice &);
-
-inline bool operator==(const SymbianDevice &d1, const SymbianDevice &d2)
- { return d1.compare(d2) == 0; }
-inline bool operator!=(const SymbianDevice &d1, const SymbianDevice &d2)
- { return d1.compare(d2) != 0; }
-inline bool operator<(const SymbianDevice &d1, const SymbianDevice &d2)
- { return d1.compare(d2) < 0; }
-
-/* SymbianDeviceManager: Singleton that maintains a list of Symbian devices.
- * and emits change signals.
- * On Windows, the update slot must be connected to a [delayed] signal
- * emitted from an event handler listening for WM_DEVICECHANGE.
- * Device removal will result in the device being closed. */
-class SYMBIANUTILS_EXPORT SymbianDeviceManager : public QObject
-{
- Q_OBJECT
-public:
- typedef QList<SymbianDevice> SymbianDeviceList;
-
- static const char *linuxBlueToothDeviceRootC;
-
- // Do not use this constructor, it is just public for Q_GLOBAL_STATIC
- explicit SymbianDeviceManager(QObject *parent = 0);
- virtual ~SymbianDeviceManager();
-
- // Singleton access.
- static SymbianDeviceManager *instance();
-
- SymbianDeviceList devices() const;
- QString toString() const;
-
- //// The CODA code prefers to set up the CodaDevice object itself, so we let it and just handle opening the underlying QIODevice and keeping track of the CodaDevice
- //// Returns true if port was opened successfully.
-
- // Gets the CodaDevice, which may or may not be open depending on what other clients have already acquired it.
- // Therefore once clients have set up any signals and slots they required, they should check CodaDevice::device()->isOpen()
- // and if false, the open failed and they should check device()->errorString() if required.
- // Caller should call releaseCodaDevice if they want the port to auto-close itself
- CodaDevicePtr getCodaDevice(const QString &port);
-
- // Note this function makes no guarantee that someone else isn't already listening on this channel id, or that there is anything on the other end
- // Returns NULL if the port couldn't be opened
- OstChannel *getOstChannel(const QString &port, uchar channelId);
-
- // Caller is responsible for disconnecting any signals from aPort - do not assume the CodaDevice will be deleted as a result of this call. On return aPort will be clear()ed.
- void releaseCodaDevice(CodaDevicePtr &aPort);
-
- int findByPortName(const QString &p) const;
- QString friendlyNameForPort(const QString &port) const;
-
-public slots:
- void update();
- void setAdditionalInformation(const QString &port, const QString &ai);
-
-signals:
- void deviceRemoved(const SymbianUtils::SymbianDevice &d);
- void deviceAdded(const SymbianUtils::SymbianDevice &d);
- void updated();
-
-private slots:
- void delayedClosePort();
-
-private:
- void ensureInitialized() const;
- void update(bool emitSignals);
- SymbianDeviceList serialPorts() const;
- SymbianDeviceList blueToothDevices() const;
- void customEvent(QEvent *event);
- void constructCodaPort(CodaDevicePtr& device, const QString& portName);
-
- SymbianDeviceManagerPrivate *d;
-};
-
-SYMBIANUTILS_EXPORT QDebug operator<<(QDebug d, const SymbianDeviceManager &);
-
-struct OstChannelPrivate;
-
-class SYMBIANUTILS_EXPORT OstChannel : public QIODevice
-{
- Q_OBJECT
-
-public:
- void close();
- ~OstChannel();
- void flush();
-
- qint64 bytesAvailable() const;
- bool isSequential() const;
- bool hasReceivedData() const;
-
- Coda::CodaDevice &codaDevice() const;
-
-private slots:
- void ostDataReceived(uchar channelId, const QByteArray &aData);
- void deviceAboutToClose();
-
-private:
- OstChannel(const CodaDevicePtr &codaPtr, uchar channelId);
- qint64 readData(char *data, qint64 maxSize);
- qint64 writeData(const char *data, qint64 maxSize);
-
-private:
- OstChannelPrivate *d;
- friend class SymbianDeviceManager;
-};
-
-} // namespace SymbianUtils
-
-#endif // SYMBIANDEVICEMANAGER_H
diff --git a/src/shared/symbianutils/symbianutils.pri b/src/shared/symbianutils/symbianutils.pri
deleted file mode 100644
index 0bcddde981..0000000000
--- a/src/shared/symbianutils/symbianutils.pri
+++ /dev/null
@@ -1,42 +0,0 @@
-INCLUDEPATH *= $$PWD
-
-QT += network
-win32 {
- greaterThan(QT_MAJOR_VERSION, 4) {
- QT += core-private
- } else {
- include(../../private_headers.pri)
- }
-}
-
-# Input
-HEADERS += $$PWD/symbianutils_global.h \
- $$PWD/callback.h \
- $$PWD/codautils.h \
- $$PWD/codautils_p.h \
- $$PWD/symbiandevicemanager.h \
- $$PWD/codadevice.h \
- $$PWD/codamessage.h \
- $$PWD/virtualserialdevice.h
-
-SOURCES += $$PWD/codautils.cpp \
- $$PWD/symbiandevicemanager.cpp \
- $$PWD/codadevice.cpp \
- $$PWD/codamessage.cpp \
- $$PWD/virtualserialdevice.cpp
-
-DEFINES += HAS_SERIALPORT
-win32:SOURCES += $$PWD/virtualserialdevice_win.cpp
-unix:SOURCES += $$PWD/virtualserialdevice_posix.cpp
-
-macx:LIBS += -framework IOKit -framework CoreFoundation
-include(../../shared/json/json.pri)
-
-DEFINES += JSON_INCLUDE_PRI
-
-contains(CONFIG, dll) {
- DEFINES += SYMBIANUTILS_BUILD_LIB
-} else {
- DEFINES += SYMBIANUTILS_BUILD_STATIC_LIB
-}
-
diff --git a/src/shared/symbianutils/symbianutils_global.h b/src/shared/symbianutils/symbianutils_global.h
deleted file mode 100644
index fa9b02a433..0000000000
--- a/src/shared/symbianutils/symbianutils_global.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef SYMBIANUTILS_GLOBAL_H
-#define SYMBIANUTILS_GLOBAL_H
-
-#include <qglobal.h>
-
-#if defined(SYMBIANUTILS_BUILD_LIB)
-# define SYMBIANUTILS_EXPORT Q_DECL_EXPORT
-#elif defined(SYMBIANUTILS_BUILD_STATIC_LIB) || defined(SYMBIANUTILS_INCLUDE_PRI)
-# define SYMBIANUTILS_EXPORT
-#else
-# define SYMBIANUTILS_EXPORT Q_DECL_IMPORT
-#endif
-
-#endif // SYMBIANUTILS_GLOBAL_H
diff --git a/src/shared/symbianutils/virtualserialdevice.cpp b/src/shared/symbianutils/virtualserialdevice.cpp
deleted file mode 100644
index 64007eb3c7..0000000000
--- a/src/shared/symbianutils/virtualserialdevice.cpp
+++ /dev/null
@@ -1,78 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "virtualserialdevice.h"
-#include <QThread>
-#include <QWaitCondition>
-
-namespace SymbianUtils {
-
-bool VirtualSerialDevice::isSequential() const
-{
- return true;
-}
-
-VirtualSerialDevice::VirtualSerialDevice(const QString &aPortName, QObject *parent) :
- QIODevice(parent), portName(aPortName), lock(QMutex::NonRecursive), emittingBytesWritten(false), waiterForBytesWritten(NULL)
-{
- platInit();
-}
-
-const QString& VirtualSerialDevice::getPortName() const
-{
- return portName;
-}
-
-void VirtualSerialDevice::close()
-{
- if (isOpen()) {
- QMutexLocker locker(&lock);
- delete waiterForBytesWritten;
- waiterForBytesWritten = NULL;
- QIODevice::close();
- platClose();
- }
-}
-
-void VirtualSerialDevice::emitBytesWrittenIfNeeded(QMutexLocker& locker, qint64 len)
-{
- if (waiterForBytesWritten) {
- waiterForBytesWritten->wakeAll();
- }
- if (!emittingBytesWritten) {
- emittingBytesWritten = true;
- locker.unlock();
- emit bytesWritten(len);
- locker.relock();
- emittingBytesWritten = false;
- }
-}
-
-} // namespace SymbianUtils
diff --git a/src/shared/symbianutils/virtualserialdevice.h b/src/shared/symbianutils/virtualserialdevice.h
deleted file mode 100644
index a4e295cecb..0000000000
--- a/src/shared/symbianutils/virtualserialdevice.h
+++ /dev/null
@@ -1,115 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#ifndef VIRTUALSERIALPORT_H
-#define VIRTUALSERIALPORT_H
-
-#include <QIODevice>
-#include <QString>
-#include <QMutex>
-
-QT_BEGIN_NAMESPACE
-class QWaitCondition;
-QT_END_NAMESPACE
-
-#include "symbianutils_global.h"
-
-namespace SymbianUtils {
-
-class VirtualSerialDevicePrivate;
-
-class SYMBIANUTILS_EXPORT VirtualSerialDevice : public QIODevice
-{
- Q_OBJECT
-public:
- explicit VirtualSerialDevice(const QString &name, QObject *parent = 0);
- ~VirtualSerialDevice();
-
- bool open(OpenMode mode);
- void close();
- const QString &getPortName() const;
- void flush();
-
- qint64 bytesAvailable() const;
- bool isSequential() const;
- bool waitForBytesWritten(int msecs);
- bool waitForReadyRead(int msecs);
-
-protected:
- qint64 readData(char *data, qint64 maxSize);
- qint64 writeData(const char *data, qint64 maxSize);
-
-private:
- void platInit();
- void platClose();
- void emitBytesWrittenIfNeeded(QMutexLocker &locker, qint64 len);
-
-private:
- QString portName;
- mutable QMutex lock;
- QList<QByteArray> pendingWrites;
- bool emittingBytesWritten;
- QWaitCondition* waiterForBytesWritten;
- VirtualSerialDevicePrivate *d;
-
-// Platform-specific stuff
-#ifdef Q_OS_WIN
-private:
- qint64 writeNextBuffer(QMutexLocker &locker);
- void doWriteCompleted(QMutexLocker &locker);
-private slots:
- void writeCompleted();
- void commEventOccurred();
-#endif
-
-#ifdef Q_OS_UNIX
-private:
- bool tryWrite(const char *data, qint64 maxSize, qint64 &bytesWritten);
- enum FlushPendingOption {
- NothingSpecial = 0,
- StopAfterWritingOneBuffer = 1,
- EmitBytesWrittenAsync = 2 // Needed so we don't emit bytesWritten signal directly from writeBytes
- };
- Q_DECLARE_FLAGS(FlushPendingOptions, FlushPendingOption)
- bool tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags = NothingSpecial);
-
-private slots:
- void writeHasUnblocked(int fileHandle);
-
-signals:
- void AsyncCall_emitBytesWrittenIfNeeded(qint64 len);
-
-#endif
-
-};
-
-} // namespace SymbianUtils
-
-#endif // VIRTUALSERIALPORT_H
diff --git a/src/shared/symbianutils/virtualserialdevice_posix.cpp b/src/shared/symbianutils/virtualserialdevice_posix.cpp
deleted file mode 100644
index a51f059e5d..0000000000
--- a/src/shared/symbianutils/virtualserialdevice_posix.cpp
+++ /dev/null
@@ -1,338 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <errno.h>
-#include <termios.h>
-#include <sys/ioctl.h>
-#include <unistd.h>
-#include <QSocketNotifier>
-#include <QTimer>
-#include <QThread>
-#include <QWaitCondition>
-#include "virtualserialdevice.h"
-
-namespace SymbianUtils {
-
-class VirtualSerialDevicePrivate
-{
-public:
- int portHandle;
- QSocketNotifier* readNotifier;
- QSocketNotifier* writeUnblockedNotifier;
-};
-
-void VirtualSerialDevice::platInit()
-{
- d = new VirtualSerialDevicePrivate;
- d->portHandle = -1;
- d->readNotifier = NULL;
- d->writeUnblockedNotifier = NULL;
- connect(this, SIGNAL(AsyncCall_emitBytesWrittenIfNeeded(qint64)), this, SIGNAL(bytesWritten(qint64)), Qt::QueuedConnection);
-}
-
-bool VirtualSerialDevice::open(OpenMode mode)
-{
- if (isOpen()) return true;
-
- d->portHandle = ::open(portName.toAscii().constData(), O_RDWR | O_NONBLOCK | O_NOCTTY);
- if (d->portHandle == -1) {
- setErrorString(tr("The port %1 could not be opened: %2 (POSIX error %3)").
- arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno));
- return false;
- }
-
- struct termios termInfo;
- if (tcgetattr(d->portHandle, &termInfo) < 0) {
- setErrorString(tr("Unable to retrieve terminal settings of port %1: %2 (POSIX error %3)").
- arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno));
- close();
- return false;
- }
- cfmakeraw(&termInfo);
- // Turn off terminal echo as not get messages back, among other things
- termInfo.c_cflag |= CREAD|CLOCAL;
- termInfo.c_cc[VTIME] = 0;
- termInfo.c_lflag &= (~(ICANON|ECHO|ECHOE|ECHOK|ECHONL|ISIG));
- termInfo.c_iflag &= (~(INPCK|IGNPAR|PARMRK|ISTRIP|ICRNL|IXANY|IXON|IXOFF));
- 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->portHandle, TCSAFLUSH, &termInfo) < 0) {
- setErrorString(tr("Unable to apply terminal settings to port %1: %2 (POSIX error %3)").
- arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno));
- close();
- return false;
- }
-
- d->readNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Read);
- connect(d->readNotifier, SIGNAL(activated(int)), this, SIGNAL(readyRead()));
-
- d->writeUnblockedNotifier = new QSocketNotifier(d->portHandle, QSocketNotifier::Write);
- d->writeUnblockedNotifier->setEnabled(false);
- connect(d->writeUnblockedNotifier, SIGNAL(activated(int)), this, SLOT(writeHasUnblocked(int)));
-
- bool ok = QIODevice::open(mode | QIODevice::Unbuffered);
- if (!ok) close();
- return ok;
-}
-
-void VirtualSerialDevice::platClose()
-{
- delete d->readNotifier;
- d->readNotifier = NULL;
-
- delete d->writeUnblockedNotifier;
- d->writeUnblockedNotifier = NULL;
-
- ::close(d->portHandle);
- d->portHandle = -1;
-}
-
-VirtualSerialDevice::~VirtualSerialDevice()
-{
- close();
- delete d;
-}
-
-qint64 VirtualSerialDevice::bytesAvailable() const
-{
- QMutexLocker locker(&lock);
- if (!isOpen()) return 0;
-
- int avail = 0;
- d->readNotifier->setEnabled(false);
- int res = ioctl(d->portHandle, FIONREAD, &avail);
- d->readNotifier->setEnabled(true);
- if (res == -1) {
- return 0;
- }
- return (qint64)avail + QIODevice::bytesAvailable();
-}
-
-qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize)
-{
- QMutexLocker locker(&lock);
- d->readNotifier->setEnabled(false);
- int result = ::read(d->portHandle, data, maxSize);
- d->readNotifier->setEnabled(true);
- if (result == -1 && errno == EAGAIN)
- result = 0; // To Qt, 0 here means nothing ready right now, and -1 is reserved for permanent errors
- return result;
-}
-
-qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize)
-{
- QMutexLocker locker(&lock);
- qint64 bytesWritten;
- bool needToWait = tryFlushPendingBuffers(locker, EmitBytesWrittenAsync);
- if (!needToWait) {
- needToWait = tryWrite(data, maxSize, bytesWritten);
- if (needToWait && bytesWritten > 0) {
- // Wrote some of the buffer, adjust pointers to point to the remainder that needs queueing
- data += bytesWritten;
- maxSize -= bytesWritten;
- }
- }
-
- if (needToWait) {
- pendingWrites.append(QByteArray(data, maxSize));
- d->writeUnblockedNotifier->setEnabled(true);
- // Now wait for the writeUnblocked signal or for a call to waitForBytesWritten
- return bytesWritten + maxSize;
- } else {
- //emitBytesWrittenIfNeeded(locker, bytesWritten);
- // Can't emit bytesWritten directly from writeData - means clients end up recursing
- emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
- return bytesWritten;
- }
-}
-
-/* Returns true if EAGAIN encountered.
- * if error occurred (other than EAGAIN) returns -1 in bytesWritten
- * lock must be held. Doesn't emit signals or set notifiers.
- */
-bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& bytesWritten)
-{
- // Must be locked
- bytesWritten = 0;
- while (maxSize > 0) {
- int result = ::write(d->portHandle, data, maxSize);
- if (result == -1) {
- if (errno == EAGAIN)
- return true; // Need to wait
- setErrorString(tr("Cannot write to port %1: %2 (POSIX error %3)").
- arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno));
-
- bytesWritten = -1;
- return false;
- } else {
- if (result == 0)
- qWarning("%s: Zero bytes written to port %s!", Q_FUNC_INFO, qPrintable(portName));
- bytesWritten += result;
- maxSize -= result;
- data += result;
- }
- }
- return false; // If we reach here we've successfully written all the data without blocking
-}
-
-/* Returns true if EAGAIN encountered. Emits (or queues) bytesWritten for any buffers written.
- * If stopAfterWritingOneBuffer is true, return immediately if a single buffer is written, rather than
- * attempting to drain the whole queue.
- * Doesn't modify notifier.
- */
-bool VirtualSerialDevice::tryFlushPendingBuffers(QMutexLocker& locker, FlushPendingOptions flags)
-{
- while (pendingWrites.count() > 0) {
- // Try writing everything we've got, until we hit EAGAIN
- const QByteArray& data = pendingWrites[0];
- qint64 bytesWritten;
- bool needToWait = tryWrite(data.constData(), data.size(), bytesWritten);
- if (needToWait) {
- if (bytesWritten > 0) {
- // We wrote some of the data, update the pending queue
- QByteArray remainder = data.mid(bytesWritten);
- pendingWrites.removeFirst();
- pendingWrites.insert(0, remainder);
- }
- return needToWait;
- } else {
- pendingWrites.removeFirst();
- if (flags & EmitBytesWrittenAsync) {
- emit AsyncCall_emitBytesWrittenIfNeeded(bytesWritten);
- } else {
- emitBytesWrittenIfNeeded(locker, bytesWritten);
- }
- if (flags & StopAfterWritingOneBuffer) return false;
- // Otherwise go round loop again
- }
- }
- return false; // no EAGAIN encountered
-}
-
-void VirtualSerialDevice::writeHasUnblocked(int fileHandle)
-{
- Q_ASSERT(fileHandle == d->portHandle);
- (void)fileHandle; // Compiler shutter-upper
- d->writeUnblockedNotifier->setEnabled(false);
-
- QMutexLocker locker(&lock);
- bool needToWait = tryFlushPendingBuffers(locker);
- if (needToWait) d->writeUnblockedNotifier->setEnabled(true);
-}
-
-// Copy of qt_safe_select from /qt/src/corelib/kernel/qeventdispatcher_unix.cpp
-// But without the timeout correction
-int safe_select(int nfds, fd_set *fdread, fd_set *fdwrite, fd_set *fdexcept,
- const struct timeval *orig_timeout)
-{
- if (!orig_timeout) {
- // no timeout -> block forever
- register int ret;
- do {
- ret = select(nfds, fdread, fdwrite, fdexcept, 0);
- } while (ret == -1 && errno == EINTR);
- return ret;
- }
-
- timeval timeout = *orig_timeout;
-
- int ret;
- forever {
- ret = ::select(nfds, fdread, fdwrite, fdexcept, &timeout);
- if (ret != -1 || errno != EINTR)
- return ret;
- }
-}
-
-bool VirtualSerialDevice::waitForBytesWritten(int msecs)
-{
- QMutexLocker locker(&lock);
- if (pendingWrites.count() == 0) return false;
-
- if (QThread::currentThread() != thread()) {
- // Wait for signal from main thread
- unsigned long timeout = msecs;
- if (msecs == -1) timeout = ULONG_MAX;
- if (waiterForBytesWritten == NULL)
- waiterForBytesWritten = new QWaitCondition;
- return waiterForBytesWritten->wait(&lock, timeout);
- }
-
- d->writeUnblockedNotifier->setEnabled(false);
- forever {
- fd_set writeSet;
- FD_ZERO(&writeSet);
- FD_SET(d->portHandle, &writeSet);
-
- struct timeval timeout;
- if (msecs != -1) {
- timeout.tv_sec = msecs / 1000;
- timeout.tv_usec = (msecs % 1000) * 1000;
- }
- int ret = safe_select(d->portHandle+1, NULL, &writeSet, NULL, msecs == -1 ? NULL : &timeout);
-
- if (ret == 0) {
- // Timeout
- return false;
- } else if (ret < 0) {
- setErrorString(tr("The function select() returned an error on port %1: %2 (POSIX error %3)").
- arg(portName, QString::fromLocal8Bit(strerror(errno))).arg(errno));
- return false;
- } else {
- bool needToWait = tryFlushPendingBuffers(locker, StopAfterWritingOneBuffer);
- if (needToWait) {
- // go round the select again
- } else {
- return true;
- }
- }
- }
-}
-
-void VirtualSerialDevice::flush()
-{
- while (waitForBytesWritten(-1)) { /* loop */ }
- tcflush(d->portHandle, TCIOFLUSH);
-}
-
-bool VirtualSerialDevice::waitForReadyRead(int msecs)
-{
- return QIODevice::waitForReadyRead(msecs); //TODO
-}
-
-} // namespace SymbianUtils
diff --git a/src/shared/symbianutils/virtualserialdevice_win.cpp b/src/shared/symbianutils/virtualserialdevice_win.cpp
deleted file mode 100644
index de528d7c89..0000000000
--- a/src/shared/symbianutils/virtualserialdevice_win.cpp
+++ /dev/null
@@ -1,362 +0,0 @@
-/**************************************************************************
-**
-** This file is part of Qt Creator
-**
-** Copyright (c) 2012 Nokia Corporation and/or its subsidiary(-ies).
-**
-** Contact: http://www.qt-project.org/
-**
-**
-** GNU Lesser General Public License Usage
-**
-** 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.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** Other Usage
-**
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**************************************************************************/
-
-#include "virtualserialdevice.h"
-#include <windows.h>
-#if QT_VERSION >= 0x050000
-# include <QWinEventNotifier>
-#else
-# include <private/qwineventnotifier_p.h>
-#endif
-#include <QThread>
-#include <QWaitCondition>
-
-namespace SymbianUtils {
-
-class VirtualSerialDevicePrivate
-{
-public:
- HANDLE portHandle;
- OVERLAPPED writeOverlapped;
- OVERLAPPED commEventOverlapped;
- DWORD commEventMask;
- QWinEventNotifier *writeCompleteNotifier;
- QWinEventNotifier *commEventNotifier;
-};
-
-void VirtualSerialDevice::platInit()
-{
- d = new VirtualSerialDevicePrivate;
- d->portHandle = INVALID_HANDLE_VALUE;
- d->writeCompleteNotifier = NULL;
- memset(&d->writeOverlapped, 0, sizeof(OVERLAPPED));
- d->commEventNotifier = NULL;
- memset(&d->commEventOverlapped, 0, sizeof(OVERLAPPED));
-}
-
-QString windowsPortName(const QString& port)
-{
- // Add the \\.\ to the name if it's a COM port and doesn't already have it
- QString winPortName(port);
- if (winPortName.startsWith(QLatin1String("COM"))) {
- winPortName.prepend("\\\\.\\");
- }
- return winPortName;
-}
-
-// Copied from \creator\src\libs\utils\winutils.cpp
-QString winErrorMessage(unsigned long error)
-{
- // Some of the windows error messages are a bit too obscure
- switch (error)
- {
- case ERROR_FILE_NOT_FOUND:
- case ERROR_NOT_FOUND:
- return VirtualSerialDevice::tr("Port not found");
- break;
- case ERROR_ACCESS_DENIED:
- return VirtualSerialDevice::tr("Port in use");
- case ERROR_SEM_TIMEOUT: // Bluetooth ports sometimes return this
- return VirtualSerialDevice::tr("Timed out");
- case ERROR_NETWORK_UNREACHABLE:
- return VirtualSerialDevice::tr("Port unreachable"); // I don't know what this error indicates... from observation, that the windows Bluetooth stack has got itself into a state and needs resetting
- default:
- break;
- }
-
- 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.trimmed();
-}
-
-bool VirtualSerialDevice::open(OpenMode mode)
-{
- Q_ASSERT(QThread::currentThread() == thread());
- if (isOpen()) return true;
-
- d->portHandle = CreateFileA(windowsPortName(portName).toAscii(), GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
- if (d->portHandle == INVALID_HANDLE_VALUE) {
- setErrorString(tr("The port %1 could not be opened: %2").
- arg(portName, winErrorMessage(GetLastError())));
- return false;
- }
-
- DCB commState;
- memset(&commState, 0, sizeof(DCB));
- commState.DCBlength = sizeof(DCB);
- bool ok = GetCommState(d->portHandle, &commState);
- if (ok) {
- commState.BaudRate = CBR_115200;
- commState.fBinary = TRUE;
- commState.fParity = FALSE;
- commState.fOutxCtsFlow = FALSE;
- commState.fOutxDsrFlow = FALSE;
- commState.fInX = FALSE;
- commState.fOutX = FALSE;
- commState.fNull = FALSE;
- commState.fAbortOnError = FALSE;
- commState.fDsrSensitivity = FALSE;
- commState.fDtrControl = DTR_CONTROL_DISABLE;
- commState.ByteSize = 8;
- commState.Parity = NOPARITY;
- commState.StopBits = ONESTOPBIT;
- ok = SetCommState(d->portHandle, &commState);
- }
- if (!ok) {
- qWarning("%s setting comm state", qPrintable(winErrorMessage(GetLastError())));
- }
-
- // http://msdn.microsoft.com/en-us/library/aa363190(v=vs.85).aspx says this means
- // "the read operation is to return immediately with the bytes that have already been received, even if no bytes have been received"
- COMMTIMEOUTS timeouts;
- timeouts.ReadIntervalTimeout = MAXDWORD;
- timeouts.ReadTotalTimeoutMultiplier = 0;
- timeouts.ReadTotalTimeoutConstant = 0;
- timeouts.WriteTotalTimeoutMultiplier = 0;
- timeouts.WriteTotalTimeoutConstant = 0;
- SetCommTimeouts(d->portHandle, &timeouts);
-
- d->writeOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- d->writeCompleteNotifier = new QWinEventNotifier(d->writeOverlapped.hEvent, this);
- connect(d->writeCompleteNotifier, SIGNAL(activated(HANDLE)), this, SLOT(writeCompleted()));
-
- // This is how we implement readyRead notifications
- d->commEventOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- d->commEventNotifier = new QWinEventNotifier(d->commEventOverlapped.hEvent, this);
- connect(d->commEventNotifier, SIGNAL(activated(HANDLE)), this, SLOT(commEventOccurred()));
-
- if (!SetCommMask(d->portHandle, EV_RXCHAR)) {
- // What to do?
- qWarning("%s: Could not set comm mask, err=%d", Q_FUNC_INFO, (int)GetLastError());
- }
- bool result = WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped);
- Q_ASSERT(result == false); // Can't see how it would make sense to be anything else...
- (void)result; // For release build
- if (GetLastError() != ERROR_IO_PENDING) {
- setErrorString(tr("An error occurred while waiting for read notifications from %1: %2").
- arg(portName, winErrorMessage(GetLastError())));
- close();
- return false;
- }
-
- ok = QIODevice::open(mode);
- if (!ok) close();
- return ok;
-}
-
-void VirtualSerialDevice::platClose()
-{
- delete d->writeCompleteNotifier;
- d->writeCompleteNotifier = NULL;
- CloseHandle(d->writeOverlapped.hEvent);
- d->writeOverlapped.hEvent = INVALID_HANDLE_VALUE;
-
- delete d->commEventNotifier;
- d->commEventNotifier = NULL;
- d->commEventOverlapped.hEvent = INVALID_HANDLE_VALUE;
-
- CloseHandle(d->portHandle);
- d->portHandle = INVALID_HANDLE_VALUE;
-}
-
-VirtualSerialDevice::~VirtualSerialDevice()
-{
- close();
- delete d;
-}
-
-qint64 VirtualSerialDevice::bytesAvailable() const
-{
- QMutexLocker locker(&lock);
- if (!isOpen()) return 0;
-
- qint64 avail = 0;
- COMSTAT Status;
- if (ClearCommError(d->portHandle, NULL, &Status)) {
- avail = Status.cbInQue;
- }
- return avail + QIODevice::bytesAvailable();
-}
-
-void VirtualSerialDevice::commEventOccurred()
-{
- DWORD event = d->commEventMask;
- if (event & EV_RXCHAR) {
- emit readyRead();
- }
- ResetEvent(d->commEventOverlapped.hEvent);
- WaitCommEvent(d->portHandle, &d->commEventMask, &d->commEventOverlapped);
-}
-
-qint64 VirtualSerialDevice::readData(char *data, qint64 maxSize)
-{
- QMutexLocker locker(&lock);
- // We do our reads synchronously
- OVERLAPPED readOverlapped;
- memset(&readOverlapped, 0, sizeof(OVERLAPPED));
- DWORD bytesRead;
- BOOL done = ReadFile(d->portHandle, data, maxSize, &bytesRead, &readOverlapped);
- if (done) return (qint64)bytesRead;
-
- if (GetLastError() == ERROR_IO_PENDING) {
- // Note the TRUE to wait for the read to complete
- done = GetOverlappedResult(d->portHandle, &readOverlapped, &bytesRead, TRUE);
- if (done) return (qint64)bytesRead;
- }
-
- // If we reach here an error has occurred
- setErrorString(tr("An error occurred while reading from %1: %2").
- arg(portName, winErrorMessage(GetLastError())));
- return -1;
-}
-
-
-qint64 VirtualSerialDevice::writeData(const char *data, qint64 maxSize)
-{
- QMutexLocker locker(&lock);
-
- pendingWrites.append(QByteArray(data, maxSize)); // Can't see a way of doing async io safely without having to copy here...
- if (pendingWrites.count() == 1) {
- return writeNextBuffer(locker);
- } else {
- return maxSize;
- }
-}
-
-qint64 VirtualSerialDevice::writeNextBuffer(QMutexLocker& locker)
-{
- Q_UNUSED(locker)
- // Must be locked on entry
- qint64 bufLen = pendingWrites[0].length();
- BOOL ok = WriteFile(d->portHandle, pendingWrites[0].constData(), bufLen, NULL, &d->writeOverlapped);
- if (ok || GetLastError() == ERROR_IO_PENDING) {
- // Apparently it can return true for a small asynchronous write...
- // Hopefully it still gets signalled in the same way!
-
- // Wait for signal via writeCompleted
- return bufLen;
- }
- else {
- setErrorString(tr("An error occurred while writing to %1: %2").
- arg(portName, winErrorMessage(GetLastError())));
- pendingWrites.removeFirst();
- return -1;
- }
-}
-
-void VirtualSerialDevice::writeCompleted()
-{
- QMutexLocker locker(&lock);
- if (pendingWrites.count() == 0) {
- qWarning("%s: writeCompleted called when there are no pending writes on %s!",
- Q_FUNC_INFO, qPrintable(portName));
- return;
- }
-
- doWriteCompleted(locker);
-}
-
-void VirtualSerialDevice::doWriteCompleted(QMutexLocker &locker)
-{
- // Must be locked on entry
- ResetEvent(d->writeOverlapped.hEvent);
-
- qint64 len = pendingWrites.first().length();
- pendingWrites.removeFirst();
-
- if (pendingWrites.count() > 0) {
- // Get the next write started before notifying in case client calls waitForBytesWritten in their slot
- writeNextBuffer(locker);
- }
-
- emitBytesWrittenIfNeeded(locker, len);
-}
-
-bool VirtualSerialDevice::waitForBytesWritten(int msecs)
-{
- QMutexLocker locker(&lock);
- if (pendingWrites.count() == 0) return false;
-
- if (QThread::currentThread() != thread()) {
- // Wait for signal from main thread
- unsigned long timeout = msecs;
- if (msecs == -1) timeout = ULONG_MAX;
- if (waiterForBytesWritten == NULL)
- waiterForBytesWritten = new QWaitCondition;
- return waiterForBytesWritten->wait(&lock, timeout);
- }
-
- DWORD waitTime = msecs;
- if (msecs == -1) waitTime = INFINITE; // Ok these are probably bitwise the same, but just to prove I've thought about it...
- DWORD result = WaitForSingleObject(d->writeOverlapped.hEvent, waitTime); // Do I need WaitForSingleObjectEx and worry about alertable states?
- if (result == WAIT_TIMEOUT) {
- return false;
- }
- else if (result == WAIT_OBJECT_0) {
- DWORD bytesWritten;
- BOOL ok = GetOverlappedResult(d->portHandle, &d->writeOverlapped, &bytesWritten, TRUE);
- if (!ok) {
- setErrorString(tr("An error occurred while syncing on waitForBytesWritten for %1: %2").
- arg(portName, winErrorMessage(GetLastError())));
- return false;
- }
- Q_ASSERT(bytesWritten == (DWORD)pendingWrites.first().length());
-
- doWriteCompleted(locker);
- return true;
- }
- else {
- setErrorString(QString("An error occurred in waitForBytesWritten() for %1: %2").
- arg(portName, winErrorMessage(GetLastError())));
- return false;
- }
-}
-
-void VirtualSerialDevice::flush()
-{
- while (waitForBytesWritten(-1)) { /* loop */ }
-}
-
-bool VirtualSerialDevice::waitForReadyRead(int msecs)
-{
- return QIODevice::waitForReadyRead(msecs); //TODO
-}
-
-} // namespace SymbianUtils