OSDN Git Service

Sharing TcfTrkDevice connections between multiple clients
authorTom Sutcliffe <ext-thomas.1.sutcliffe@nokia.com>
Mon, 7 Feb 2011 13:14:57 +0000 (14:14 +0100)
committerPawel Polanski <pawel.3.polanski@nokia.com>
Tue, 8 Feb 2011 08:18:45 +0000 (09:18 +0100)
src/plugins/debugger/gdb/codagdbadapter.cpp
src/plugins/debugger/gdb/codagdbadapter.h
src/plugins/qt4projectmanager/qt-s60/codaruncontrol.cpp
src/plugins/qt4projectmanager/qt-s60/s60deploystep.cpp
src/shared/symbianutils/codadevice.cpp
src/shared/symbianutils/codadevice.h
src/shared/symbianutils/symbiandevicemanager.cpp
src/shared/symbianutils/symbiandevicemanager.h
src/shared/symbianutils/virtualserialdevice_posix.cpp

index 3792be5..31ba90e 100644 (file)
@@ -37,7 +37,7 @@
 #include "codadevice.h"
 #include "trkutils.h"
 #include "gdbmi.h"
-#include "virtualserialdevice.h"
+#include "symbiandevicemanager.h"
 
 #include "registerhandler.h"
 #include "threadshandler.h"
@@ -123,7 +123,6 @@ CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
     AbstractGdbAdapter(engine),
     m_running(false),
     m_stopReason(0),
-    m_trkDevice(new CodaDevice(this)),
     m_gdbAckMode(true),
     m_uid(0),
     m_verbose(0),
@@ -148,11 +147,15 @@ CodaGdbAdapter::CodaGdbAdapter(GdbEngine *engine) :
 
     connect(debuggerCore()->action(VerboseLog), SIGNAL(valueChanged(QVariant)),
         this, SLOT(setVerbose(QVariant)));
-    connect(m_trkDevice, SIGNAL(error(QString)),
+}
+
+void CodaGdbAdapter::setupTrkDeviceSignals()
+{
+    connect(m_codaDevice.data(), SIGNAL(error(QString)),
         this, SLOT(codaDeviceError(QString)));
-    connect(m_trkDevice, SIGNAL(logMessage(QString)),
+    connect(m_codaDevice.data(), SIGNAL(logMessage(QString)),
         this, SLOT(trkLogMessage(QString)));
-    connect(m_trkDevice, SIGNAL(tcfEvent(Coda::CodaEvent)),
+    connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)),
         this, SLOT(codaEvent(Coda::CodaEvent)));
 }
 
@@ -172,7 +175,8 @@ void CodaGdbAdapter::setVerbose(int verbose)
     if (debug)
         qDebug("CodaGdbAdapter::setVerbose %d", verbose);
     m_verbose = verbose;
-    m_trkDevice->setVerbose(m_verbose);
+    if (m_codaDevice)
+        m_codaDevice->setVerbose(m_verbose);
 }
 
 void CodaGdbAdapter::trkLogMessage(const QString &msg)
@@ -278,7 +282,7 @@ void CodaGdbAdapter::handleCodaRunControlModuleLoadContextSuspendedEvent(const C
                 qDebug() << "Initial module load suspended: " << m_session.toString();
         } else {
             // Consecutive module load suspended: (not observed yet): Just continue
-            m_trkDevice->sendRunControlResumeCommand(CodaCallback(), se.id());
+            m_codaDevice->sendRunControlResumeCommand(CodaCallback(), se.id());
         }
     }
 }
@@ -305,7 +309,7 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
 
     switch (e.type()) {
     case CodaEvent::LocatorHello:
-        m_trkDevice->sendLoggingAddListenerCommand(CodaCallback());
+        m_codaDevice->sendLoggingAddListenerCommand(CodaCallback());
         startGdb(); // Commands are only accepted after hello
         break;
     case CodaEvent::RunControlModuleLoadSuspended: // A module was loaded
@@ -349,7 +353,7 @@ void CodaGdbAdapter::codaEvent(const CodaEvent &e)
             m_stopReason = reason.contains(QLatin1String("exception"), Qt::CaseInsensitive)
                            || reason.contains(QLatin1String("panic"), Qt::CaseInsensitive) ?
                            gdbServerSignalSegfault : gdbServerSignalTrap;
-            m_trkDevice->sendRegistersGetMRangeCommand(
+            m_codaDevice->sendRegistersGetMRangeCommand(
                 CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegistersAfterStop),
                 currentThreadContextId(), 0,
                 Symbian::RegisterCount);
@@ -604,7 +608,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
             reportRegisters();
         } else {
             sendGdbServerAck();
-            if (m_trkDevice->registerNames().isEmpty()) {
+            if (m_codaDevice->registerNames().isEmpty()) {
                 m_registerRequestPending = true;
             } else {
                 sendRegistersGetMCommand();
@@ -688,7 +692,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
         logMessage(_("Writing %1 bytes from 0x%2: %3").
                    arg(addrLength.second).arg(addrLength.first, 0, 16).
                    arg(QString::fromAscii(data.toHex())));
-        m_trkDevice->sendMemorySetCommand(
+        m_codaDevice->sendMemorySetCommand(
             CodaCallback(this, &CodaGdbAdapter::handleWriteMemory),
             m_tcfProcessId, addrLength.first, data);
     }
@@ -707,7 +711,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
             sendGdbServerMessage(thread.gdbReportSingleRegister(registerNumber), thread.gdbSingleRegisterLogMessage(registerNumber));
         } else {
             //qDebug() << "Fetching single register";
-            m_trkDevice->sendRegistersGetMRangeCommand(
+            m_codaDevice->sendRegistersGetMRangeCommand(
                 CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegister),
                 currentThreadContextId(), registerNumber, 1);
         }
@@ -723,7 +727,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
         logMessage(_("Setting register #%1 to 0x%2").arg(regnumValue.first).arg(regnumValue.second, 0, 16));
         QByteArray registerValue;
         trk::appendInt(&registerValue, trk::BigEndian); // Registers are big endian
-        m_trkDevice->sendRegistersSetCommand(
+        m_codaDevice->sendRegistersSetCommand(
             CodaCallback(this, &CodaGdbAdapter::handleWriteRegister),
             currentThreadContextId(), regnumValue.first, registerValue,
             QVariant(regnumValue.first));
@@ -899,7 +903,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
             bp.setContextId(m_session.pid);
             // We use the automatic ids calculated from the location
             // address instead of the map in snapshot.
-            m_trkDevice->sendBreakpointsAddCommand(
+            m_codaDevice->sendBreakpointsAddCommand(
                 CodaCallback(this, &CodaGdbAdapter::handleAndReportSetBreakpoint),
                 bp);
         } else {
@@ -914,7 +918,7 @@ void CodaGdbAdapter::handleGdbServerCommand(const QByteArray &cmd)
         // $z0,786a4ccc,4#99
         const int pos = cmd.lastIndexOf(',');
         const uint addr = cmd.mid(3, pos - 3).toUInt(0, 16);
-        m_trkDevice->sendBreakpointsRemoveCommand(
+        m_codaDevice->sendBreakpointsRemoveCommand(
             CodaCallback(this, &CodaGdbAdapter::handleClearBreakpoint),
             Coda::Breakpoint::idFromLocation(addr));
     }
@@ -960,7 +964,7 @@ void CodaGdbAdapter::sendRunControlTerminateCommand()
     // Requires id of main thread to terminate.
     // Note that calling 'Settings|set|removeExecutable' crashes TCF TRK,
     // so, it is apparently not required.
-    m_trkDevice->sendRunControlTerminateCommand(CodaCallback(this, &CodaGdbAdapter::handleRunControlTerminate),
+    m_codaDevice->sendRunControlTerminateCommand(CodaCallback(this, &CodaGdbAdapter::handleRunControlTerminate),
                                                 mainThreadContextId());
 }
 
@@ -993,7 +997,7 @@ void CodaGdbAdapter::gdbSetCurrentThread(const QByteArray &cmd, const char *why)
 
 void CodaGdbAdapter::interruptInferior()
 {
-    m_trkDevice->sendRunControlSuspendCommand(CodaCallback(), m_tcfProcessId);
+    m_codaDevice->sendRunControlSuspendCommand(CodaCallback(), m_tcfProcessId);
 }
 
 void CodaGdbAdapter::startAdapter()
@@ -1015,22 +1019,25 @@ void CodaGdbAdapter::startAdapter()
 
     QSharedPointer<QTcpSocket> codaSocket;
     if (parameters.communicationChannel == DebuggerStartParameters::CommunicationChannelTcpIp) {
+        m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
+        setupTrkDeviceSignals();
         codaSocket = QSharedPointer<QTcpSocket>(new QTcpSocket);
-        m_trkDevice->setDevice(codaSocket);
+        m_codaDevice->setDevice(codaSocket);
         m_trkIODevice = codaSocket;
     } else {
-        QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(parameters.remoteChannel));
-        m_trkDevice->setSerialFrame(true);
-        m_trkDevice->setDevice(serialDevice);
-        bool ok = serialDevice->open(QIODevice::ReadWrite);
+        m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(parameters.remoteChannel);
+        bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
+
         if (!ok) {
-            QString msg = QString("Couldn't open serial device: %1.")
-                .arg(serialDevice->errorString());
+            QString msg = QString("Couldn't open serial device %1").arg(parameters.remoteChannel);
+            if (m_codaDevice)
+                msg.append(QString(": %1").arg(m_codaDevice->device()->errorString()));
             logMessage(msg, LogError);
             m_engine->handleAdapterStartFailed(msg, QString());
             return;
         }
-        m_trkIODevice = serialDevice;
+        setupTrkDeviceSignals();
+        m_codaDevice->setVerbose(m_verbose);
     }
 
     if (debug)
@@ -1071,7 +1078,7 @@ void CodaGdbAdapter::startAdapter()
                    .arg(codaAddress.first).arg(codaAddress.second));
         codaSocket->connectToHost(codaAddress.first, codaAddress.second);
     } else {
-        m_trkDevice->sendSerialPing(false);
+        m_codaDevice->sendSerialPing(false);
     }
 }
 
@@ -1085,7 +1092,7 @@ void CodaGdbAdapter::setupInferior()
     for (unsigned i = 0; i < libraryCount; i++)
         libraries.push_back(QString::fromAscii(librariesC[i]));
 
-    m_trkDevice->sendProcessStartCommand(
+    m_codaDevice->sendProcessStartCommand(
         CodaCallback(this, &CodaGdbAdapter::handleCreateProcess),
         m_remoteExecutable, m_uid, m_remoteArguments,
         QString(), true, libraries);
@@ -1105,7 +1112,7 @@ void CodaGdbAdapter::addThread(unsigned id)
         // We cannot retrieve register values unless the registers of that
         // thread have been retrieved (TCF TRK oddity).
         const QByteArray contextId = Coda::RunControlContext::tcfId(m_session.pid, id);
-        m_trkDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
+        m_codaDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
                                                      contextId, QVariant(contextId));
     }
 }
@@ -1197,6 +1204,10 @@ void CodaGdbAdapter::cleanup()
             }
         }
     } //!m_trkIODevice.isNull()
+    if (m_codaDevice) {
+        disconnect(m_codaDevice.data(), 0, this, 0);
+        SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
+    }
 }
 
 void CodaGdbAdapter::shutdownInferior()
@@ -1211,7 +1222,7 @@ void CodaGdbAdapter::shutdownAdapter()
         m_engine->notifyAdapterShutdownOk();
     } else {
         // Something is wrong, gdb crashed. Kill debuggee (see handleDeleteProcess2)
-        if (m_trkDevice->device()->isOpen()) {
+        if (m_codaDevice->device()->isOpen()) {
             logMessage("Emergency shutdown of CODA", LogError);
             sendRunControlTerminateCommand();
         }
@@ -1244,9 +1255,9 @@ void CodaGdbAdapter::handleWriteRegister(const CodaCommandResult &result)
 void CodaGdbAdapter::sendRegistersGetMCommand()
 {
     // Send off a register command, which requires the names to be present.
-    QTC_ASSERT(!m_trkDevice->registerNames().isEmpty(), return )
+    QTC_ASSERT(!m_codaDevice->registerNames().isEmpty(), return )
 
-    m_trkDevice->sendRegistersGetMRangeCommand(
+    m_codaDevice->sendRegistersGetMRangeCommand(
                 CodaCallback(this, &CodaGdbAdapter::handleAndReportReadRegisters),
                 currentThreadContextId(), 0,
                 Symbian::RegisterCount);
@@ -1273,12 +1284,12 @@ void CodaGdbAdapter::handleRegisterChildren(const Coda::CodaCommandResult &resul
     // able to access the register contents.
     QVector<QByteArray> registerNames = Coda::CodaDevice::parseRegisterGetChildren(result);
     if (registerNames.size() == 1) {
-        m_trkDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
+        m_codaDevice->sendRegistersGetChildrenCommand(CodaCallback(this, &CodaGdbAdapter::handleRegisterChildren),
                                                      registerNames.front(), result.cookie);
         return;
     }
     // First thread: Set base names in device.
-    if (!m_trkDevice->registerNames().isEmpty())
+    if (!m_codaDevice->registerNames().isEmpty())
         return;
     // Make sure we get all registers
     const int registerCount = registerNames.size();
@@ -1297,7 +1308,7 @@ void CodaGdbAdapter::handleRegisterChildren(const Coda::CodaCommandResult &resul
         msg += QString::fromAscii(registerNames[i]);
     }
     logMessage(msg);
-    m_trkDevice->setRegisterNames(registerNames);
+    m_codaDevice->setRegisterNames(registerNames);
     if (m_registerRequestPending) { // Request already pending?
         logMessage(_("Resuming registers request after receiving register names..."));
         sendRegistersGetMCommand();
@@ -1425,7 +1436,7 @@ void CodaGdbAdapter::sendMemoryGetCommand(const MemoryRange &range, bool buffere
     const CodaCallback cb = buffered ?
       CodaCallback(this, &CodaGdbAdapter::handleReadMemoryBuffered) :
       CodaCallback(this, &CodaGdbAdapter::handleReadMemoryUnbuffered);
-    m_trkDevice->sendMemoryGetCommand(cb, currentThreadContextId(), range.from, range.size(), cookie);
+    m_codaDevice->sendMemoryGetCommand(cb, currentThreadContextId(), range.from, range.size(), cookie);
 }
 
 void CodaGdbAdapter::handleReadMemoryBuffered(const CodaCommandResult &result)
@@ -1563,7 +1574,7 @@ void CodaGdbAdapter::sendTrkContinue()
     // at the next stop.
     if (m_snapshot.threadInfo.size() > 1)
         m_snapshot.threadInfo.remove(1, m_snapshot.threadInfo.size() - 1);
-    m_trkDevice->sendRunControlResumeCommand(CodaCallback(), m_tcfProcessId);
+    m_codaDevice->sendRunControlResumeCommand(CodaCallback(), m_tcfProcessId);
 }
 
 void CodaGdbAdapter::sendTrkStepRange()
@@ -1586,7 +1597,7 @@ void CodaGdbAdapter::sendTrkStepRange()
 
     logMessage(_("Stepping from 0x%1 to 0x%2 (current PC=0x%3), mode %4").
                arg(from, 0, 16).arg(to, 0, 16).arg(pc).arg(int(mode)));
-    m_trkDevice->sendRunControlResumeCommand(
+    m_codaDevice->sendRunControlResumeCommand(
         CodaCallback(this, &CodaGdbAdapter::handleStep),
         currentThreadContextId(),
         mode, 1, from, to);
index 03fe9ca..2e0b030 100644 (file)
@@ -106,6 +106,7 @@ public:
     virtual DumperHandling dumperHandling() const { return DumperNotAvailable; }
 
 private:
+    void setupTrkDeviceSignals();
     void startAdapter();
     void setupInferior();
     void runEngine();
@@ -144,7 +145,8 @@ private:
     QString m_gdbServerName; // 127.0.0.1:(2222+uid)
     bool m_running;
     int m_stopReason;
-    Coda::CodaDevice *m_trkDevice;
+
+    QSharedPointer<Coda::CodaDevice> m_codaDevice;
     QSharedPointer<QIODevice> m_trkIODevice;
 
     //
index c751823..cc67ce2 100644 (file)
@@ -65,7 +65,7 @@ using namespace Qt4ProjectManager;
 using namespace Qt4ProjectManager::Internal;
 using namespace Coda;
 
-enum { debug = 1 };
+enum { debug = 0 };
 
 CodaRunControl::CodaRunControl(RunConfiguration *runConfiguration, const QString &mode) :
     S60RunControlBase(runConfiguration, mode),
@@ -115,35 +115,37 @@ bool CodaRunControl::setupLauncher()
         appendMessage(tr("Connecting to '%2'...").arg(m_serialPort), NormalMessageFormat);
         m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPort);
 
-        bool ok = m_codaDevice && m_tcfTrkDevice->device()->isOpen();
+        bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
         if (!ok) {
-            appendMessage(tr("Couldn't open serial device: %1").arg(m_tcfTrkDevice->device()->errorString()), ErrorMessageFormat);
+            appendMessage(tr("Couldn't open serial device: %1").arg(m_codaDevice->device()->errorString()), ErrorMessageFormat);
             return false;
         }
         connect(SymbianUtils::SymbianDeviceManager::instance(), SIGNAL(deviceRemoved(const SymbianUtils::SymbianDevice)),
                 this, SLOT(deviceRemoved(SymbianUtils::SymbianDevice)));
-        connect(m_tcfTrkDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString)));
-        connect(m_tcfTrkDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString)));
-        connect(m_tcfTrkDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
-        connect(m_tcfTrkDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
+        connect(m_codaDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString)));
+        connect(m_codaDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString)));
+        connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)));
+        connect(m_codaDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
         m_state = StateConnecting;
         m_codaDevice->sendSerialPing(false);
-        QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
     } else {
         // For TCP we don't use device manager, we just set it up directly
         m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
         connect(m_codaDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString)));
         connect(m_codaDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString)));
-        connect(m_codaDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)));
+        connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)));
 
         const QSharedPointer<QTcpSocket> codaSocket(new QTcpSocket);
         m_codaDevice->setDevice(codaSocket);
         codaSocket->connectToHost(m_address, m_port);
         m_state = StateConnecting;
         appendMessage(tr("Connecting to %1:%2...").arg(m_address).arg(m_port), NormalMessageFormat);
-        QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
+
     }
-    if (debug) m_tcfTrkDevice->setVerbose(1);
+    QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
+    if (debug)
+        m_codaDevice->setVerbose(debug);
+
     return true;
 }
 
index 15f4acb..a173b30 100644 (file)
@@ -314,9 +314,9 @@ void S60DeployStep::stop()
         if (m_launcher)
             m_launcher->terminate();
     } else {
-        if (m_trkDevice) {
-            disconnect(m_trkDevice.data(), 0, this, 0);
-            SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice);
+        if (m_codaDevice) {
+            disconnect(m_codaDevice.data(), 0, this, 0);
+            SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
         }
     }
     emit finished(false);
@@ -342,7 +342,7 @@ void S60DeployStep::setupConnections()
     } else {
         connect(m_codaDevice.data(), SIGNAL(error(QString)), this, SLOT(slotError(QString)));
         connect(m_codaDevice.data(), SIGNAL(logMessage(QString)), this, SLOT(slotTrkLogMessage(QString)));
-        connect(m_codaDevice.data(), SIGNAL(tcfEvent(tcftrk::TcfTrkEvent)), this, SLOT(slotTcftrkEvent(tcftrk::TcfTrkEvent)), Qt::DirectConnection);
+        connect(m_codaDevice.data(), SIGNAL(tcfEvent(Coda::CodaEvent)), this, SLOT(slotCodaEvent(Coda::CodaEvent)), Qt::DirectConnection);
         connect(m_codaDevice.data(), SIGNAL(serialPong(QString)), this, SLOT(slotSerialPong(QString)));
         connect(this, SIGNAL(manualInstallation()), this, SLOT(showManualInstallationInfo()));
     }
@@ -353,7 +353,7 @@ void S60DeployStep::startDeployment()
     if (m_channel == S60DeployConfiguration::CommunicationTrkSerialConnection) {
         QTC_ASSERT(m_launcher, return);
     }
-    QTC_ASSERT(!m_trkDevice.data(), return);
+    QTC_ASSERT(!m_codaDevice.data(), return);
 
     // We need to defer setupConnections() in the case of CommunicationCodaSerialConnection
     //setupConnections();
@@ -383,18 +383,19 @@ void S60DeployStep::startDeployment()
         }
     } else if (m_channel == S60DeployConfiguration::CommunicationCodaSerialConnection) {
         appendMessage(tr("Deploying application to '%1'...").arg(m_serialPortFriendlyName), false);
-        m_trkDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName);
-        bool ok = m_trkDevice && m_trkDevice->device()->isOpen();
+        m_codaDevice = SymbianUtils::SymbianDeviceManager::instance()->getTcfPort(m_serialPortName);
+        bool ok = m_codaDevice && m_codaDevice->device()->isOpen();
         if (!ok) {
             QString deviceError = tr("No such port");
-            if (m_trkDevice) deviceError = m_trkDevice->device()->errorString();
+            if (m_codaDevice)
+                deviceError = m_codaDevice->device()->errorString();
             reportError(tr("Couldn't open serial device: %1").arg(deviceError));
             stop();
             return;
         }
         setupConnections();
         m_state = StateConnecting;
-        m_trkDevice->sendSerialPing(false);
+        m_codaDevice->sendSerialPing(false);
         QTimer::singleShot(4000, this, SLOT(checkForTimeout()));
     } else {
         m_codaDevice = QSharedPointer<Coda::CodaDevice>(new Coda::CodaDevice);
@@ -439,9 +440,9 @@ void S60DeployStep::run(QFutureInterface<bool> &fi)
     delete m_timer;
     m_timer = 0;
 
-    if (m_trkDevice) {
-        disconnect(m_trkDevice.data(), 0, this, 0);
-        SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_trkDevice);
+    if (m_codaDevice) {
+        disconnect(m_codaDevice.data(), 0, this, 0);
+        SymbianUtils::SymbianDeviceManager::instance()->releaseTcfPort(m_codaDevice);
     }
 
     delete m_eventLoop;
@@ -499,7 +500,7 @@ void S60DeployStep::initFileSending()
 
     QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName());
     QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName);
-    m_trkDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemOpen),
+    m_codaDevice->sendFileSystemOpenCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemOpen),
                                            remoteFileLocation.toAscii(), flags);
     appendMessage(tr("Copying \"%1\"...").arg(packageName), false);
 }
@@ -512,11 +513,11 @@ void S60DeployStep::initFileInstallation()
     QString packageName(QFileInfo(m_signedPackages.at(m_currentFileIndex)).fileName());
     QString remoteFileLocation = QString::fromLatin1("%1:\\Data\\%2").arg(m_installationDrive).arg(packageName);
     if (m_silentInstall) {
-        m_trkDevice->sendSymbianInstallSilentInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
+        m_codaDevice->sendSymbianInstallSilentInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
                                                             remoteFileLocation.toAscii(), QString::fromLatin1("%1:").arg(m_installationDrive).toAscii());
         appendMessage(tr("Installing package \"%1\" on drive %2:...").arg(packageName).arg(m_installationDrive), false);
     } else {
-        m_trkDevice->sendSymbianInstallUIInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
+        m_codaDevice->sendSymbianInstallUIInstallCommand(Coda::CodaCallback(this, &S60DeployStep::handleSymbianInstall),
                                                         remoteFileLocation.toAscii());
         appendMessage(tr("Please continue the installation on your device."), false);
         emit manualInstallation();
@@ -588,7 +589,7 @@ void S60DeployStep::putSendNextChunk()
             qDebug("Writing %llu bytes to remote file '%s' at %llu\n",
                    m_putLastChunkSize,
                    m_remoteFileHandle.constData(), pos);
-        m_trkDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemWrite),
+        m_codaDevice->sendFileSystemWriteCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemWrite),
                                                 m_remoteFileHandle, data, unsigned(pos));
         setCopyProgress((100*(m_putLastChunkSize+pos))/size);
     }
@@ -596,7 +597,7 @@ void S60DeployStep::putSendNextChunk()
 
 void S60DeployStep::closeRemoteFile()
 {
-    m_trkDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemClose),
+    m_codaDevice->sendFileSystemCloseCommand(Coda::CodaCallback(this, &S60DeployStep::handleFileSystemClose),
                                             m_remoteFileHandle);
 }
 
index c01a798..a8a77d0 100644 (file)
@@ -43,7 +43,7 @@
 #include <QtCore/QDateTime>
 #include <QtCore/QFileInfo>
 
-enum { debug = 1 };
+enum { debug = 0 };
 
 static const char tcpMessageTerminatorC[] = "\003\001";
 
@@ -60,15 +60,18 @@ static const char locatorAnswerC[] = "E\0Locator\0Hello\0[\"Locator\"]";
 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)
+static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target, char protocolId)
 {
     target->append(char(0x01));
-    target->append(char(0x92)); // CODA serial message ID
+    target->append(protocolId);
     appendShort(target, ushort(data.size()), trk::BigEndian);
     target->append(data);
 }
@@ -76,14 +79,14 @@ static inline void encodeSerialFrame(const QByteArray &data, QByteArray *target)
 // Split in chunks of 1K according to CODA protocol chunking
 static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
 {
-     // Reserve 2 header bytes
+    // 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);
+        encodeSerialFrame(dataIn, &frame, codaProtocolId);
         return frame;
     }
     // Split.
@@ -102,7 +105,7 @@ static inline QByteArray encodeUsbSerialMessage(const QByteArray &dataIn)
         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);
+        encodeSerialFrame(chunk, &frame, codaProtocolId);
         pos = chunkEnd;
     }
     if (debug > 1)
@@ -471,26 +474,24 @@ void CodaDevice::slotDeviceReadyRead()
 
 // Find a serial header in input stream '0x1', '0x92', 'lenH', 'lenL'
 // and return message position and size.
-QPair<int, int> TcfTrkDevice::findSerialHeader(QByteArray &in)
+QPair<int, int> CodaDevice::findSerialHeader(QByteArray &in)
 {
-    const char header1 = 0x1;
-    const char header2 = char(0x92);
-    const char header2tracecore = char(0x91);
-    // Header should in theory always be at beginning of
+    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) == header2) {
+        if (in.at(0) == header1 && in.at(1) == codaProtocolId) {
             // Good packet
             const int length = trk::extractShort(in.constData() + 2);
             return QPair<int, int>(4, length);
-        } else if (in.at(0) == header1 && in.at(1) == header2tracecore) {
+        } else if (in.at(0) == header1 && in.at(1) >= validProtocolIdStart && in.at(1) <= validProtocolIdEnd) {
             // We recognise it but it's not a TCF message - emit it for any interested party to handle
             const int length = trk::extractShort(in.constData() + 2);
             if (4 + length <= in.size()) {
                 // We have all the data
                 QByteArray data(in.mid(4, length));
-                emit traceCoreEvent(data);
+                emit unknownEvent(in.at(1), data);
                 in.remove(0, 4+length);
                 // and continue
             } else {
@@ -504,7 +505,6 @@ QPair<int, int> TcfTrkDevice::findSerialHeader(QByteArray &in)
             QByteArray bad = in.mid(0, nextHeader);
             qWarning("Bogus data received on serial line: %s\n"
                      "Frame Header at: %d", qPrintable(trk::stringFromArray(bad)), nextHeader);
-            d->m_device->write(bad); // Backatcha - TOMSCI TESTING
             in.remove(0, bad.length());
             // and continue
         }
@@ -787,9 +787,6 @@ void CodaDevice::sendSerialPing(bool pingOnly)
     if (!checkOpen())
         return;
 
-    dumpObjectInfo();
-    d->m_device->dumpObjectInfo();
-
     d->m_serialPingOnly = pingOnly;
     setSerialFrame(true);
     writeMessage(QByteArray(serialPingC, qstrlen(serialPingC)), false);
@@ -869,6 +866,24 @@ void CodaDevice::writeMessage(QByteArray data, bool ensureTerminating0)
         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
index a52c8d8..f2e029b 100644 (file)
@@ -360,6 +360,8 @@ public:
     // 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);
@@ -367,7 +369,7 @@ public:
 signals:
     void genericTcfEvent(int service, const QByteArray &name, const QVector<JsonValue> &value);
     void tcfEvent(const Coda::CodaEvent &knownEvent);
-    void traceCoreEvent(const QByteArray& data);
+    void unknownEvent(uchar protocolId, const QByteArray& data);
     void serialPong(const QString &codaVersion);
 
     void logMessage(const QString &);
index 61c9761..c36bab9 100644 (file)
@@ -33,7 +33,7 @@
 
 #include "symbiandevicemanager.h"
 #include "trkdevice.h"
-#include "tcftrkdevice.h"
+#include "codadevice.h"
 #include "virtualserialdevice.h"
 
 #include <QtCore/QSettings>
@@ -73,7 +73,7 @@ public:
 
     DeviceCommunicationType type;
     QSharedPointer<trk::TrkDevice> device;
-    QSharedPointer<tcftrk::TcfTrkDevice> tcfdevice;
+    QSharedPointer<Coda::CodaDevice> codaDevice;
     bool deviceAcquired;
 };
 
@@ -85,14 +85,11 @@ SymbianDeviceData::SymbianDeviceData() :
 
 bool SymbianDeviceData::isOpen() const
 {
-    if (device) {
-        // TRK device
+    if (device)
         return device->isOpen();
-    } else if (tcfdevice) {
-        return tcfdevice->device()->isOpen();
-    } else {
-        return false;
-    }
+    if (codaDevice)
+        return codaDevice->device()->isOpen();
+    return false;
 }
 
 SymbianDeviceData::~SymbianDeviceData()
@@ -110,8 +107,10 @@ void SymbianDeviceData::forcedClose()
         if (deviceAcquired)
             qWarning("Device on '%s' unplugged while an operation is in progress.",
                      qPrintable(portName));
-        if (device) device->close();
-        else tcfdevice->device()->close();
+        if (device)
+            device->close();
+        else
+            codaDevice->device()->close();
     }
 }
 
@@ -278,12 +277,12 @@ struct SymbianDeviceManagerPrivate {
 class QConstructTcfPortEvent : public QEvent
 {
 public:
-    QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, TcfTrkDevicePtr *device, QWaitCondition *waiter) :
+    QConstructTcfPortEvent(QEvent::Type eventId, const QString &portName, CodaDevicePtr *device, QWaitCondition *waiter) :
         QEvent(eventId), m_portName(portName), m_device(device), m_waiter(waiter)
        {}
 
     QString m_portName;
-    TcfTrkDevicePtr* m_device;
+    CodaDevicePtr* m_device;
     QWaitCondition *m_waiter;
 };
 
@@ -353,7 +352,7 @@ SymbianDeviceManager::TrkDevicePtr
     return rc;
 }
 
-TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port)
+CodaDevicePtr SymbianDeviceManager::getTcfPort(const QString &port)
 {
     ensureInitialized();
     const int idx = findByPortName(port);
@@ -361,16 +360,16 @@ TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port)
         qWarning("Attempt to acquire device '%s' that does not exist.", qPrintable(port));
         if (debug)
             qDebug() << *this;
-        return TcfTrkDevicePtr();
+        return CodaDevicePtr();
     }
     SymbianDevice& device = d->m_devices[idx];
     if (device.m_data->device) {
         qWarning("Attempting to open a port '%s' that is configured for TRK!", qPrintable(port));
-        return TcfTrkDevicePtr();
+        return CodaDevicePtr();
     }
-    TcfTrkDevicePtr& devicePtr = device.m_data->tcfdevice;
-    if (devicePtr.isNull()) {
-        // Check we instanciate in the correct thread - we can't afford to create the TcfTrkDevice (and more specifically, open the VirtualSerialDevice) in a thread that isn't guaranteed to be long-lived.
+    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 current thread
@@ -378,57 +377,47 @@ TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &port)
             QWaitCondition waiter;
             QCoreApplication::postEvent(this, new QConstructTcfPortEvent((QEvent::Type)d->m_constructTcfPortEventType, port, &devicePtr, &waiter));
             waiter.wait(&d->m_tcfPortWaitMutex);
-            // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the TcfTrkDevice will be fully set up
+            // When the wait returns (due to the wakeAll in SymbianDeviceManager::customEvent), the CodaDevice will be fully set up
             d->m_tcfPortWaitMutex.unlock();
         } else {
             // We're in the main thread, just set it up directly
             constructTcfPort(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()) {
-        bool ok = devicePtr->device().staticCast<SymbianUtils::VirtualSerialDevice>()->open(QIODevice::ReadWrite);
-        if (!ok && debug) {
-            qDebug("SymbianDeviceManager: Failed to open port %s", qPrintable(port));
-        }
-        // We still carry on in the case we failed to open so the client can access the IODevice's errorString()
-    }
-    //Q_ASSERT(QThread::currentThread() == devicePtr->thread());
     return devicePtr;
 }
 
-void SymbianDeviceManager::constructTcfPort(TcfTrkDevicePtr& device, const QString& portName)
+void SymbianDeviceManager::constructTcfPort(CodaDevicePtr& device, const QString& portName)
 {
     QMutexLocker locker(&d->m_tcfPortWaitMutex);
-    device = QSharedPointer<tcftrk::TcfTrkDevice>(new tcftrk::TcfTrkDevice);
-    const QSharedPointer<SymbianUtils::VirtualSerialDevice> serialDevice(new SymbianUtils::VirtualSerialDevice(portName));
-    device->setSerialFrame(true);
-    device->setDevice(serialDevice);
+    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_constructTcfPortEventType)
-    {
+    if (event->type() == d->m_constructTcfPortEventType) {
         QConstructTcfPortEvent* constructEvent = static_cast<QConstructTcfPortEvent*>(event);
         constructTcfPort(*constructEvent->m_device, constructEvent->m_portName);
         constructEvent->m_waiter->wakeAll(); // Should only ever be one thing waiting on this
     }
 }
 
-/*
-TcfTrkDevicePtr SymbianDeviceManager::getTcfPort(const QString &host, quint16 port)
+void SymbianDeviceManager::releaseTcfPort(CodaDevicePtr &aPort)
 {
-    // No attempt to check the device list. The main purpose in doing that is to cooperatively share the port with other services, and there's no need to do that with TCP/IP as you can just use separate port numbers.
-    // Ok it might make it slightly quicker but I'm not going to worry about it just now
-
-}
-*/
-
-void SymbianDeviceManager::releaseTcfPort(TcfTrkDevicePtr &aPort)
-{
-    if (aPort) {
+    if (aPort)
         aPort.clear();
-    }
     //TODO close the port after a timeer if last reference?
 }
 
@@ -442,11 +431,10 @@ void SymbianDeviceManager::releaseDevice(const QString &port)
     const int idx = findByPortName(port);
     if (debug)
         qDebug() << "SymbianDeviceManager::releaseDevice" << port << idx << sender();
-    if (idx != -1) {
+    if (idx != -1)
         d->m_devices[idx].releaseDevice();
-    } else {
+    else
         qWarning("Attempt to release non-existing device %s.", qPrintable(port));
-    }
 }
 
 void SymbianDeviceManager::setAdditionalInformation(const QString &port, const QString &ai)
index 1ff885c..3ebb8ae 100644 (file)
@@ -48,8 +48,8 @@ QT_END_NAMESPACE
 namespace trk {
     class TrkDevice;
 }
-namespace tcftrk {
-    class TcfTrkDevice;
+namespace Coda {
+    class CodaDevice;
 }
 
 namespace SymbianUtils {
@@ -62,7 +62,7 @@ enum DeviceCommunicationType {
     BlueToothCommunication = 1
 };
 
-typedef QSharedPointer<tcftrk::TcfTrkDevice> TcfTrkDevicePtr;
+typedef QSharedPointer<Coda::CodaDevice> CodaDevicePtr;
 
 // SymbianDevice: Explicitly shared device data and a TrkDevice
 // instance that can be acquired (exclusively) for use.
@@ -146,17 +146,17 @@ public:
     // Acquire a TRK device for use. Assuming the port is found, equivalent to devices()[findByPortName(port)].acquireDevice(). See also releaseDevice().
     TrkDevicePtr acquireDevice(const QString &port);
 
-    //// The TCF code prefers to set up the TcfTrkDevice object itself, so we let it and just handle opening the underlying QIODevice and keeping track of the TcfTrkDevice
+    //// The TCF 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 TcfTrkDevice, 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 TcfTrkDevice::device()->isOpen()
+    // 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 releaseTcfPort if they want the port to auto-close itself
-    TcfTrkDevicePtr getTcfPort(const QString &port);
+    CodaDevicePtr getTcfPort(const QString &port);
 
-    // Caller is responsible for disconnecting any signals from aPort - do not assume the TcfTrkDevice will be deleted as a result of this call. On return aPort will be clear()ed.
-    void releaseTcfPort(TcfTrkDevicePtr &aPort);
+    // 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 releaseTcfPort(CodaDevicePtr &aPort);
 
     int findByPortName(const QString &p) const;
     QString friendlyNameForPort(const QString &port) const;
@@ -178,7 +178,7 @@ private:
     SymbianDeviceList serialPorts() const;
     SymbianDeviceList blueToothDevices() const;
     void customEvent(QEvent *event);
-    void constructTcfPort(TcfTrkDevicePtr& device, const QString& portName);
+    void constructTcfPort(CodaDevicePtr& device, const QString& portName);
 
     SymbianDeviceManagerPrivate *d;
 };
index 5fdfc2f..c659843 100644 (file)
@@ -127,14 +127,11 @@ bool VirtualSerialDevice::tryWrite(const char *data, qint64 maxSize, qint64& byt
     while (maxSize > 0) {
         int result = ::write(d->portHandle, data, maxSize);
         if (result == -1) {
-            if (errno == EAGAIN) {
-                // Need to wait
-                return true;
-            } else {
-                setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName));
-                bytesWritten = -1;
-                return false;
-            }
+            if (errno == EAGAIN)
+                return true; // Need to wait
+            setErrorString(QString("Posix error %1 from write to %2").arg(errno).arg(portName));
+            bytesWritten = -1;
+            return false;
         } else {
             if (result == 0)
                 qWarning("Zero bytes written to port!");