14#include "keyple/plugin/pcsc/cpp/CardTerminal.hpp"
22#include "keyple/core/util/cpp/KeypleStd.hpp"
23#include "keyple/core/util/cpp/StringUtils.hpp"
24#include "keyple/core/util/cpp/System.hpp"
25#include "keyple/core/util/cpp/Thread.hpp"
26#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
27#include "keyple/core/util/cpp/exception/RuntimeException.hpp"
28#include "keyple/plugin/pcsc/cpp/CardTerminals.hpp"
29#include "keyple/plugin/pcsc/cpp/exception/CardException.hpp"
30#include "keyple/plugin/pcsc/cpp/exception/CardNotPresentException.hpp"
31#include "keyple/plugin/pcsc/cpp/exception/CardTerminalException.hpp"
39using keyple::core::util::cpp::StringUtils;
40using keyple::core::util::cpp::System;
41using keyple::core::util::cpp::Thread;
42using keyple::core::util::cpp::exception::IllegalArgumentException;
43using keyple::core::util::cpp::exception::RuntimeException;
44using keyple::plugin::pcsc::cpp::exception::CardException;
45using keyple::plugin::pcsc::cpp::exception::CardNotPresentException;
46using keyple::plugin::pcsc::cpp::exception::CardTerminalException;
50CardTerminal::CardTerminal(
51 const std::shared_ptr<CardTerminals> cardTerminals
52,
const std::string& name)
54, mCardTerminals(cardTerminals)
59CardTerminal::getName()
const
65CardTerminal::connect(
const std::string& protocol)
67 int dwPreferredProtocols;
68 int dwShareMode = SCARD_SHARE_SHARED;
70 std::string _protocol = StringUtils::toupper(protocol);
73 if (StringUtils::startsWith(protocol,
"EXCLUSIVE;")) {
74 dwShareMode = SCARD_SHARE_EXCLUSIVE;
75 const size_t prefixSize = std::string(
"EXCLUSIVE;").size();
76 _protocol = _protocol.substr(prefixSize, protocol.size() - prefixSize);
79 if (
"T=0" == _protocol) {
80 dwPreferredProtocols = SCARD_PROTOCOL_T0;
81 }
else if (
"T=1" == _protocol) {
82 dwPreferredProtocols = SCARD_PROTOCOL_T1;
83 }
else if (
"*" == _protocol) {
85 }
else if (
"DIRECT" == _protocol) {
87 dwPreferredProtocols = 0;
92 dwShareMode = SCARD_SHARE_DIRECT;
94 throw IllegalArgumentException(
95 "Protocol should be one of (prepended with EXCLUSIVE;) T=0, T=1," \
96 " *, DIRECT. Got " + protocol);
101 SCARD_IO_REQUEST ioRequest;
103 LONG rv = SCardConnect(
104 mCardTerminals->mContext,
105 (LPCSTR)mName.c_str(),
107 (DWORD)dwPreferredProtocols,
111 if (rv == SCARD_S_SUCCESS) {
112 switch (dwProtocol) {
113 case SCARD_PROTOCOL_T0:
114 ioRequest = *SCARD_PCI_T0;
116 case SCARD_PROTOCOL_T1:
117 ioRequest = *SCARD_PCI_T1;
123 DWORD atrLen =
sizeof(_atr);
135 std::vector<uint8_t> atr(_atr, _atr + atrLen);
137 return std::make_shared<Card>(
138 shared_from_this(), handle, atr, dwProtocol, ioRequest);
141 throw CardNotPresentException(
142 "Card not present: error " + std::string(pcsc_stringify_error(rv)));
146 "SCardConnect failed with error: %\n",
147 std::string(pcsc_stringify_error(rv)));
149 "Failed to connect to card: error " +
150 std::string(pcsc_stringify_error(rv)));
155CardTerminal::isCardPresent()
157 SCARD_READERSTATE states[1] = {};
158 states[0].szReader = mName.c_str();
160 LONG rv = SCardGetStatusChange(mCardTerminals->mContext, 0, states, 1);
161 if (rv != SCARD_S_SUCCESS) {
163 "SCardGetStatusChange failed with error: %\n",
164 std::string(pcsc_stringify_error(rv)));
166 "Failed to get reader status: error " +
167 std::string(pcsc_stringify_error(rv)));
170 return 0 != (states[0].dwEventState & SCARD_STATE_PRESENT);
174CardTerminal::waitForCardAbsent(uint64_t timeout)
178 = std::chrono::duration_cast<std::chrono::milliseconds>(
179 std::chrono::system_clock::now().time_since_epoch())
183 bool isCardAbsent = !this->isCardPresent();
194 newMs = std::chrono::duration_cast<std::chrono::milliseconds>(
195 std::chrono::system_clock::now().time_since_epoch())
198 }
while (newMs <= (currentMs + timeout));
204CardTerminal::waitForCardPresent(uint64_t timeout)
208 = std::chrono::duration_cast<std::chrono::milliseconds>(
209 std::chrono::system_clock::now().time_since_epoch())
213 bool isCardPresent = this->isCardPresent();
224 newMs = std::chrono::duration_cast<std::chrono::milliseconds>(
225 std::chrono::system_clock::now().time_since_epoch())
228 }
while (newMs <= (currentMs + timeout));
234CardTerminal::operator==(
const CardTerminal& o)
const
236 return !mName.compare(o.mName);
240CardTerminal::operator!=(
const CardTerminal& o)
const
242 return !(*
this == o);
246operator<<(std::ostream& os,
const CardTerminal& t)
248 os <<
"CardTerminal: {"
249 <<
"NAME = " << t.mName <<
"}";
255operator<<(std::ostream& os,
const std::vector<CardTerminal>& vt)
257 os <<
"CardTerminalS: {";
258 for (
const auto& t : vt) {
#define SCARD_PROTOCOL_ANY
PcscReader::DisconnectionMode DisconnectionMode
bool isCardCommunicationError(uint64_t rv)
std::ostream & operator<<(std::ostream &os, const PcscReader::IsoProtocol &ip)