9#import <CoreNFC/NFCNDEFReaderSession.h>
10#import <CoreNFC/NFCReaderSession.h>
11#import <CoreNFC/NFCTagReaderSession.h>
12#import <CoreNFC/NFCISO7816Tag.h>
13#import <CoreNFC/NFCTag.h>
15#include <QtCore/qapplicationstatic.h>
16#include <QtCore/qloggingcategory.h>
28 id some =
static_cast<id>(
obj);
30 if ([some conformsToProtocol:
@protocol(NFCNDEFTag)])
32 else if ([some conformsToProtocol:
@protocol(NFCTag)])
55 Q_ASSERT([
id(
tag) conformsToProtocol:
@protocol(NFCNDEFTag)]);
58 notifier = [qtDelegate ndefNotifier];
79 ndefOperations.clear();
89 sessionDelegate = nil;
96 if (!nfcTag || isNdefTag())
99 if (@available(
iOS 13, *)) {
103 return QByteArray::fromNSData(iso7816Tag.identifier);
111 if (!nfcTag || isNdefTag())
114 if (@available(
iOS 13, *)) {
118 if (
tag.type != NFCTagTypeISO7816Compatible || iso7816Tag == nil)
121 if (iso7816Tag.historicalBytes != nil && iso7816Tag.applicationData == nil)
124 if (iso7816Tag.historicalBytes == nil && iso7816Tag.applicationData != nil)
138 if (@available(
iOS 13, *)) {
140 if (
tag && [
tag conformsToProtocol:@protocol(NFCISO7816Tag)])
178 return hasNDEFMessage;
183 hasNDEFMessage =
false;
188 qCWarning(QT_IOS_NFC,
"Target does not allow to read NDEF messages, "
189 "was not detected as NDEF tag by the reader session?");
198 ndefOperations.push_back(op);
209 qCWarning(QT_IOS_NFC,
"Target does not allow to write NDEF messages, "
210 "was not detected as NDEF tag by the reader session?");
215 if (messages.
size() != 1) {
220 qCWarning(QT_IOS_NFC,
"Only one NDEF message per request ID can be written");
229 ndefOperations.push_back(op);
237 if (requestInProgress.
isValid())
240 const auto tagIsAvailable = [
this](
auto tag) {
241 return tag && (!connected ||
tag.available);
247 if (@available(
iOS 13, *))
248 return tagIsAvailable(
static_cast<id<NFCTag>>(nfcTag.get()));
255 if (connected || requestInProgress.
isValid())
259 return connected =
true;
264 if (@available(
iOS 13, *)) {
265 requestInProgress = queue.
head().first;
267 NFCTagReaderSession* session =
tag.session;
268 [session connectToTag:
tag completionHandler: ^(NSError*
error){
269 const bool success =
error == nil;
289bool QNearFieldTargetPrivateImpl::isNdefTag()
const
291 return [
static_cast<id>(nfcTag.get()) conformsToProtocol:@protocol(NFCNDEFTag)];
294void QNearFieldTargetPrivateImpl::onTargetCheck()
314QNdefMessage ndefToQtNdefMessage(NFCNDEFMessage *nativeMessage)
320 for (NFCNDEFPayload *ndefRecord
in nativeMessage.records) {
322 if (ndefRecord.typeNameFormat != NFCTypeNameFormatUnchanged)
324 if (ndefRecord.identifier)
325 qtNdefRecord.
setId(QByteArray::fromNSData(ndefRecord.identifier));
327 qtNdefRecord.
setType(QByteArray::fromNSData(ndefRecord.type));
328 if (ndefRecord.payload)
329 qtNdefRecord.
setPayload(QByteArray::fromNSData(ndefRecord.payload));
338void QNearFieldTargetPrivateImpl::onExecuteRequest()
340 if (!nfcTag || requestInProgress.
isValid())
344 if (ndefOperations.empty())
352 const auto op = ndefOperations.front();
353 ndefOperations.pop_front();
360 auto *cbNotifier = guard.get();
367 this, &QNearFieldTargetPrivateImpl::messageRead,
371 [ndefTag readNDEFWithCompletionHandler:^(NFCNDEFMessage * _Nullable msg, NSError * _Nullable err) {
372 const std::unique_ptr<QNfcNdefNotifier> notifierGuard(cbNotifier);
374 NSLog(
@"Reading NDEF messaged ended with error: %@", err);
379 const QNdefMessage ndefMessage(ndefToQtNdefMessage(msg));
384 this, &QNearFieldTargetPrivateImpl::messageWritten,
390 NFCNDEFMessage *ndefMessage = [NFCNDEFMessage ndefMessageWithData:ndefData];
393 [ndefTag writeNDEF:ndefMessage completionHandler:^(NSError *err) {
394 const std::unique_ptr<QNfcNdefNotifier> notifierGuard(cbNotifier);
396 NSLog(
@"Writing NDEF messaged ended with error: %@", err);
408 if (@available(
iOS 13, *)) {
412 requestInProgress =
request.first;
414 auto *apdu = [[[NFCISO7816APDU alloc] initWithData:
request.second.toNSData()] autorelease];
415 [
tag sendCommandAPDU: apdu completionHandler: ^(NSData* responseData, uint8_t sw1, uint8_t sw2, NSError*
error){
416 QByteArray recvBuffer = QByteArray::fromNSData(responseData);
417 recvBuffer +=
static_cast<char>(sw1);
418 recvBuffer +=
static_cast<char>(sw2);
419 const bool success =
error == nil;
420 responseProvider->provideResponse(
request.first, success, recvBuffer);
443 hasNDEFMessage =
message.size() != 0;
446 requestInProgress = {};
454 requestInProgress = {};
qsizetype size() const noexcept
bool isEmpty() const noexcept
void push_back(parameter_type t)
The QNdefMessage class provides an NFC NDEF message.
Q_NFC_EXPORT QByteArray toByteArray() const
Returns the NDEF message as a byte array.
The QNdefRecord class provides an NFC NDEF record.
void setPayload(const QByteArray &payload)
Sets the payload of the NDEF record to payload.
void setId(const QByteArray &id)
Sets the id of the NDEF record to id.
TypeNameFormat
This enum describes the type name format of an NDEF record.
void setType(const QByteArray &type)
Sets the type of the NDEF record to type.
void setTypeNameFormat(TypeNameFormat typeNameFormat)
Sets the type name format of the NDEF record to typeNameFormat.
void targetLost(QNearFieldTargetPrivateImpl *target)
QNearFieldTarget::RequestId writeNdefMessages(const QList< QNdefMessage > &messages) override
int maxCommandLength() const override
QNearFieldTarget::RequestId readNdefMessages() override
~QNearFieldTargetPrivateImpl() override
QNearFieldTargetPrivateImpl(QJniObject intent, const QByteArray uid, QObject *parent=nullptr)
void ndefMessageRead(const QNdefMessage &message, const QNearFieldTarget::RequestId &id)
QNearFieldTarget::Type type() const override
QNearFieldTarget::RequestId sendCommand(const QByteArray &command) override
QNearFieldTarget::AccessMethods accessMethods() const override
bool hasNdefMessage() override
QTimer * targetCheckTimer
QByteArray uid() const override
void error(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id)
virtual void setResponseForRequest(const QNearFieldTarget::RequestId &id, const QVariant &response, bool emitRequestCompleted=true)
void requestCompleted(const QNearFieldTarget::RequestId &id)
void reportError(QNearFieldTarget::Error error, const QNearFieldTarget::RequestId &id)
\inmodule QtNfc \inheaderfile QNearFieldTarget
bool isValid() const
Returns true if this is a valid request id; otherwise returns false.
The QNearFieldTarget class provides an interface for communicating with a target device.
Type
This enum describes the type of tag the target is detected as.
Error
This enum describes the error codes that a near field target reports.
void tagError(QNearFieldTarget::Error code, QNearFieldTarget::RequestId request)
void ndefMessageRead(const QNdefMessage &message, QNearFieldTarget::RequestId request)
void ndefMessageWritten(QNearFieldTarget::RequestId request)
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
static bool disconnect(const QObject *sender, const char *signal, const QObject *receiver, const char *member)
\threadsafe
void enqueue(const T &t)
Adds value t to the tail of the queue.
T & head()
Returns a reference to the queue's head item.
T dequeue()
Removes the head item in the queue and returns it.
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void stop()
Stops the timer.
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
void responseReceived(QNearFieldTarget::RequestId requestId, bool success, QByteArray recvBuffer)
Combined button and popup list for selecting options.
#define Q_APPLICATION_STATIC(TYPE, NAME,...)
AudioChannelLayoutTag tag
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char return DBusMessage return DBusMessage const char return DBusMessage dbus_bool_t return DBusMessage dbus_uint32_t return DBusMessage void
DBusConnection const char DBusError * error
QNearFieldTarget::RequestId requestId
QT_BEGIN_NAMESPACE dispatch_queue_t qt_Nfc_Queue()
#define qCWarning(category,...)
GLuint GLsizei const GLchar * message
QNetworkRequest request(url)
QNearFieldTarget::RequestId requestId
enum NdefOperation::Type type
void operator()(void *tag)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent