summaryrefslogtreecommitdiffstats
path: root/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'tests/auto/nfccommons/qnearfieldtarget_emulator.cpp')
-rw-r--r--tests/auto/nfccommons/qnearfieldtarget_emulator.cpp279
1 files changed, 279 insertions, 0 deletions
diff --git a/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp b/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp
new file mode 100644
index 00000000..776ba6f6
--- /dev/null
+++ b/tests/auto/nfccommons/qnearfieldtarget_emulator.cpp
@@ -0,0 +1,279 @@
+// Copyright (C) 2016 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only
+
+#include "qnearfieldtarget_emulator_p.h"
+#include <QtNfc/private/qnearfieldtarget_p.h>
+
+#include <QtCore/QByteArray>
+#include <QtCore/QByteArrayView>
+#include <QtCore/QCoreApplication>
+#include <QtCore/QDateTime>
+#include <QtCore/QDirIterator>
+#include <QtCore/QMutex>
+#include <QtCore/QSettings>
+
+QT_BEGIN_NAMESPACE
+
+static QMutex tagMutex;
+static QMap<TagBase *, bool> tagMap;
+
+Q_GLOBAL_STATIC(TagActivator, globalTagActivator)
+
+TagType1::TagType1(TagBase *tag, QObject *parent)
+: QNearFieldTagType1(parent), tag(tag)
+{
+}
+
+TagType1::~TagType1()
+{
+}
+
+QByteArray TagType1::uid() const
+{
+ QMutexLocker locker(&tagMutex);
+
+ return tag->uid();
+}
+
+QNearFieldTarget::AccessMethods TagType1::accessMethods() const
+{
+ return QNearFieldTarget::NdefAccess | QNearFieldTarget::TagTypeSpecificAccess;
+}
+
+QNearFieldTarget::RequestId TagType1::sendCommand(const QByteArray &command)
+{
+ QMutexLocker locker(&tagMutex);
+
+ QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate);
+
+ // tag not in proximity
+ if (!tagMap.value(tag)) {
+ reportError(QNearFieldTarget::TargetOutOfRangeError, id);
+ return id;
+ }
+
+ quint16 crc = qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41);
+
+ QByteArray response = tag->processCommand(command + char(crc & 0xff) + char(crc >> 8));
+
+ if (response.isEmpty()) {
+ reportError(QNearFieldTarget::NoResponseError, id);
+ return id;
+ }
+
+ // check crc
+ if (qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41) != 0) {
+ reportError(QNearFieldTarget::ChecksumMismatchError, id);
+ return id;
+ }
+
+ response.chop(2);
+
+ QMetaObject::invokeMethod(this, [this, id, response] {
+ this->setResponseForRequest(id, response);
+ }, Qt::QueuedConnection);
+
+ return id;
+}
+
+bool TagType1::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs)
+{
+ QCoreApplication::sendPostedEvents(this, QEvent::MetaCall);
+
+ return QNearFieldTagType1::waitForRequestCompleted(id, msecs);
+}
+
+
+TagType2::TagType2(TagBase *tag, QObject *parent)
+: QNearFieldTagType2(parent), tag(tag)
+{
+}
+
+TagType2::~TagType2()
+{
+}
+
+QByteArray TagType2::uid() const
+{
+ QMutexLocker locker(&tagMutex);
+
+ return tag->uid();
+}
+
+QNearFieldTarget::AccessMethods TagType2::accessMethods() const
+{
+ return QNearFieldTarget::NdefAccess | QNearFieldTarget::TagTypeSpecificAccess;
+}
+
+QNearFieldTarget::RequestId TagType2::sendCommand(const QByteArray &command)
+{
+ QMutexLocker locker(&tagMutex);
+
+ QNearFieldTarget::RequestId id(new QNearFieldTarget::RequestIdPrivate);
+
+ // tag not in proximity
+ if (!tagMap.value(tag)) {
+ reportError(QNearFieldTarget::TargetOutOfRangeError, id);
+ return id;
+ }
+
+ quint16 crc = qChecksum(QByteArrayView(command.constData(), command.size()), Qt::ChecksumItuV41);
+
+ QByteArray response = tag->processCommand(command + char(crc & 0xff) + char(crc >> 8));
+
+ if (response.isEmpty())
+ return id;
+
+ if (response.size() > 1) {
+ // check crc
+ if (qChecksum(QByteArrayView(response.constData(), response.size()), Qt::ChecksumItuV41) != 0) {
+ reportError(QNearFieldTarget::ChecksumMismatchError, id);
+ return id;
+ }
+
+ response.chop(2);
+ }
+
+ QMetaObject::invokeMethod(this, [this, id, response] {
+ this->setResponseForRequest(id, response);
+ }, Qt::QueuedConnection);
+
+ return id;
+}
+
+bool TagType2::waitForRequestCompleted(const QNearFieldTarget::RequestId &id, int msecs)
+{
+ QCoreApplication::sendPostedEvents(this, QEvent::MetaCall);
+
+ return QNearFieldTagType2::waitForRequestCompleted(id, msecs);
+}
+
+TagActivator::TagActivator() : QObject()
+{
+ qRegisterMetaType<QNearFieldTarget::Error>();
+}
+
+TagActivator::~TagActivator()
+{
+ QMutexLocker locker(&tagMutex);
+ qDeleteAll(tagMap.keys());
+ tagMap.clear();
+}
+
+void TagActivator::initialize()
+{
+ QMutexLocker locker(&tagMutex);
+
+ if (!tagMap.isEmpty())
+ return;
+
+#ifndef BUILTIN_TESTDATA
+ QDirIterator nfcTargets(QDir::currentPath(), QStringList(QStringLiteral("*.nfc")), QDir::Files);
+#else
+ QDirIterator nfcTargets(":/nfcdata", QStringList(QStringLiteral("*.nfc")), QDir::Files);
+#endif
+ while (nfcTargets.hasNext()) {
+ const QString targetFilename = nfcTargets.next();
+
+ QSettings target(targetFilename, QSettings::IniFormat);
+
+ target.beginGroup(QStringLiteral("Target"));
+
+ const QString tagType = target.value(QStringLiteral("Type")).toString();
+
+ target.endGroup();
+
+ if (tagType == QLatin1String("TagType1")) {
+ NfcTagType1 *tag = new NfcTagType1;
+ tag->load(&target);
+
+ tagMap.insert(tag, false);
+ } else if (tagType == QLatin1String("TagType2")) {
+ NfcTagType2 *tag = new NfcTagType2;
+ tag->load(&target);
+
+ tagMap.insert(tag, false);
+ } else {
+ qWarning("Unknown tag type %s\n", qPrintable(tagType));
+ }
+ }
+
+ current = tagMap.end();
+}
+
+void TagActivator::reset()
+{
+ QMutexLocker locker(&tagMutex);
+
+ stopInternal();
+
+ qDeleteAll(tagMap.keys());
+ tagMap.clear();
+}
+
+void TagActivator::start()
+{
+ QMutexLocker locker(&tagMutex);
+ timerId = startTimer(1000);
+}
+
+void TagActivator::stop()
+{
+ QMutexLocker locker(&tagMutex);
+ stopInternal();
+}
+
+void TagActivator::stopInternal()
+{
+ if (timerId != -1) {
+ killTimer(timerId);
+ timerId = -1;
+ }
+}
+
+TagActivator *TagActivator::instance()
+{
+ return globalTagActivator();
+}
+
+void TagActivator::timerEvent(QTimerEvent *e)
+{
+ Q_UNUSED(e);
+
+ tagMutex.lock();
+
+ if (current != tagMap.end()) {
+ if (current.key()->lastAccessTime() + 1500 > QDateTime::currentMSecsSinceEpoch()) {
+ tagMutex.unlock();
+ return;
+ }
+
+ *current = false;
+
+ TagBase *tag = current.key();
+
+ tagMutex.unlock();
+ Q_EMIT tagDeactivated(tag);
+ tagMutex.lock();
+ }
+
+ if (current != tagMap.end())
+ ++current;
+
+ if (current == tagMap.end())
+ current = tagMap.begin();
+
+ if (current != tagMap.end()) {
+ *current = true;
+
+ TagBase *tag = current.key();
+
+ tagMutex.unlock();
+ Q_EMIT tagActivated(tag);
+ tagMutex.lock();
+ }
+
+ tagMutex.unlock();
+}
+
+QT_END_NAMESPACE