/*************************************************************************** ** ** Copyright (C) 2016 BlackBerry Limited. All rights reserved. ** Copyright (C) 2016 BasysKom GmbH. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtNfc module of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and The Qt Company. For licensing terms ** and conditions see https://www.qt.io/terms-conditions. For further ** information use the contact form at https://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 3 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL3 included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 3 requirements ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. ** ** GNU General Public License Usage ** Alternatively, this file may be used under the terms of the GNU ** General Public License version 2.0 or (at your option) the GNU General ** Public license version 3 or any later version approved by the KDE Free ** Qt Foundation. The licenses are as published by the Free Software ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 ** included in the packaging of this file. Please review the following ** information to ensure the GNU General Public License requirements will ** be met: https://www.gnu.org/licenses/gpl-2.0.html and ** https://www.gnu.org/licenses/gpl-3.0.html. ** ** $QT_END_LICENSE$ ** ****************************************************************************/ #include "qnearfieldmanager_neard_p.h" #include "qnearfieldtarget_neard_p.h" #include "neard/adapter_p.h" #include "neard/dbusproperties_p.h" #include "neard/dbusobjectmanager_p.h" QT_BEGIN_NAMESPACE Q_DECLARE_LOGGING_CATEGORY(QT_NFC_NEARD) // TODO We need a constructor that lets us select an adapter QNearFieldManagerPrivateImpl::QNearFieldManagerPrivateImpl() : QNearFieldManagerPrivate(), m_neardHelper(NeardHelper::instance()) { QDBusPendingReply reply = m_neardHelper->dbusObjectManager()->GetManagedObjects(); reply.waitForFinished(); if (reply.isError()) { qCWarning(QT_NFC_NEARD) << "Error getting managed objects"; return; } bool found = false; const QList paths = reply.value().keys(); for (const QDBusObjectPath &path : paths) { const InterfaceList ifaceList = reply.value().value(path); const QStringList ifaces = ifaceList.keys(); for (const QString &iface : ifaces) { if (iface == QStringLiteral("org.neard.Adapter")) { found = true; m_adapterPath = path.path(); qCDebug(QT_NFC_NEARD) << "org.neard.Adapter found for path" << m_adapterPath; break; } } if (found) break; } if (!found) { qCWarning(QT_NFC_NEARD) << "no adapter found, neard daemon running?"; } else { connect(m_neardHelper, &NeardHelper::tagFound, this, &QNearFieldManagerPrivateImpl::handleTagFound); connect(m_neardHelper, &NeardHelper::tagRemoved, this, &QNearFieldManagerPrivateImpl::handleTagRemoved); } } QNearFieldManagerPrivateImpl::~QNearFieldManagerPrivateImpl() { stopTargetDetection(); } bool QNearFieldManagerPrivateImpl::isAvailable() const { if (!m_neardHelper->dbusObjectManager()->isValid() || m_adapterPath.isNull()) { qCWarning(QT_NFC_NEARD) << "dbus object manager invalid or adapter path invalid"; return false; } QDBusPendingReply reply = m_neardHelper->dbusObjectManager()->GetManagedObjects(); reply.waitForFinished(); if (reply.isError()) { qCWarning(QT_NFC_NEARD) << "error getting managed objects"; return false; } const QList paths = reply.value().keys(); for (const QDBusObjectPath &path : paths) { if (m_adapterPath == path.path()) return true; } return false; } bool QNearFieldManagerPrivateImpl::isSupported() const { if (m_adapterPath.isEmpty()) { qCWarning(QT_NFC_NEARD) << "no adapter found, neard daemon running?"; return false; } if (!m_neardHelper->dbusObjectManager()->isValid() || m_adapterPath.isNull()) { qCWarning(QT_NFC_NEARD) << "dbus object manager invalid or adapter path invalid"; return false; } return true; } bool QNearFieldManagerPrivateImpl::startTargetDetection() { qCDebug(QT_NFC_NEARD) << "starting target detection"; if (!isAvailable()) return false; OrgFreedesktopDBusPropertiesInterface dbusProperties(QStringLiteral("org.neard"), m_adapterPath, QDBusConnection::systemBus()); if (!dbusProperties.isValid()) { qCWarning(QT_NFC_NEARD) << "dbus property interface invalid"; return false; } // check if the adapter is currently polling QDBusPendingReply replyPolling = dbusProperties.Get(QStringLiteral("org.neard.Adapter"), QStringLiteral("Polling")); replyPolling.waitForFinished(); if (!replyPolling.isError()) { if (replyPolling.value().variant().toBool()) { qCDebug(QT_NFC_NEARD) << "adapter is already polling"; return true; } } else { qCWarning(QT_NFC_NEARD) << "error getting 'Polling' state from property interface"; return false; } // check if the adapter it powered QDBusPendingReply replyPowered = dbusProperties.Get(QStringLiteral("org.neard.Adapter"), QStringLiteral("Powered")); replyPowered.waitForFinished(); if (!replyPowered.isError()) { if (replyPowered.value().variant().toBool()) { qCDebug(QT_NFC_NEARD) << "adapter is already powered"; } else { QDBusPendingReply replyTryPowering = dbusProperties.Set(QStringLiteral("org.neard.Adapter"), QStringLiteral("Powered"), QDBusVariant(true)); replyTryPowering.waitForFinished(); if (!replyTryPowering.isError()) { qCDebug(QT_NFC_NEARD) << "powering adapter"; } } } else { qCWarning(QT_NFC_NEARD) << "error getting 'Powered' state from property interface"; return false; } // create adapter and start poll loop OrgNeardAdapterInterface neardAdapter(QStringLiteral("org.neard"), m_adapterPath, QDBusConnection::systemBus()); // possible modes: "Target", "Initiator", "Dual" QDBusPendingReply<> replyPollLoop = neardAdapter.StartPollLoop(QStringLiteral("Dual")); replyPollLoop.waitForFinished(); if (replyPollLoop.isError()) { qCWarning(QT_NFC_NEARD) << "error when starting polling"; return false; } else { qCDebug(QT_NFC_NEARD) << "successfully started polling"; } return true; } void QNearFieldManagerPrivateImpl::stopTargetDetection() { qCDebug(QT_NFC_NEARD) << "stopping target detection"; if (!isAvailable()) return; OrgFreedesktopDBusPropertiesInterface dbusProperties(QStringLiteral("org.neard"), m_adapterPath, QDBusConnection::systemBus()); if (!dbusProperties.isValid()) { qCWarning(QT_NFC_NEARD) << "dbus property interface invalid"; return; } // check if the adapter is currently polling QDBusPendingReply replyPolling = dbusProperties.Get(QStringLiteral("org.neard.Adapter"), QStringLiteral("Polling")); replyPolling.waitForFinished(); if (!replyPolling.isError()) { if (replyPolling.value().variant().toBool()) { // create adapter and stop poll loop OrgNeardAdapterInterface neardAdapter(QStringLiteral("org.neard"), m_adapterPath, QDBusConnection::systemBus()); QDBusPendingReply<> replyStopPolling = neardAdapter.StopPollLoop(); replyStopPolling.waitForFinished(); if (replyStopPolling.isError()) qCWarning(QT_NFC_NEARD) << "error when stopping polling"; else qCDebug(QT_NFC_NEARD) << "successfully stopped polling"; } else { qCDebug(QT_NFC_NEARD) << "already stopped polling"; } } else { qCWarning(QT_NFC_NEARD) << "error getting 'Polling' state from property interface"; } } int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(QObject *object, const QMetaMethod &method) { Q_UNUSED(object); Q_UNUSED(method); return -1; } int QNearFieldManagerPrivateImpl::registerNdefMessageHandler(const QNdefFilter &filter, QObject *object, const QMetaMethod &method) { Q_UNUSED(filter); Q_UNUSED(object); Q_UNUSED(method); return -1; } bool QNearFieldManagerPrivateImpl::unregisterNdefMessageHandler(int handlerId) { Q_UNUSED(handlerId); return false; } void QNearFieldManagerPrivateImpl::requestAccess(QNearFieldManager::TargetAccessModes accessModes) { Q_UNUSED(accessModes); } void QNearFieldManagerPrivateImpl::releaseAccess(QNearFieldManager::TargetAccessModes accessModes) { Q_UNUSED(accessModes); } void QNearFieldManagerPrivateImpl::handleTagFound(const QDBusObjectPath &path) { NearFieldTarget *nfTag = new NearFieldTarget(this, path); m_activeTags.insert(path.path(), nfTag); emit targetDetected(nfTag); } void QNearFieldManagerPrivateImpl::handleTagRemoved(const QDBusObjectPath &path) { const QString adapterPath = path.path(); if (m_activeTags.contains(adapterPath)) { QNearFieldTarget *nfTag = m_activeTags.value(adapterPath); m_activeTags.remove(adapterPath); emit targetLost(nfTag); } } QT_END_NAMESPACE