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