1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtNfc module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#include "qnearfieldmanagervirtualbase_p.h"
41#include "qndefmessage.h"
42#include "qtlv_p.h"
43
44QT_BEGIN_NAMESPACE
45
46//static inline bool matchesTarget(QNearFieldTarget::Type type,
47// const QList<QNearFieldTarget::Type> &types)
48//{
49// return types.contains(type) || types.contains(QNearFieldTarget::AnyTarget);
50//}
51
52QNearFieldManagerPrivateVirtualBase::QNearFieldManagerPrivateVirtualBase()
53{
54}
55
56QNearFieldManagerPrivateVirtualBase::~QNearFieldManagerPrivateVirtualBase()
57{
58}
59
60bool QNearFieldManagerPrivateVirtualBase::startTargetDetection()
61{
62 return true;
63}
64
65void QNearFieldManagerPrivateVirtualBase::stopTargetDetection()
66{
67}
68
69int QNearFieldManagerPrivateVirtualBase::getFreeId()
70{
71 if (!m_freeIds.isEmpty())
72 return m_freeIds.takeFirst();
73
74 m_registeredHandlers.append(t: Callback());
75 return m_registeredHandlers.count() - 1;
76}
77
78int QNearFieldManagerPrivateVirtualBase::registerNdefMessageHandler(QObject *object,
79 const QMetaMethod &method)
80{
81 int id = getFreeId();
82
83 Callback &callback = m_registeredHandlers[id];
84
85 callback.filter = QNdefFilter();
86 callback.object = object;
87 callback.method = method;
88
89 return id;
90}
91
92int QNearFieldManagerPrivateVirtualBase::registerNdefMessageHandler(const QNdefFilter &filter,
93 QObject *object,
94 const QMetaMethod &method)
95{
96 int id = getFreeId();
97
98 Callback &callback = m_registeredHandlers[id];
99
100 callback.filter = filter;
101 callback.object = object;
102 callback.method = method;
103
104 return id;
105}
106
107bool QNearFieldManagerPrivateVirtualBase::unregisterNdefMessageHandler(int id)
108{
109 if (id < 0 || id >= m_registeredHandlers.count())
110 return false;
111
112 m_freeIds.append(t: id);
113
114 while (m_freeIds.contains(t: m_registeredHandlers.count() - 1)) {
115 m_freeIds.removeAll(t: m_registeredHandlers.count() - 1);
116 m_registeredHandlers.removeLast();
117 }
118
119 return true;
120}
121
122void QNearFieldManagerPrivateVirtualBase::targetActivated(QNearFieldTarget *target)
123{
124 //if (matchesTarget(target->type(), m_detectTargetTypes))
125 emit targetDetected(target);
126
127 if (target->hasNdefMessage()) {
128 QTlvReader reader(target);
129 while (!reader.atEnd()) {
130 if (!reader.readNext()) {
131 if (!target->waitForRequestCompleted(id: reader.requestId()))
132 break;
133 else
134 continue;
135 }
136
137 // NDEF Message TLV
138 if (reader.tag() == 0x03)
139 ndefReceived(message: QNdefMessage::fromByteArray(message: reader.data()), target);
140 }
141 }
142}
143
144void QNearFieldManagerPrivateVirtualBase::targetDeactivated(QNearFieldTarget *target)
145{
146 emit targetLost(target);
147 QMetaObject::invokeMethod(obj: target, member: "disconnected");
148}
149
150struct VerifyRecord
151{
152 QNdefFilter::Record filterRecord;
153 unsigned int count;
154};
155
156void QNearFieldManagerPrivateVirtualBase::ndefReceived(const QNdefMessage &message,
157 QNearFieldTarget *target)
158{
159 for (int i = 0; i < m_registeredHandlers.count(); ++i) {
160 if (m_freeIds.contains(t: i))
161 continue;
162
163 Callback &callback = m_registeredHandlers[i];
164
165 bool matched = true;
166
167 QList<VerifyRecord> filterRecords;
168 for (int j = 0; j < callback.filter.recordCount(); ++j) {
169 VerifyRecord vr;
170 vr.count = 0;
171 vr.filterRecord = callback.filter.recordAt(i: j);
172
173 filterRecords.append(t: vr);
174 }
175
176 for (const QNdefRecord &record : message) {
177 for (int j = 0; matched && (j < filterRecords.count()); ++j) {
178 VerifyRecord &vr = filterRecords[j];
179
180 if (vr.filterRecord.typeNameFormat == record.typeNameFormat() &&
181 ( vr.filterRecord.type == record.type() ||
182 vr.filterRecord.type.isEmpty()) ) {
183 ++vr.count;
184 break;
185 } else {
186 if (callback.filter.orderMatch()) {
187 if (vr.filterRecord.minimum <= vr.count &&
188 vr.count <= vr.filterRecord.maximum) {
189 continue;
190 } else {
191 matched = false;
192 }
193 }
194 }
195 }
196 }
197
198 for (int j = 0; matched && (j < filterRecords.count()); ++j) {
199 const VerifyRecord &vr = filterRecords.at(i: j);
200
201 if (vr.filterRecord.minimum <= vr.count && vr.count <= vr.filterRecord.maximum)
202 continue;
203 else
204 matched = false;
205 }
206
207 if (matched) {
208 callback.method.invoke(object: callback.object, Q_ARG(QNdefMessage, message),
209 Q_ARG(QNearFieldTarget *, target));
210 }
211 }
212}
213
214QT_END_NAMESPACE
215

source code of qtconnectivity/src/nfc/qnearfieldmanagervirtualbase.cpp