|
|
|
@ -70,10 +70,6 @@ |
|
|
|
|
avoid the ugly M$-C-quirks. This interface is memory clean. |
|
|
|
|
@todo: Not implemented, not supported: |
|
|
|
|
- SCardGetStatusChange(hContext, 0, rgReaderStates, 1); |
|
|
|
|
- SCardReconnect(hCard, SCARD_SHARE_SHARED, |
|
|
|
|
SCARD_PROTOCOL_T0 | SCARD_PROTOCOL_T1, |
|
|
|
|
SCARD_LEAVE_CARD, |
|
|
|
|
&dwActiveProtocol); |
|
|
|
|
- several other |
|
|
|
|
I do not need these, and I don't know the usecase where they are |
|
|
|
|
required. If you need something that is not yet supported, please |
|
|
|
@ -312,7 +308,8 @@ namespace pcsc { |
|
|
|
|
in.size(), |
|
|
|
|
0, buff, &len), |
|
|
|
|
"smartcard transmit message "+crypto::hex(in)); |
|
|
|
|
} catch (...) { |
|
|
|
|
} catch (std::exception& x) { |
|
|
|
|
CRYPTOLOG("failed with "<<x.what()); |
|
|
|
|
// try to fix Apple's Mac OS X 10.10 implementation bug
|
|
|
|
|
# ifdef __APPLE__ |
|
|
|
|
/*! @bug Work around Mac OSX 10.10 bug. On Mac OSX
|
|
|
|
@ -320,22 +317,23 @@ namespace pcsc { |
|
|
|
|
reconnect, first transaction (SCardTransmit) |
|
|
|
|
fails with SCARD_W_RESET_CARD |
|
|
|
|
(0x80100068). */ |
|
|
|
|
for (int bugCnt(0); |
|
|
|
|
bugCnt<100 && _state==SCARD_W_RESET_CARD; |
|
|
|
|
++bugCnt) { // just try to resend
|
|
|
|
|
for (int cnt(0); cnt<10 && _state==SCARD_W_RESET_CARD; ++cnt) { |
|
|
|
|
// just try to resend
|
|
|
|
|
CRYPTOLOG("Mac OS X 10.10 implementation bug: " |
|
|
|
|
"On Mac OSX 10.10 there is a bug in " |
|
|
|
|
"PCSC: After a reconnect, first " |
|
|
|
|
"transaction (SCardTransmit) fails " |
|
|
|
|
"with SCARD_W_RESET_CARD (0x80100068). " |
|
|
|
|
"Retry Nr. "<<bugCnt); |
|
|
|
|
"Retry Nr. "<<cnt); |
|
|
|
|
try { |
|
|
|
|
reconnect(); |
|
|
|
|
check(SCardTransmit(_id, &rPci, |
|
|
|
|
(LPCBYTE)in.c_str(), |
|
|
|
|
in.size(), |
|
|
|
|
0, buff, &len), |
|
|
|
|
"smartcard transmit resend message "+crypto::hex(in)); |
|
|
|
|
} catch (...) { |
|
|
|
|
} catch (std::exception& x) { |
|
|
|
|
CRYPTOLOG("failed with "<<x.what()); |
|
|
|
|
continue; // try again
|
|
|
|
|
} |
|
|
|
|
break; // success
|
|
|
|
@ -436,6 +434,18 @@ namespace pcsc { |
|
|
|
|
return _connection->check(state, context); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Reconnect SmartCard After Reset
|
|
|
|
|
/*! @param mode one of
|
|
|
|
|
- @c SCARD_LEAVE_CARD |
|
|
|
|
Do not do anything special on reconnect. |
|
|
|
|
- @c SCARD_RESET_CARD |
|
|
|
|
Reset the card (Warm Reset). |
|
|
|
|
- @c SCARD_UNPOWER_CARD |
|
|
|
|
Power down the card and reset it (Cold Reset). */ |
|
|
|
|
void reconnect(DWORD mode=SCARD_LEAVE_CARD) { |
|
|
|
|
check(SCardReconnect(_id, _mode, _protocol, mode, &_protocol)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
//! Only Connection is allowed to instanciate.
|
|
|
|
|
friend class Connection; |
|
|
|
|
|
|
|
|
@ -443,10 +453,10 @@ namespace pcsc { |
|
|
|
|
Reader(const std::string& nm, std::shared_ptr<Connection> c, |
|
|
|
|
DWORD mode=SCARD_SHARE_SHARED, |
|
|
|
|
DWORD protocol=SCARD_PROTOCOL_T1): |
|
|
|
|
name(nm), _connection(c) { |
|
|
|
|
name(nm), _connection(c), _mode(mode) { |
|
|
|
|
CRYPTOLOG("Connect Reader"); |
|
|
|
|
check(SCardConnect(_connection->id(), strconv(name).c_str(), |
|
|
|
|
mode, protocol, |
|
|
|
|
_mode, protocol, |
|
|
|
|
&_id, &_protocol), |
|
|
|
|
"connect smartcard \""+name+"\""); |
|
|
|
|
} |
|
|
|
@ -460,6 +470,7 @@ namespace pcsc { |
|
|
|
|
std::shared_ptr<Connection> _connection; |
|
|
|
|
SCARDHANDLE _id; |
|
|
|
|
DWORD _state; |
|
|
|
|
DWORD _mode; |
|
|
|
|
DWORD _protocol; |
|
|
|
|
static int _neesting; |
|
|
|
|
|
|
|
|
|