@@ -76,7 +76,7 @@ QHash<DRIVER_FEATURES,quint32> QPCSCReader::Private::features()
7676 for (const auto &f: feature)
7777 {
7878 if (f.tag )
79- featuresList[DRIVER_FEATURES ( f.tag ) ] = qFromBigEndian<quint32>(f.value );
79+ featuresList[f.tag ] = qFromBigEndian<quint32>(f.value );
8080 }
8181 return featuresList;
8282}
@@ -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,19 +203,19 @@ 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 ();
200- updateState ();
209+ if (parent->d ->context )
210+ SC (GetStatusChange, d->d ->context , 0 , &d->state , 1U );
201211}
202212
203213QPCSCReader::~QPCSCReader ()
204214{
205- disconnect ();
206- d->d ->lock [d->reader ]->unlock ();
215+ if (d->isTransacted )
216+ SC (EndTransaction, d->card , SCARD_LEAVE_CARD);
217+ if (d->card )
218+ SC (Disconnect, d->card , SCARD_LEAVE_CARD);
207219 delete d;
208220}
209221
@@ -212,29 +224,12 @@ QByteArray QPCSCReader::atr() const
212224 return QByteArray::fromRawData ((const char *)d->state .rgbAtr , int (d->state .cbAtr )).toHex ().toUpper ();
213225}
214226
215- bool QPCSCReader::beginTransaction ()
216- {
217- return d->isTransacted = SC (BeginTransaction, d->card ) == SCARD_S_SUCCESS;
218- }
219-
220227bool QPCSCReader::connect (Connect connect, Mode mode)
221228{
222- LONG err = SC (Connect, d->d ->context , d->state .szReader , connect, mode, &d->card , &d->io .dwProtocol );
223- updateState ();
224- return err == SCARD_S_SUCCESS;
225- }
226-
227- void QPCSCReader::disconnect ( Reset reset )
228- {
229- if (d->isTransacted )
230- SC (EndTransaction, d->card , reset);
231- d->isTransacted = false ;
232- if ( d->card )
233- SC (Disconnect, d->card , reset);
234- d->io .dwProtocol = SCARD_PROTOCOL_UNDEFINED;
235- d->card = {};
236- d->featuresList .clear ();
237- updateState ();
229+ if (SC (Connect, d->d ->context , d->state .szReader , connect, mode, &d->card , &d->io .dwProtocol ) != SCARD_S_SUCCESS)
230+ return false ;
231+ d->isTransacted = SC (BeginTransaction, d->card ) == SCARD_S_SUCCESS;
232+ return true ;
238233}
239234
240235bool QPCSCReader::isPinPad () const
@@ -272,7 +267,7 @@ QHash<QPCSCReader::Properties, int> QPCSCReader::properties() const
272267 int tag = *p++, len = *p++, value = 0 ;
273268 for (int i = 0 ; i < len; ++i)
274269 value |= *p++ << 8 * i;
275- properties[ Properties (tag)] = value;
270+ properties. emplace ( Properties (tag), value) ;
276271 }
277272 }
278273 return properties;
@@ -303,7 +298,7 @@ QPCSCReader::Result QPCSCReader::transfer( const QByteArray &apdu ) const
303298 case 0x6100 : // Read more
304299 {
305300 QByteArray cmd ( " \x00\xC0\x00\x00\x00 " , 5 );
306- cmd[4 ] = data. at ( int (size - 1 ) );
301+ cmd[4 ] = char (result. SW );
307302 Result result2 = transfer ( cmd );
308303 result2.data .prepend (result.data );
309304 return result2;
@@ -397,16 +392,3 @@ QPCSCReader::Result QPCSCReader::transferCTL(const QByteArray &apdu, bool verify
397392 if (!result.data .isEmpty ()) qCDebug (APDU).nospace ().noquote () << result.data .toHex ();
398393 return result;
399394}
400-
401- bool QPCSCReader::updateState ( quint32 msec )
402- {
403- if (!d->d ->context )
404- return false ;
405- d->state .dwCurrentState = d->state .dwEventState ;
406- switch (SC (GetStatusChange, d->d ->context , msec, &d->state , 1U ))
407- {
408- case LONG (SCARD_S_SUCCESS): return true ;
409- case LONG (SCARD_E_TIMEOUT): return msec == 0 ;
410- default : return false ;
411- }
412- }
0 commit comments