2727#include <array>
2828#include <cstring>
2929
30- Q_LOGGING_CATEGORY(APDU,"QPCSC.APDU")
31- Q_LOGGING_CATEGORY(SCard,"QPCSC.SCard")
30+ static Q_LOGGING_CATEGORY(APDU,"QPCSC.APDU")
31+ static Q_LOGGING_CATEGORY(SCard,"QPCSC.SCard")
3232
3333static quint16 toUInt16(const QByteArray &data, int size)
3434{
@@ -94,10 +94,12 @@ QPCSC::QPCSC()
9494QPCSC::~QPCSC()
9595{
9696 requestInterruption();
97+ d->sleepCond.wakeAll();
98+ if(d->thread)
99+ SC(Cancel, d->thread);
97100 wait();
98- if( d->context )
101+ if(d->context)
99102 SC(ReleaseContext, d->context);
100- qDeleteAll(d->lock);
101103 delete d;
102104}
103105
@@ -138,23 +140,30 @@ void QPCSC::run()
138140 std::vector<SCARD_READERSTATE> list;
139141 while(!isInterruptionRequested())
140142 {
141- if(!pcsc.serviceRunning())
142- {
143- sleep(5);
144- continue;
145- }
146143 // "\\?PnP?\Notification" does not work on macOS
147144 QByteArray data = pcsc.rawReaders();
148145 if(data.isEmpty())
149146 {
150- sleep(5);
147+ QMutexLocker locker(&d->sleepMutex);
148+ if (isInterruptionRequested())
149+ break;
150+ d->sleepCond.wait(&d->sleepMutex, 5000);
151151 continue;
152152 }
153153 for(const char *name = data.constData(); *name; name += strlen(name) + 1)
154154 {
155155 if(std::none_of(list.cbegin(), list.cend(), [&name](const SCARD_READERSTATE &state) { return strcmp(state.szReader, name) == 0; }))
156156 list.push_back({ strdup(name), nullptr, 0, 0, 0, {} });
157157 }
158+ if(list.empty())
159+ {
160+ QMutexLocker locker(&d->sleepMutex);
161+ if (isInterruptionRequested())
162+ break;
163+ d->sleepCond.wait(&d->sleepMutex, 5000);
164+ continue;
165+ }
166+ d->thread = pcsc.d->context;
158167 if(SC(GetStatusChange, pcsc.d->context, 5*1000U, list.data(), DWORD(list.size())) != SCARD_S_SUCCESS)
159168 continue;
160169 for(auto i = list.begin(); i != list.end(); )
@@ -164,6 +173,8 @@ void QPCSC::run()
164173 ++i;
165174 continue;
166175 }
176+ if((i->dwCurrentState & SCARD_STATE_PRESENT) != (i->dwEventState & SCARD_STATE_PRESENT))
177+ Q_EMIT cardChanged();
167178 i->dwCurrentState = i->dwEventState;
168179 qCDebug(SCard) << "New state: " << QString::fromLocal8Bit(i->szReader) << stateToString(i->dwCurrentState);
169180 Q_EMIT statusChanged(QString::fromLocal8Bit(i->szReader), stateToString(i->dwCurrentState));
@@ -176,6 +187,7 @@ void QPCSC::run()
176187 ++i;
177188 }
178189 }
190+ d->thread = {};
179191}
180192
181193bool QPCSC::serviceRunning() const
@@ -191,9 +203,6 @@ bool QPCSC::serviceRunning() const
191203QPCSCReader::QPCSCReader( const QString &reader, QPCSC *parent )
192204 : d(new Private)
193205{
194- if(!parent->d->lock.contains(reader))
195- parent->d->lock[reader] = new QMutex();
196- parent->d->lock[reader]->lock();
197206 d->d = parent->d;
198207 d->reader = reader.toUtf8();
199208 d->state.szReader = d->reader.constData();
@@ -203,7 +212,6 @@ QPCSCReader::QPCSCReader( const QString &reader, QPCSC *parent )
203212QPCSCReader::~QPCSCReader()
204213{
205214 disconnect();
206- d->d->lock[d->reader]->unlock();
207215 delete d;
208216}
209217
@@ -218,21 +226,16 @@ bool QPCSCReader::beginTransaction()
218226}
219227
220228bool QPCSCReader::connect(Connect connect, Mode mode)
221- {
222- return connectEx(connect, mode) == SCARD_S_SUCCESS;
223- }
224-
225- quint32 QPCSCReader::connectEx(Connect connect, Mode mode)
226229{
227230 LONG err = SC(Connect, d->d->context, d->state.szReader, connect, mode, &d->card, &d->io.dwProtocol);
228231 updateState();
229- return quint32( err) ;
232+ return err == SCARD_S_SUCCESS ;
230233}
231234
232235void QPCSCReader::disconnect( Reset reset )
233236{
234- if(d->isTransacted)
235- endTransaction() ;
237+ if(d->isTransacted && SC(EndTransaction, d->card, Reset::LeaveCard) == SCARD_S_SUCCESS )
238+ d->isTransacted = false ;
236239 if( d->card )
237240 SC(Disconnect, d->card, reset);
238241 d->io.dwProtocol = SCARD_PROTOCOL_UNDEFINED;
@@ -241,14 +244,6 @@ void QPCSCReader::disconnect( Reset reset )
241244 updateState();
242245}
243246
244- bool QPCSCReader::endTransaction( Reset reset )
245- {
246- bool result = SC(EndTransaction, d->card, reset) == SCARD_S_SUCCESS;
247- if(result)
248- d->isTransacted = false;
249- return result;
250- }
251-
252247bool QPCSCReader::isPinPad() const
253248{
254249 if(d->reader.contains("HID Global OMNIKEY 3x21 Smart Card Reader") ||
@@ -290,15 +285,6 @@ QHash<QPCSCReader::Properties, int> QPCSCReader::properties() const
290285 return properties;
291286}
292287
293- bool QPCSCReader::reconnect( Reset reset, Mode mode )
294- {
295- if( !d->card )
296- return false;
297- LONG err = SC(Reconnect, d->card, DWORD(SCARD_SHARE_SHARED), mode, reset, &d->io.dwProtocol);
298- updateState();
299- return err == SCARD_S_SUCCESS;
300- }
301-
302288QStringList QPCSCReader::state() const
303289{
304290 return stateToString(d->state.dwEventState);
0 commit comments