1// Copyright (C) 2016 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qnearfieldtarget.h"
5#include "qnearfieldtarget_p.h"
6#include "qndefmessage.h"
7
8#include <QtCore/QString>
9#include <QtCore/QUrl>
10
11#include <QtCore/QDebug>
12
13#include <QCoreApplication>
14
15QT_BEGIN_NAMESPACE
16
17QT_IMPL_METATYPE_EXTERN_TAGGED(QNearFieldTarget::RequestId, QNearFieldTarget__RequestId)
18
19/*!
20 \class QNearFieldTarget
21 \brief The QNearFieldTarget class provides an interface for communicating with a target
22 device.
23
24 \ingroup connectivity-nfc
25 \inmodule QtNfc
26 \since 5.2
27
28 QNearFieldTarget provides a generic interface for communicating with an NFC target device.
29 Both NFC Forum devices and NFC Forum Tag targets are supported by this class. All target
30 specific classes subclass this class.
31
32 The type() function can be used to get the type of the target device. The uid() function
33 returns the unique identifier of the target. The AccessMethods flags returns from the
34 accessMethods() function can be tested to determine which access methods are supported by the
35 target.
36
37 If the target supports NdefAccess, hasNdefMessage() can be called to test if the target has a
38 stored NDEF message, readNdefMessages() and writeNdefMessages() functions can be used to get
39 and set the NDEF message.
40
41 If the target supports TagTypeSpecificAccess, sendCommand() can be used to send a single
42 proprietary command to the target and retrieve the response.
43*/
44
45/*!
46 \enum QNearFieldTarget::Type
47
48 This enum describes the type of tag the target is detected as.
49
50 \value ProprietaryTag An unidentified proprietary target tag.
51 \value NfcTagType1 An NFC tag type 1 target.
52 \value NfcTagType2 An NFC tag type 2 target.
53 \value NfcTagType3 An NFC tag type 3 target.
54 \value NfcTagType4 An NFC tag type 4 target. This value is used if the NfcTagType4
55 cannot be further refined by NfcTagType4A or NfcTagType4B below.
56 \value NfcTagType4A An NFC tag type 4 target based on ISO/IEC 14443-3A.
57 \value NfcTagType4B An NFC tag type 4 target based on ISO/IEC 14443-3B.
58 \value MifareTag A Mifare target.
59*/
60
61/*!
62 \enum QNearFieldTarget::AccessMethod
63
64 This enum describes the access methods a near field target supports.
65
66 \value UnknownAccess The target supports an unknown access type.
67 \value NdefAccess The target supports reading and writing NDEF messages using
68 readNdefMessages() and writeNdefMessages().
69 \value TagTypeSpecificAccess The target supports sending tag type specific commands using
70 sendCommand().
71 \value AnyAccess The target supports any of the known access types.
72*/
73
74/*!
75 \enum QNearFieldTarget::Error
76
77 This enum describes the error codes that a near field target reports.
78
79 \value NoError No error has occurred.
80 \value UnknownError An unidentified error occurred.
81 \value UnsupportedError The requested operation is unsupported by this near field
82 target.
83 \value TargetOutOfRangeError The target is no longer within range.
84 \value NoResponseError The target did not respond.
85 \value ChecksumMismatchError The checksum has detected a corrupted response.
86 \value InvalidParametersError Invalid parameters were passed to a tag type specific function.
87 \value ConnectionError Failed to connect to the target.
88 \value NdefReadError Failed to read NDEF messages from the target.
89 \value NdefWriteError Failed to write NDEF messages to the target.
90 \value CommandError Failed to send a command to the target.
91 \value TimeoutError The request could not be completed within the time
92 specified in waitForRequestCompleted().
93*/
94
95/*!
96 \fn void QNearFieldTarget::disconnected()
97
98 This signal is emitted when the near field target moves out of proximity.
99*/
100
101/*!
102 \fn void QNearFieldTarget::ndefMessageRead(const QNdefMessage &message)
103
104 This signal is emitted when a complete NDEF \a message has been read from the target.
105
106 \sa readNdefMessages()
107*/
108
109/*!
110 \fn void QNearFieldTarget::requestCompleted(const QNearFieldTarget::RequestId &id)
111
112 This signal is emitted when a request \a id completes.
113
114 \sa sendCommand()
115*/
116
117/*!
118 \fn void QNearFieldTarget::error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id)
119
120 This signal is emitted when an error occurs while processing request \a id. The \a error
121 parameter describes the error.
122*/
123
124/*!
125 \class QNearFieldTarget::RequestId
126 \inmodule QtNfc
127 \inheaderfile QNearFieldTarget
128 \brief A request id handle.
129*/
130
131/*!
132 Constructs a new invalid request id handle.
133*/
134QNearFieldTarget::RequestId::RequestId()
135{
136}
137
138/*!
139 Constructs a new request id handle that is a copy of \a other.
140*/
141QNearFieldTarget::RequestId::RequestId(const RequestId &other)
142: d(other.d)
143{
144}
145
146/*!
147 \internal
148*/
149QNearFieldTarget::RequestId::RequestId(RequestIdPrivate *p)
150: d(p)
151{
152}
153
154/*!
155 Destroys the request id handle.
156*/
157QNearFieldTarget::RequestId::~RequestId()
158{
159}
160
161/*!
162 Returns \c true if this is a valid request id; otherwise returns \c false.
163*/
164bool QNearFieldTarget::RequestId::isValid() const
165{
166 return d;
167}
168
169/*!
170 Returns the current reference count of the request id.
171*/
172int QNearFieldTarget::RequestId::refCount() const
173{
174 if (d)
175 return d->ref.loadRelaxed();
176
177 return 0;
178}
179
180/*!
181 \internal
182*/
183bool QNearFieldTarget::RequestId::operator<(const RequestId &other) const
184{
185 return std::less<const RequestIdPrivate*>()(d.constData(), other.d.constData());
186}
187
188/*!
189 \internal
190*/
191bool QNearFieldTarget::RequestId::operator==(const RequestId &other) const
192{
193 return d == other.d;
194}
195
196/*!
197 \internal
198*/
199bool QNearFieldTarget::RequestId::operator!=(const RequestId &other) const
200{
201 return d != other.d;
202}
203
204/*!
205 Assigns a copy of \a other to this request id and returns a reference to this request id.
206*/
207QNearFieldTarget::RequestId &QNearFieldTarget::RequestId::operator=(const RequestId &other)
208{
209 d = other.d;
210 return *this;
211}
212
213/*!
214 Constructs a new near field target with \a parent.
215*/
216QNearFieldTarget::QNearFieldTarget(QObject *parent)
217: QNearFieldTarget(new QNearFieldTargetPrivate(this), parent)
218{
219}
220
221/*!
222 Destroys the near field target.
223*/
224QNearFieldTarget::~QNearFieldTarget()
225{
226 Q_D(QNearFieldTarget);
227
228 d->disconnect();
229}
230
231/*!
232 Returns the UID of the near field target.
233
234 \note On iOS, this function returns an empty QByteArray for
235 a near field target discovered using NdefAccess method.
236
237 \sa QNearFieldTarget::AccessMethod
238*/
239QByteArray QNearFieldTarget::uid() const
240{
241 Q_D(const QNearFieldTarget);
242
243 return d->uid();
244}
245
246/*!
247 Returns the type of tag type of this near field target.
248*/
249QNearFieldTarget::Type QNearFieldTarget::type() const
250{
251 Q_D(const QNearFieldTarget);
252
253 return d->type();
254}
255
256/*!
257 Returns the access methods supported by this near field target.
258*/
259QNearFieldTarget::AccessMethods QNearFieldTarget::accessMethods() const
260{
261 Q_D(const QNearFieldTarget);
262
263 return d->accessMethods();
264}
265
266/*!
267 \since 5.9
268
269 Closes the connection to the target to enable communication with the target
270 from a different instance. The connection will also be closed, when the
271 QNearFieldTarget is destroyed. A connection to the target device is
272 (re)created to process a command or read/write a NDEF messages.
273
274 Returns \c true only if an existing connection was successfully closed;
275 otherwise returns \c false.
276*/
277bool QNearFieldTarget::disconnect()
278{
279 Q_D(QNearFieldTarget);
280
281 return d->disconnect();
282}
283
284/*!
285 Returns \c true if at least one NDEF message is stored on the near field
286 target; otherwise returns \c false.
287*/
288bool QNearFieldTarget::hasNdefMessage()
289{
290 Q_D(QNearFieldTarget);
291
292 return d->hasNdefMessage();
293}
294
295/*!
296 Starts reading NDEF messages stored on the near field target. Returns a request id which can
297 be used to track the completion status of the request. An invalid request id will be returned
298 if the target does not support reading NDEF messages.
299
300 An ndefMessageRead() signal will be emitted for each NDEF message. The requestCompleted()
301 signal will be emitted was all NDEF messages have been read. The error() signal is emitted if
302 an error occurs.
303
304 \note An attempt to read an NDEF message from a tag, that is in INITIALIZED
305 state as defined by NFC Forum, will fail with the \l NdefReadError, as the
306 tag is formatted to support NDEF but does not contain a message yet.
307*/
308QNearFieldTarget::RequestId QNearFieldTarget::readNdefMessages()
309{
310 Q_D(QNearFieldTarget);
311
312 return d->readNdefMessages();
313}
314
315/*!
316 Writes the NDEF messages in \a messages to the target. Returns a request id which can be used
317 to track the completion status of the request. An invalid request id will be returned if the
318 target does not support reading NDEF messages.
319
320 The requestCompleted() signal will be emitted when the write operation completes
321 successfully; otherwise the error() signal is emitted.
322*/
323QNearFieldTarget::RequestId QNearFieldTarget::writeNdefMessages(const QList<QNdefMessage> &messages)
324{
325 Q_D(QNearFieldTarget);
326
327 return d->writeNdefMessages(messages);
328}
329
330/*!
331 \since 5.9
332
333 Returns the maximum number of bytes that can be sent with sendCommand. 0 will
334 be returned if the target does not support sending tag type specific commands.
335
336 \sa sendCommand()
337*/
338int QNearFieldTarget::maxCommandLength() const
339{
340 Q_D(const QNearFieldTarget);
341
342 return d->maxCommandLength();
343}
344
345/*!
346 Sends \a command to the near field target. Returns a request id which can be used to track the
347 completion status of the request. An invalid request id will be returned if the target does not
348 support sending tag type specific commands.
349
350 The requestCompleted() signal will be emitted on successful completion of the request;
351 otherwise the error() signal will be emitted.
352
353 Once the request completes successfully the response can be retrieved from the
354 requestResponse() function. The response of this request will be a QByteArray.
355
356 \sa requestCompleted(), waitForRequestCompleted()
357*/
358QNearFieldTarget::RequestId QNearFieldTarget::sendCommand(const QByteArray &command)
359{
360 Q_D(QNearFieldTarget);
361
362 return d->sendCommand(command);
363}
364
365/*!
366 Waits up to \a msecs milliseconds for the request \a id to complete.
367 Returns \c true if the request completes successfully and the
368 requestCompeted() signal is emitted; otherwise returns \c false.
369*/
370bool QNearFieldTarget::waitForRequestCompleted(const RequestId &id, int msecs)
371{
372 Q_D(QNearFieldTarget);
373
374 return d->waitForRequestCompleted(id, msecs);
375}
376
377/*!
378 Returns the decoded response for request \a id. If the request is unknown or has not yet been
379 completed an invalid QVariant is returned.
380*/
381QVariant QNearFieldTarget::requestResponse(const RequestId &id) const
382{
383 Q_D(const QNearFieldTarget);
384
385 return d->requestResponse(id);
386}
387
388/*!
389 \internal
390*/
391QNearFieldTarget::QNearFieldTarget(QNearFieldTargetPrivate *backend, QObject *parent)
392: QObject(parent), d_ptr(backend)
393{
394 Q_D(QNearFieldTarget);
395
396 d->q_ptr = this;
397 d->setParent(this);
398
399 qRegisterMetaType<QNearFieldTarget::RequestId>();
400 qRegisterMetaType<QNearFieldTarget::Error>();
401 qRegisterMetaType<QNdefMessage>();
402
403 connect(sender: d, signal: &QNearFieldTargetPrivate::disconnected,
404 context: this, slot: &QNearFieldTarget::disconnected);
405 connect(sender: d, signal: &QNearFieldTargetPrivate::ndefMessageRead,
406 context: this, slot: &QNearFieldTarget::ndefMessageRead);
407 connect(sender: d, signal: &QNearFieldTargetPrivate::requestCompleted,
408 context: this, slot: &QNearFieldTarget::requestCompleted);
409 connect(sender: d, signal: &QNearFieldTargetPrivate::error,
410 context: this, slot: &QNearFieldTarget::error);
411}
412
413QT_END_NAMESPACE
414
415#include "moc_qnearfieldtarget.cpp"
416

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