equal
deleted
inserted
replaced
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) |