7#include <QtCore/QLoggingCategory>
8#include <QtCore/QTimer>
10#if defined(Q_OS_DARWIN)
11# define SCARD_ATTR_MAXINPUT 0x0007A007
12#elif !defined(Q_OS_WIN)
43 if (!m_card->isValid() || m_card->m_inAutoTransaction)
46 auto ret = SCardBeginTransaction(m_card->m_handle);
47 if (
ret != SCARD_S_SUCCESS) {
56QPcscCard::Transaction::~Transaction()
59 if (!m_initiated || !m_card->isValid())
62 auto ret = SCardEndTransaction(m_card->m_handle, SCARD_LEAVE_CARD);
64 if (
ret != SCARD_S_SUCCESS) {
75 m_keepAliveTimer =
new QTimer(
this);
79 m_ioPci.dwProtocol = protocol;
80 m_ioPci.cbPciLength =
sizeof(m_ioPci);
83 m_tagDetectionFsm = std::make_unique<QNfcTagType4NdefFsm>();
85 performNdefDetection();
94void QPcscCard::performNdefDetection()
101 Transaction transaction(
this);
103 auto action = m_tagDetectionFsm->detectNdefSupport();
106 auto command = m_tagDetectionFsm->getCommand(action);
109 auto result = sendCommand(command, NoAutoTransaction);
110 action = m_tagDetectionFsm->provideResponse(
result.response);
114 qCDebug(QT_NFC_PCSC) <<
"NDEF detection result" << action;
117 qCDebug(QT_NFC_PCSC) <<
"NDEF supported:" << m_supportsNdef;
129 SCardDisconnect(m_handle, m_inAutoTransaction ? SCARD_RESET_CARD : SCARD_LEAVE_CARD);
132 m_inAutoTransaction =
false;
156 QPcscCard::AutoTransaction autoTransaction)
161 if (!m_inAutoTransaction && autoTransaction == StartAutoTransaction) {
162 qCDebug(QT_NFC_PCSC) <<
"Starting transaction";
165 auto ret = SCardBeginTransaction(m_handle);
166 if (
ret != SCARD_S_SUCCESS) {
171 m_inAutoTransaction =
true;
172 m_keepAliveTimer->
start();
176 result.response.resize(0xFFFF + 2);
177 DWORD recvLength =
result.response.size();
181 result.ret = SCardTransmit(m_handle, &m_ioPci,
reinterpret_cast<LPCBYTE
>(command.
constData()),
182 command.
size(),
nullptr,
183 reinterpret_cast<LPBYTE
>(
result.response.data()), &recvLength);
184 if (
result.ret != SCARD_S_SUCCESS) {
189 result.response.resize(recvLength);
196void QPcscCard::onKeepAliveTimeout()
198 if (!m_isValid || !m_inAutoTransaction) {
199 m_keepAliveTimer->
stop();
224 if (!m_supportsNdef) {
229 Transaction transaction(
this);
233 auto nextState = m_tagDetectionFsm->readMessages();
237 auto command = m_tagDetectionFsm->getCommand(nextState);
240 auto result = sendCommand(command, NoAutoTransaction);
241 nextState = m_tagDetectionFsm->provideResponse(
result.response);
244 auto message = m_tagDetectionFsm->getMessage(nextState);
251 qCDebug(QT_NFC_PCSC) <<
"Final state:" << nextState;
272 if (m_inAutoTransaction) {
275 ret = SCardEndTransaction(m_handle, SCARD_RESET_CARD);
276 if (
ret != SCARD_S_SUCCESS) {
282 m_inAutoTransaction =
false;
285 DWORD activeProtocol;
286 ret = SCardReconnect(m_handle, SCARD_SHARE_SHARED, SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1,
287 SCARD_LEAVE_CARD, &activeProtocol);
288 if (
ret != SCARD_S_SUCCESS) {
313 auto result = sendCommand(command, StartAutoTransaction);
330 if (!m_supportsNdef) {
335 Transaction transaction(
this);
337 auto nextState = m_tagDetectionFsm->writeMessages(messages);
340 auto command = m_tagDetectionFsm->getCommand(nextState);
342 auto result = sendCommand(command, NoAutoTransaction);
343 nextState = m_tagDetectionFsm->provideResponse(
result.response);
382 auto ret = SCardStatus(m_handle,
nullptr,
nullptr, &
state,
nullptr,
nullptr,
nullptr);
383 if (
ret != SCARD_S_SUCCESS) {
391 return (
state & SCARD_PRESENT) != 0;
400 static constexpr int DefaultMaxInputLength = 261;
403 DWORD attrSize =
sizeof(maxInput);
404 auto ret = SCardGetAttrib(m_handle, SCARD_ATTR_MAXINPUT,
reinterpret_cast<LPBYTE
>(&maxInput),
406 if (
ret != SCARD_S_SUCCESS) {
408 return DefaultMaxInputLength;
411 if (attrSize !=
sizeof(maxInput)) {
412 qCWarning(QT_NFC_PCSC) <<
"Unexpected attribute size for SCARD_ATTR_MAXINPUT:" << attrSize;
413 return DefaultMaxInputLength;
416 return static_cast<int>(maxInput);
qsizetype size() const noexcept
Returns the number of bytes in this byte array.
const char * constData() const noexcept
Returns a pointer to the const data stored in the byte array.
QByteArray toHex(char separator='\0') const
Returns a hex encoded copy of the byte array.
\inmodule QtNfc \inheaderfile QNearFieldTarget
static QMetaObject::Connection connect(const QObject *sender, const char *signal, const QObject *receiver, const char *member, Qt::ConnectionType=Qt::AutoConnection)
\threadsafe
void deleteLater()
\threadsafe
void onReadNdefMessagesRequest(const QNearFieldTarget::RequestId &request)
void onDisconnectRequest()
void requestCompleted(const QNearFieldTarget::RequestId &request, QNearFieldTarget::Error reason, const QVariant &result)
QPcscCard(SCARDHANDLE handle, DWORD protocol, QObject *parent=nullptr)
void onWriteNdefMessagesRequest(const QNearFieldTarget::RequestId &request, const QList< QNdefMessage > &messages)
void onSendCommandRequest(const QNearFieldTarget::RequestId &request, const QByteArray &command)
void ndefMessageRead(const QNdefMessage &message)
Q_INVOKABLE void enableAutodelete()
void start(int msec)
Starts or restarts the timer with a timeout interval of msec milliseconds.
void setInterval(int msec)
void stop()
Stops the timer.
void timeout(QPrivateSignal)
This signal is emitted when the timer times out.
constexpr uint8_t GetData
QByteArray build(uint8_t cla, uint8_t ins, uint8_t p1, uint8_t p2, QByteArrayView data, uint16_t ne=0)
QString errorMessage(LONG error)
Combined button and popup list for selecting options.
QTextStream & hex(QTextStream &stream)
Calls QTextStream::setIntegerBase(16) on stream and returns stream.
#define qCWarning(category,...)
#define qCDebug(category,...)
#define Q_DECLARE_LOGGING_CATEGORY(name)
GLuint64 GLenum void * handle
GLuint GLsizei const GLchar * message
static QT_BEGIN_NAMESPACE constexpr int KeepAliveIntervalMs
QNetworkRequest request(url)
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent