14#include "keyple/plugin/pcsc/PcscPluginAdapter.hpp"
16#include "keyple/core/plugin/PluginIOException.hpp"
17#include "keyple/core/util/cpp/KeypleStd.hpp"
18#include "keyple/core/util/cpp/StringUtils.hpp"
19#include "keyple/core/util/cpp/exception/Exception.hpp"
20#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
21#include "keyple/plugin/pcsc/PcscPluginFactoryAdapter.hpp"
22#include "keyple/plugin/pcsc/PcscReaderAdapter.hpp"
23#include "keyple/plugin/pcsc/PcscCardCommunicationProtocol.hpp"
24#include "keyple/plugin/pcsc/PcscSupportedContactProtocol.hpp"
25#include "keyple/plugin/pcsc/PcscSupportedContactlessProtocol.hpp"
26#include "keyple/plugin/pcsc/cpp/CardTerminal.hpp"
27#include "keyple/plugin/pcsc/cpp/CardTerminals.hpp"
28#include "keyple/plugin/pcsc/cpp/TerminalFactory.hpp"
29#include "keyple/plugin/pcsc/cpp/exception/CardTerminalException.hpp"
35using keyple::core::plugin::PluginIOException;
36using keyple::core::util::cpp::StringUtils;
37using keyple::core::util::cpp::exception::Exception;
38using keyple::core::util::cpp::exception::IllegalArgumentException;
39using keyple::plugin::pcsc::cpp::CardTerminal;
40using keyple::plugin::pcsc::cpp::CardTerminals;
41using keyple::plugin::pcsc::cpp::TerminalFactory;
42using keyple::plugin::pcsc::cpp::exception::CardTerminalException;
44std::shared_ptr<PcscPluginAdapter> PcscPluginAdapter::INSTANCE;
46const int PcscPluginAdapter::MONITORING_CYCLE_DURATION_MS = 1000;
48PcscPluginAdapter::PcscPluginAdapter()
50, ObservablePluginSpi()
51, mIsCardTerminalsInitialized(false)
57 {PcscCardCommunicationProtocol::ISO_14443_4.getName(),
58 PcscCardCommunicationProtocol::ISO_14443_4.getDefaultRule()},
59 {PcscCardCommunicationProtocol::INNOVATRON_B_PRIME.getName(),
60 PcscCardCommunicationProtocol::INNOVATRON_B_PRIME.getDefaultRule()},
61 {PcscSupportedContactlessProtocol::INNOVATRON_B_PRIME_CARD.getName(),
62 PcscSupportedContactlessProtocol::INNOVATRON_B_PRIME_CARD.getDefaultRule()},
63 {PcscCardCommunicationProtocol::MIFARE_ULTRALIGHT.getName(),
64 PcscCardCommunicationProtocol::MIFARE_ULTRALIGHT.getDefaultRule()},
65 {PcscSupportedContactlessProtocol::MIFARE_ULTRA_LIGHT.getName(),
66 PcscSupportedContactlessProtocol::MIFARE_ULTRA_LIGHT.getDefaultRule()},
67 {PcscSupportedContactlessProtocol::MIFARE_CLASSIC.getName(),
68 PcscSupportedContactlessProtocol::MIFARE_CLASSIC.getDefaultRule()},
69 {PcscSupportedContactlessProtocol::MIFARE_DESFIRE.getName(),
70 PcscSupportedContactlessProtocol::MIFARE_DESFIRE.getDefaultRule()},
71 {PcscCardCommunicationProtocol::ST25_SRT512.getName(),
72 PcscCardCommunicationProtocol::ST25_SRT512.getDefaultRule()},
73 {PcscSupportedContactlessProtocol::MEMORY_ST25.getName(),
74 PcscSupportedContactlessProtocol::MEMORY_ST25.getDefaultRule()},
77 {PcscCardCommunicationProtocol::ISO_7816_3.getName(),
78 PcscCardCommunicationProtocol::ISO_7816_3.getDefaultRule()},
81 {PcscSupportedContactProtocol::ISO_7816_3_T0.getName(),
82 PcscSupportedContactProtocol::ISO_7816_3_T0.getDefaultRule()},
83 {PcscSupportedContactProtocol::ISO_7816_3_T1.getName(),
84 PcscSupportedContactProtocol::ISO_7816_3_T1.getDefaultRule()}};
88std::shared_ptr<PcscPluginAdapter>
89PcscPluginAdapter::getInstance()
92 INSTANCE = std::make_shared<PcscPluginAdapter>();
98std::unique_ptr<PcscReaderAdapter>
99PcscPluginAdapter::createReader(std::shared_ptr<CardTerminal> terminal)
101 return std::unique_ptr<PcscReaderAdapter>(
new PcscReaderAdapter(
102 terminal, shared_from_this(), mCardMonitoringCycleDuration));
106PcscPluginAdapter::getMonitoringCycleDuration()
const
108 return MONITORING_CYCLE_DURATION_MS;
111const std::vector<std::string>
112PcscPluginAdapter::searchAvailableReaderNames()
114 std::vector<std::string> readerNames;
116 mLogger->trace(
"Plugin [%]: search available reader\n", getName());
118 for (
const auto& terminal : getCardTerminalList()) {
119 readerNames.push_back(terminal->getName());
122 mLogger->trace(
"Plugin [%]: readers found: %", getName(), readerNames);
128PcscPluginAdapter::getName()
const
130 return PcscPluginFactoryAdapter::PLUGIN_NAME;
133const std::vector<std::shared_ptr<ReaderSpi>>
134PcscPluginAdapter::searchAvailableReaders()
136 std::vector<std::shared_ptr<ReaderSpi>> readerSpis;
138 mLogger->trace(
"Plugin [%]: search available readers\n", getName());
140 for (
const auto& terminal : getCardTerminalList()) {
141 readerSpis.push_back(createReader(terminal));
144 for (
const auto& readerSpi : readerSpis) {
146 "Plugin [%]: reader found: %\n", getName(), readerSpi->getName());
153PcscPluginAdapter::onUnregister()
158const std::vector<std::shared_ptr<CardTerminal>>
159PcscPluginAdapter::getCardTerminalList()
167 if (!mIsCardTerminalsInitialized) {
168 mTerminals = TerminalFactory::getDefault()->terminals();
169 mIsCardTerminalsInitialized =
true;
172 return mTerminals->list();
174 }
catch (
const Exception& e) {
175 const auto msg = e.getMessage();
177 if (StringUtils::contains(msg,
"SCARD_E_NO_READERS_AVAILABLE")) {
178 mLogger->error(
"Plugin [%]: no reader available\n", getName());
181 StringUtils::contains(msg,
"SCARD_E_NO_SERVICE")
182 || StringUtils::contains(msg,
"SCARD_E_SERVICE_STOPPED")) {
184 "Plugin [%]: no smart card service error\n", getName());
185 mIsCardTerminalsInitialized =
false;
187 }
else if (StringUtils::contains(msg,
"SCARD_F_COMM_ERROR")) {
189 "Plugin [%]: reader communication error\n", getName());
192 throw PluginIOException(
193 "Could not access terminals list",
194 CardTerminalException(msg));
198 return std::vector<std::shared_ptr<CardTerminal>>(0);
201std::shared_ptr<ReaderSpi>
202PcscPluginAdapter::searchReader(
const std::string& readerName)
204 mLogger->trace(
"Plugin [%]: search reader [%]\n", getName(), readerName);
206 const auto terminals = getCardTerminalList();
207 auto it = std::find_if(
210 [readerName](
const std::shared_ptr<CardTerminal>& terminal) {
211 return terminal->getName() == readerName;
214 if (it != terminals.end()) {
215 mLogger->trace(
"Plugin [%]: reader found\n", getName());
216 return createReader(*it);
219 mLogger->trace(
"Plugin [%]: reader not found\n", getName());
225PcscPluginAdapter::getProtocolRule(
const std::string& readerProtocol)
const
227 const auto it = mProtocolRulesMap.find(readerProtocol);
228 if (it != mProtocolRulesMap.end()) {
236 throw IllegalArgumentException(
"bad protocol");
241PcscPluginAdapter::isContactless(
const std::string& readerName)
243 return mContactlessReaderIdentificationFilterPattern->matcher(readerName)
248PcscPluginAdapter::setContactlessReaderIdentificationFilterPattern(
249 const std::shared_ptr<Pattern> contactlessReaderIdentificationFilter)
251 mContactlessReaderIdentificationFilterPattern
252 = contactlessReaderIdentificationFilter;
258PcscPluginAdapter::addProtocolRulesMap(
259 const std::map<std::string, std::string> protocolRulesMap)
261 if (!protocolRulesMap.empty()) {
263 "Plugin [%]: add protocol identification rules: %\n",
268 "Plugin [%]: use default protocol identification rules\n",
272 mProtocolRulesMap.insert(protocolRulesMap.begin(), protocolRulesMap.end());
278PcscPluginAdapter::setCardMonitoringCycleDuration(
279 const int cardMonitoringCycleDuration)
281 mCardMonitoringCycleDuration = cardMonitoringCycleDuration;