// Copyright (C) 2022 The Qt Company Ltd. // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only #include "qnearfieldmanager_pcsc_p.h" #include "qnearfieldtarget_pcsc_p.h" #include "pcsc/qpcscmanager_p.h" #include "pcsc/qpcsccard_p.h" #include #include QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; Q_DECLARE_LOGGING_CATEGORY(QT_NFC_PCSC) /* Constructs a new near field manager private implementation. This object creates a worker thread with an instance of QPcscManager in it. All the communication with QPcscManager is done using signal-slot mechanism. */ QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() { qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; m_worker = new QPcscManager; m_workerThread = new QThread(this); m_workerThread->setObjectName(u"QtNfcThread"_s); m_worker->moveToThread(m_workerThread); connect(m_worker, &QPcscManager::cardInserted, this, &QNearFieldManagerPrivateImpl::onCardInserted); connect(this, &QNearFieldManagerPrivateImpl::startTargetDetectionRequest, m_worker, &QPcscManager::onStartTargetDetectionRequest); connect(this, &QNearFieldManagerPrivateImpl::stopTargetDetectionRequest, m_worker, &QPcscManager::onStopTargetDetectionRequest); m_workerThread->start(); } /* Destroys the near field manager private implementation. */ QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() { qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; // Destroy the worker. It calls QThread::quit() on the working thread in // its destructor. QMetaObject::invokeMethod(m_worker, &QObject::deleteLater, Qt::QueuedConnection); m_workerThread->wait(); } bool QNearFieldManagerPrivateImpl::isEnabled() const { return true; } bool QNearFieldManagerPrivateImpl::isSupported(QNearFieldTarget::AccessMethod accessMethod) const { switch (accessMethod) { case QNearFieldTarget::TagTypeSpecificAccess: case QNearFieldTarget::NdefAccess: return true; default: return false; } } bool QNearFieldManagerPrivateImpl::startTargetDetection(QNearFieldTarget::AccessMethod accessMethod) { qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; Q_EMIT startTargetDetectionRequest(accessMethod); return true; } void QNearFieldManagerPrivateImpl::stopTargetDetection(const QString &errorMessage) { Q_UNUSED(errorMessage); qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; Q_EMIT stopTargetDetectionRequest(); } /* Invoked when the worker has detected a new card. The worker will ensure that the card object remains valid until the manager emits targetCreatedForCard() signal. */ void QNearFieldManagerPrivateImpl::onCardInserted(QPcscCard *card, const QByteArray &uid, QNearFieldTarget::AccessMethods accessMethods, int maxInputLength) { qCDebug(QT_NFC_PCSC) << Q_FUNC_INFO; auto priv = new QNearFieldTargetPrivateImpl(uid, accessMethods, maxInputLength, this); connect(priv, &QNearFieldTargetPrivateImpl::disconnectRequest, card, &QPcscCard::onDisconnectRequest); connect(priv, &QNearFieldTargetPrivateImpl::destroyed, card, &QPcscCard::onTargetDestroyed); connect(priv, &QNearFieldTargetPrivateImpl::sendCommandRequest, card, &QPcscCard::onSendCommandRequest); connect(priv, &QNearFieldTargetPrivateImpl::readNdefMessagesRequest, card, &QPcscCard::onReadNdefMessagesRequest); connect(priv, &QNearFieldTargetPrivateImpl::writeNdefMessagesRequest, card, &QPcscCard::onWriteNdefMessagesRequest); connect(priv, &QNearFieldTargetPrivateImpl::targetLost, this, &QNearFieldManagerPrivateImpl::onTargetLost); connect(card, &QPcscCard::disconnected, priv, &QNearFieldTargetPrivateImpl::onDisconnected); connect(card, &QPcscCard::invalidated, priv, &QNearFieldTargetPrivateImpl::onInvalidated); connect(card, &QPcscCard::requestCompleted, priv, &QNearFieldTargetPrivateImpl::onRequestCompleted); connect(card, &QPcscCard::ndefMessageRead, priv, &QNearFieldTargetPrivateImpl::onNdefMessageRead); auto target = new QNearFieldTarget(priv, this); Q_EMIT targetDetected(target); // Let the worker know that the card object can be deleted if it is no // longer needed. QMetaObject::invokeMethod(card, &QPcscCard::enableAutodelete, Qt::QueuedConnection); } void QNearFieldManagerPrivateImpl::onTargetLost(QNearFieldTargetPrivate *target) { Q_EMIT targetLost(target->q_ptr); } Q_LOGGING_CATEGORY(QT_NFC_PCSC, "qt.nfc.pcsc") QT_END_NAMESPACE