tools/runonphone/symbianutils/trkdevice.cpp
changeset 30 5dc02b23752f
parent 18 2f34d5167611
child 33 3e2da88830cd
--- a/tools/runonphone/symbianutils/trkdevice.cpp	Wed Jun 23 19:07:03 2010 +0300
+++ b/tools/runonphone/symbianutils/trkdevice.cpp	Tue Jul 06 15:10:48 2010 +0300
@@ -52,6 +52,7 @@
 #include <QtCore/QMutex>
 #include <QtCore/QWaitCondition>
 #include <QtCore/QSharedPointer>
+#include <QtCore/QScopedPointer>
 #include <QtCore/QMetaType>
 
 #ifdef Q_OS_WIN
@@ -102,6 +103,11 @@
 
 enum { verboseTrk = 0 };
 
+static inline QString msgAccessingClosedDevice(const QString &msg)
+{
+    return QString::fromLatin1("Error: Attempt to access device '%1', which is closed.").arg(msg);
+}
+
 namespace trk {
 
 ///////////////////////////////////////////////////////////////////////
@@ -155,10 +161,11 @@
 ///////////////////////////////////////////////////////////////////////
 
 class TrkWriteQueue
-{    
+{
     Q_DISABLE_COPY(TrkWriteQueue)
 public:
     explicit TrkWriteQueue();
+    void clear();
 
     // Enqueue messages.
     void queueTrkMessage(byte code, TrkCallback callback,
@@ -208,13 +215,24 @@
 {
 }
 
+void TrkWriteQueue::clear()
+{
+    m_trkWriteToken = 0;
+    m_trkWriteBusy = false;
+    m_trkWriteQueue.clear();
+    const int discarded = m_writtenTrkMessages.size();
+    m_writtenTrkMessages.clear();
+    if (verboseTrk)
+        qDebug() << "TrkWriteQueue::clear: discarded " << discarded;
+}
+
 byte TrkWriteQueue::nextTrkWriteToken()
 {
     ++m_trkWriteToken;
     if (m_trkWriteToken == 0)
         ++m_trkWriteToken;
     if (verboseTrk)
-        qDebug() << "Write token: " << m_trkWriteToken;
+        qDebug() << "nextTrkWriteToken:" << m_trkWriteToken;
     return m_trkWriteToken;
 }
 
@@ -349,7 +367,7 @@
 {
     Q_OBJECT
     Q_DISABLE_COPY(WriterThread)
-public:            
+public:
     explicit WriterThread(const QSharedPointer<DeviceContext> &context);
 
     // Enqueue messages.
@@ -357,6 +375,8 @@
                         const QByteArray &data, const QVariant &cookie);
     void queueTrkInitialPing();
 
+    void clearWriteQueue();
+
     // Call this from the device read notification with the results.
     void slotHandleResult(const TrkResult &result);
 
@@ -374,7 +394,7 @@
 private slots:
     void invokeNoopMessage(const trk::TrkMessage &);
 
-private:    
+private:
     bool write(const QByteArray &data, QString *errorMessage);
     inline int writePendingMessage();
 
@@ -462,6 +482,7 @@
     m_waitCondition.wakeAll();
     wait();
     m_terminate = false;
+    m_queue.clear();
 }
 
 #ifdef Q_OS_WIN
@@ -561,6 +582,13 @@
     tryWrite();
 }
 
+void WriterThread::clearWriteQueue()
+{
+    m_dataMutex.lock();
+    m_queue.clear();
+    m_dataMutex.unlock();
+}
+
 void WriterThread::queueTrkInitialPing()
 {
     m_dataMutex.lock();
@@ -592,6 +620,8 @@
     Q_DISABLE_COPY(ReaderThreadBase)
 public:
 
+    int bytesPending() const { return m_trkReadBuffer.size(); }
+
 signals:
     void messageReceived(const trk::TrkResult &result, const QByteArray &rawData);
 
@@ -692,7 +722,7 @@
     if (!ClearCommError(m_context->device, NULL, &comStat)){
         emit error(QString::fromLatin1("ClearCommError failed: %1").arg(winErrorMessage(GetLastError())));
         return -7;
-    }    
+    }
     const DWORD bytesToRead = qMax(DWORD(1), qMin(comStat.cbInQue, DWORD(BufSize)));
     // Trigger read
     DWORD bytesRead = 0;
@@ -708,7 +738,7 @@
     if (readError != ERROR_IO_PENDING) {
         emit error(QString::fromLatin1("Read error: %1").arg(winErrorMessage(readError)));
         return -1;
-    }    
+    }
     // Wait for either termination or data
     const DWORD wr = WaitForMultipleObjects(HandleCount, m_handles, false, INFINITE);
     if (wr == WAIT_FAILED) {
@@ -783,7 +813,7 @@
     int m_terminatePipeFileDescriptors[2];
 };
 
-UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) : 
+UnixReaderThread::UnixReaderThread(const QSharedPointer<DeviceContext> &context) :
     ReaderThreadBase(context)
 {
     m_terminatePipeFileDescriptors[0] = m_terminatePipeFileDescriptors[1] = -1;
@@ -877,8 +907,8 @@
     TrkDevicePrivate();
 
     QSharedPointer<DeviceContext> deviceContext;
-    QSharedPointer<WriterThread> writerThread;
-    QSharedPointer<ReaderThread> readerThread;
+    QScopedPointer<WriterThread> writerThread;
+    QScopedPointer<ReaderThread> readerThread;
 
     QByteArray trkReadBuffer;
     int verbose;
@@ -917,14 +947,14 @@
 
 bool TrkDevice::open(QString *errorMessage)
 {
-    if (d->verbose)
+    if (d->verbose || verboseTrk)
         qDebug() << "Opening" << port() << "is open: " << isOpen() << " serialFrame=" << serialFrame();
+    if (isOpen())
+        return true;
     if (d->port.isEmpty()) {
         *errorMessage = QLatin1String("Internal error: No port set on TrkDevice");
         return false;
     }
-
-    close();
 #ifdef Q_OS_WIN
     const QString fullPort = QLatin1String("\\\\.\\") + d->port;
     d->deviceContext->device = CreateFile(reinterpret_cast<const WCHAR*>(fullPort.utf16()),
@@ -975,7 +1005,7 @@
         return false;
     }
 #endif
-    d->readerThread = QSharedPointer<ReaderThread>(new ReaderThread(d->deviceContext));
+    d->readerThread.reset(new ReaderThread(d->deviceContext));
     connect(d->readerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)),
             Qt::QueuedConnection);
     connect(d->readerThread.data(), SIGNAL(messageReceived(trk::TrkResult,QByteArray)),
@@ -983,18 +1013,22 @@
             Qt::QueuedConnection);
     d->readerThread->start();
 
-    d->writerThread = QSharedPointer<WriterThread>(new WriterThread(d->deviceContext));
+    d->writerThread.reset(new WriterThread(d->deviceContext));
     connect(d->writerThread.data(), SIGNAL(error(QString)), this, SLOT(emitError(QString)),
-            Qt::QueuedConnection);    
-    d->writerThread->start();    
+            Qt::QueuedConnection);
+    d->writerThread->start();
 
-    if (d->verbose)
-        qDebug() << "Opened" << d->port;
+    if (d->verbose || verboseTrk)
+        qDebug() << "Opened" << d->port << d->readerThread.data() << d->writerThread.data();
     return true;
 }
 
 void TrkDevice::close()
 {
+    if (verboseTrk)
+        qDebug() << "close" << d->port << " is open: " << isOpen()
+        << " read pending " << (d->readerThread.isNull() ? 0 : d->readerThread->bytesPending())
+        << sender();
     if (!isOpen())
         return;
     if (d->readerThread)
@@ -1010,6 +1044,7 @@
 #else
     d->deviceContext->file.close();
 #endif
+
     if (d->verbose)
         emitLogMessage("Close");
 }
@@ -1030,6 +1065,8 @@
 
 void TrkDevice::setPort(const QString &p)
 {
+    if (verboseTrk)
+        qDebug() << "setPort" << p;
     d->port = p;
 }
 
@@ -1045,6 +1082,8 @@
 
 void TrkDevice::setSerialFrame(bool f)
 {
+    if (verboseTrk)
+        qDebug() << "setSerialFrame" << f;
     d->deviceContext->serialFrame = f;
 }
 
@@ -1060,12 +1099,14 @@
 
 void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArray &rawData)
 {
-    d->writerThread->slotHandleResult(result);
-    if (d->verbose > 1)
-        qDebug() << "Received: " << result.toString();
-    emit messageReceived(result);    
-    if (!rawData.isEmpty())
-        emit rawDataReceived(rawData);
+    if (isOpen()) { // Might receive bytes after closing due to queued connections.
+        d->writerThread->slotHandleResult(result);
+        if (d->verbose > 1)
+            qDebug() << "Received: " << result.toString();
+        emit messageReceived(result);
+        if (!rawData.isEmpty())
+            emit rawDataReceived(rawData);
+    }
 }
 
 void TrkDevice::emitError(const QString &s)
@@ -1075,15 +1116,27 @@
     emit error(s);
 }
 
+void TrkDevice::clearWriteQueue()
+{
+    if (isOpen())
+        d->writerThread->clearWriteQueue();
+}
+
 void TrkDevice::sendTrkMessage(byte code, TrkCallback callback,
      const QByteArray &data, const QVariant &cookie)
 {
+    if (!isOpen()) {
+        emitError(msgAccessingClosedDevice(d->port));
+        return;
+    }
     if (!d->writerThread.isNull()) {
         if (d->verbose > 1) {
-            QByteArray msg = "Sending:  ";
+            QByteArray msg = "Sending:  0x";
             msg += QByteArray::number(code, 16);
             msg += ": ";
             msg += stringFromArray(data).toLatin1();
+            if (cookie.isValid())
+                msg += " Cookie: " + cookie.toString().toLatin1();
             qDebug("%s", msg.data());
         }
         d->writerThread->queueTrkMessage(code, callback, data, cookie);
@@ -1092,12 +1145,20 @@
 
 void TrkDevice::sendTrkInitialPing()
 {
+    if (!isOpen()) {
+        emitError(msgAccessingClosedDevice(d->port));
+        return;
+    }
     if (!d->writerThread.isNull())
         d->writerThread->queueTrkInitialPing();
 }
 
 bool TrkDevice::sendTrkAck(byte token)
 {
+    if (!isOpen()) {
+        emitError(msgAccessingClosedDevice(d->port));
+        return false;
+    }
     if (d->writerThread.isNull())
         return false;
     // The acknowledgement must not be queued!