tools/runonphone/trk/trkdevice.cpp
branchRCL_3
changeset 5 d3bac044e0f0
parent 4 3b1da2848fc7
equal deleted inserted replaced
4:3b1da2848fc7 5:d3bac044e0f0
    97     return rc;
    97     return rc;
    98 }
    98 }
    99 
    99 
   100 #endif
   100 #endif
   101 
   101 
       
   102 enum { verboseTrk = 0 };
       
   103 
   102 namespace trk {
   104 namespace trk {
   103 
   105 
   104 ///////////////////////////////////////////////////////////////////////
   106 ///////////////////////////////////////////////////////////////////////
   105 //
   107 //
   106 // TrkMessage
   108 // TrkMessage
   124 TrkMessage::TrkMessage(byte c, byte t, TrkCallback cb) :
   126 TrkMessage::TrkMessage(byte c, byte t, TrkCallback cb) :
   125     code(c),
   127     code(c),
   126     token(t),
   128     token(t),
   127     callback(cb)
   129     callback(cb)
   128 {
   130 {
       
   131 }
       
   132 
       
   133 QDebug operator<<(QDebug d, const TrkMessage &msg)
       
   134 {
       
   135     return d << "Message: Code: " << msg.code
       
   136         << " Token: " << msg.token << " " << msg.data.toHex();
   129 }
   137 }
   130 
   138 
   131 } // namespace trk
   139 } // namespace trk
   132 
   140 
   133 Q_DECLARE_METATYPE(trk::TrkMessage)
   141 Q_DECLARE_METATYPE(trk::TrkMessage)
   202 byte TrkWriteQueue::nextTrkWriteToken()
   210 byte TrkWriteQueue::nextTrkWriteToken()
   203 {
   211 {
   204     ++m_trkWriteToken;
   212     ++m_trkWriteToken;
   205     if (m_trkWriteToken == 0)
   213     if (m_trkWriteToken == 0)
   206         ++m_trkWriteToken;
   214         ++m_trkWriteToken;
       
   215     if (verboseTrk)
       
   216         qDebug() << "Write token: " << m_trkWriteToken;
   207     return m_trkWriteToken;
   217     return m_trkWriteToken;
   208 }
   218 }
   209 
   219 
   210 void TrkWriteQueue::queueTrkMessage(byte code, TrkCallback callback,
   220 void TrkWriteQueue::queueTrkMessage(byte code, TrkCallback callback,
   211     const QByteArray &data, const QVariant &cookie)
   221     const QByteArray &data, const QVariant &cookie)
   332 // done by the thread owning the TrkWriteQueue, while pendingMessage() is called
   342 // done by the thread owning the TrkWriteQueue, while pendingMessage() is called
   333 // from another thread. This happens via a Qt::BlockingQueuedConnection.
   343 // from another thread. This happens via a Qt::BlockingQueuedConnection.
   334 
   344 
   335 ///////////////////////////////////////////////////////////////////////
   345 ///////////////////////////////////////////////////////////////////////
   336 
   346 
   337 class WriterThread : public QThread {
   347 class WriterThread : public QThread
       
   348 {
   338     Q_OBJECT
   349     Q_OBJECT
   339     Q_DISABLE_COPY(WriterThread)
   350     Q_DISABLE_COPY(WriterThread)
   340 public:            
   351 public:            
   341     explicit WriterThread(const QSharedPointer<DeviceContext> &context);
   352     explicit WriterThread(const QSharedPointer<DeviceContext> &context);
   342 
   353 
   398     m_waitMutex.lock();
   409     m_waitMutex.lock();
   399     m_waitCondition.wait(&m_waitMutex, 100);
   410     m_waitCondition.wait(&m_waitMutex, 100);
   400     m_waitMutex.unlock();
   411     m_waitMutex.unlock();
   401     if (m_terminate)
   412     if (m_terminate)
   402         return 1;
   413         return 1;
       
   414 
   403     // Send off message
   415     // Send off message
   404     m_dataMutex.lock();
   416     m_dataMutex.lock();
   405     TrkMessage message;
   417     TrkMessage message;
   406     const TrkWriteQueue::PendingMessageResult pr = m_queue.pendingMessage(&message);
   418     const TrkWriteQueue::PendingMessageResult pr = m_queue.pendingMessage(&message);
   407     m_dataMutex.unlock();
   419     m_dataMutex.unlock();
       
   420 
   408     switch (pr) {
   421     switch (pr) {
   409     case TrkWriteQueue::NoMessage:
   422     case TrkWriteQueue::NoMessage:
   410         break;
   423         break;
   411     case TrkWriteQueue::PendingMessage: {
   424     case TrkWriteQueue::PendingMessage: {
       
   425             //qDebug() << "Write pending message " << message;
   412             // Untested: try to re-send a few times
   426             // Untested: try to re-send a few times
   413             bool success = false;
   427             bool success = false;
   414             for (int r = 0; !success && (r < MaxAttempts); r++) {
   428             for (int r = 0; !success && (r < MaxAttempts); r++) {
   415                 success = trkWriteRawMessage(message);
   429                 success = trkWriteRawMessage(message);
   416                 if (!success) {
   430                 if (!success) {
   426             m_dataMutex.unlock();
   440             m_dataMutex.unlock();
   427         }
   441         }
   428         break;
   442         break;
   429     case TrkWriteQueue::NoopMessageDequeued:
   443     case TrkWriteQueue::NoopMessageDequeued:
   430         // Sync with thread that owns us via a blocking signal
   444         // Sync with thread that owns us via a blocking signal
       
   445         if (verboseTrk)
       
   446             qDebug() << "Noop message dequeued" << message;
   431         emit internalNoopMessageDequeued(message);
   447         emit internalNoopMessageDequeued(message);
   432         break;
   448         break;
   433     } // switch
   449     } // switch
   434     return 0;
   450     return 0;
   435 }
   451 }
   497 }
   513 }
   498 #endif
   514 #endif
   499 
   515 
   500 bool WriterThread::write(const QByteArray &data, QString *errorMessage)
   516 bool WriterThread::write(const QByteArray &data, QString *errorMessage)
   501 {
   517 {
       
   518     if (verboseTrk)
       
   519         qDebug() << "Write raw data: " << data.toHex();
   502     QMutexLocker locker(&m_context->mutex);
   520     QMutexLocker locker(&m_context->mutex);
   503 #ifdef Q_OS_WIN
   521 #ifdef Q_OS_WIN
   504     DWORD charsWritten;
   522     DWORD charsWritten;
   505     if (!overlappedSyncWrite(m_context->device, m_terminate, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped, errorMessage)) {
   523     if (!overlappedSyncWrite(m_context->device, m_terminate, data.data(), data.size(), &charsWritten, &m_context->writeOverlapped, errorMessage)) {
   506         return false;
   524         return false;
   555 {
   573 {
   556     m_queue.slotHandleResult(result, &m_dataMutex);
   574     m_queue.slotHandleResult(result, &m_dataMutex);
   557     tryWrite(); // Have messages been enqueued in-between?
   575     tryWrite(); // Have messages been enqueued in-between?
   558 }
   576 }
   559 
   577 
       
   578 
   560 ///////////////////////////////////////////////////////////////////////
   579 ///////////////////////////////////////////////////////////////////////
   561 //
   580 //
   562 // ReaderThreadBase: Base class for a thread that reads data from
   581 // ReaderThreadBase: Base class for a thread that reads data from
   563 // the device, decodes the messages and emit signals for the messages.
   582 // the device, decodes the messages and emit signals for the messages.
   564 // A Qt::BlockingQueuedConnection should be used for the message signal
   583 // A Qt::BlockingQueuedConnection should be used for the message signal
   565 // to ensure messages are processed in the correct sequence.
   584 // to ensure messages are processed in the correct sequence.
   566 //
   585 //
   567 ///////////////////////////////////////////////////////////////////////
   586 ///////////////////////////////////////////////////////////////////////
   568 
   587 
   569 class ReaderThreadBase : public QThread {
   588 class ReaderThreadBase : public QThread
       
   589 {
   570     Q_OBJECT
   590     Q_OBJECT
   571     Q_DISABLE_COPY(ReaderThreadBase)
   591     Q_DISABLE_COPY(ReaderThreadBase)
   572 public:
   592 public:
   573 
   593 
   574 signals:
   594 signals:
   623 // Waits on an overlapped I/O handle and an event that tells the thread to
   643 // Waits on an overlapped I/O handle and an event that tells the thread to
   624 // terminate.
   644 // terminate.
   625 //
   645 //
   626 ///////////////////////////////////////////////////////////////////////
   646 ///////////////////////////////////////////////////////////////////////
   627 
   647 
   628 class WinReaderThread : public ReaderThreadBase {
   648 class WinReaderThread : public ReaderThreadBase
       
   649 {
   629     Q_OBJECT
   650     Q_OBJECT
   630     Q_DISABLE_COPY(WinReaderThread)
   651     Q_DISABLE_COPY(WinReaderThread)
   631 public:
   652 public:
   632     explicit WinReaderThread(const QSharedPointer<DeviceContext> &context);
   653     explicit WinReaderThread(const QSharedPointer<DeviceContext> &context);
   633     ~WinReaderThread();
   654     ~WinReaderThread();
   833 
   854 
   834 void UnixReaderThread::terminate()
   855 void UnixReaderThread::terminate()
   835 {
   856 {
   836     // Trigger select() by writing to the pipe
   857     // Trigger select() by writing to the pipe
   837     char c = 0;
   858     char c = 0;
   838     write(m_terminatePipeFileDescriptors[1], &c, 1);
   859     int written = write(m_terminatePipeFileDescriptors[1], &c, 1);
       
   860     // FIXME: Use result.
   839     wait();
   861     wait();
   840 }
   862 }
   841 
   863 
   842 typedef UnixReaderThread ReaderThread;
   864 typedef UnixReaderThread ReaderThread;
   843 
   865 
  1019 }
  1041 }
  1020 
  1042 
  1021 void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArray &rawData)
  1043 void TrkDevice::slotMessageReceived(const trk::TrkResult &result, const QByteArray &rawData)
  1022 {
  1044 {
  1023     d->writerThread->slotHandleResult(result);
  1045     d->writerThread->slotHandleResult(result);
       
  1046     if (d->verbose > 1)
       
  1047         qDebug() << "Received: " << result.toString();
  1024     emit messageReceived(result);    
  1048     emit messageReceived(result);    
  1025     if (!rawData.isEmpty())
  1049     if (!rawData.isEmpty())
  1026         emit rawDataReceived(rawData);
  1050         emit rawDataReceived(rawData);
  1027 }
  1051 }
  1028 
  1052 
  1055         return false;
  1079         return false;
  1056     // The acknowledgement must not be queued!
  1080     // The acknowledgement must not be queued!
  1057     TrkMessage msg(0x80, token);
  1081     TrkMessage msg(0x80, token);
  1058     msg.token = token;
  1082     msg.token = token;
  1059     msg.data.append('\0');
  1083     msg.data.append('\0');
       
  1084     if (verboseTrk)
       
  1085         qDebug() << "Write synchroneous message: " << msg;
  1060     return d->writerThread->trkWriteRawMessage(msg);
  1086     return d->writerThread->trkWriteRawMessage(msg);
  1061     // 01 90 00 07 7e 80 01 00 7d 5e 7e
  1087     // 01 90 00 07 7e 80 01 00 7d 5e 7e
  1062 }
  1088 }
  1063 
  1089 
  1064 void TrkDevice::emitLogMessage(const QString &msg)
  1090 void TrkDevice::emitLogMessage(const QString &msg)