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 {PcscCardCommunicationProtocol::MIFARE_CLASSIC_1K.getName(),
70 PcscCardCommunicationProtocol::MIFARE_CLASSIC_1K.getDefaultRule()},
71 {PcscCardCommunicationProtocol::MIFARE_CLASSIC_4K.getName(),
72 PcscCardCommunicationProtocol::MIFARE_CLASSIC_4K.getDefaultRule()},
73 {PcscSupportedContactlessProtocol::MIFARE_DESFIRE.getName(),
74 PcscSupportedContactlessProtocol::MIFARE_DESFIRE.getDefaultRule()},
75 {PcscCardCommunicationProtocol::ST25_SRT512.getName(),
76 PcscCardCommunicationProtocol::ST25_SRT512.getDefaultRule()},
77 {PcscSupportedContactlessProtocol::MEMORY_ST25.getName(),
78 PcscSupportedContactlessProtocol::MEMORY_ST25.getDefaultRule()},
81 {PcscCardCommunicationProtocol::ISO_7816_3.getName(),
82 PcscCardCommunicationProtocol::ISO_7816_3.getDefaultRule()},
85 {PcscSupportedContactProtocol::ISO_7816_3_T0.getName(),
86 PcscSupportedContactProtocol::ISO_7816_3_T0.getDefaultRule()},
87 {PcscSupportedContactProtocol::ISO_7816_3_T1.getName(),
88 PcscSupportedContactProtocol::ISO_7816_3_T1.getDefaultRule()}};
92std::shared_ptr<PcscPluginAdapter>
93PcscPluginAdapter::getInstance()
96 INSTANCE = std::make_shared<PcscPluginAdapter>();
102std::unique_ptr<PcscReaderAdapter>
103PcscPluginAdapter::createReader(std::shared_ptr<CardTerminal> terminal)
105 return std::unique_ptr<PcscReaderAdapter>(
new PcscReaderAdapter(
106 terminal, shared_from_this(), mCardMonitoringCycleDuration));
110PcscPluginAdapter::getMonitoringCycleDuration()
const
112 return MONITORING_CYCLE_DURATION_MS;
115const std::vector<std::string>
116PcscPluginAdapter::searchAvailableReaderNames()
118 std::vector<std::string> readerNames;
120 mLogger->trace(
"Searching available reader names\n");
122 for (
const auto& terminal : getCardTerminalList()) {
123 readerNames.push_back(terminal->getName());
126 mLogger->trace(
"Readers found [names=%]\n", readerNames);
132PcscPluginAdapter::getName()
const
134 return PcscPluginFactoryAdapter::PLUGIN_NAME;
137const std::vector<std::shared_ptr<ReaderSpi>>
138PcscPluginAdapter::searchAvailableReaders()
140 std::vector<std::shared_ptr<ReaderSpi>> readerSpis;
142 mLogger->trace(
"Searching available readers\n");
144 for (
const auto& terminal : getCardTerminalList()) {
145 readerSpis.push_back(createReader(terminal));
148 for (
const auto& readerSpi : readerSpis) {
150 "Reader found [name=%]\n", readerSpi->getName());
157PcscPluginAdapter::onUnregister()
162const std::vector<std::shared_ptr<CardTerminal>>
163PcscPluginAdapter::getCardTerminalList()
171 if (!mIsCardTerminalsInitialized) {
172 mTerminals = TerminalFactory::getDefault()->terminals();
173 mIsCardTerminalsInitialized =
true;
176 return mTerminals->list();
178 }
catch (
const Exception& e) {
179 const auto msg = e.getMessage();
181 if (StringUtils::contains(msg,
"SCARD_E_NO_READERS_AVAILABLE")) {
182 mLogger->error(
"No reader available\n");
185 StringUtils::contains(msg,
"SCARD_E_NO_SERVICE")
186 || StringUtils::contains(msg,
"SCARD_E_SERVICE_STOPPED")) {
188 "No running smart card service\n");
189 mIsCardTerminalsInitialized =
false;
191 }
else if (StringUtils::contains(msg,
"SCARD_F_COMM_ERROR")) {
193 "Reader communication error occurred\n");
196 throw PluginIOException(
197 "Could not access terminals list",
198 CardTerminalException(msg));
202 return std::vector<std::shared_ptr<CardTerminal>>(0);
205std::shared_ptr<ReaderSpi>
206PcscPluginAdapter::searchReader(
const std::string& readerName)
208 mLogger->trace(
"Searching reader [reader=%]\n", readerName);
210 const auto terminals = getCardTerminalList();
211 auto it = std::find_if(
214 [readerName](
const std::shared_ptr<CardTerminal>& terminal) {
215 return terminal->getName() == readerName;
218 if (it != terminals.end()) {
219 mLogger->trace(
"Reader found\n");
220 return createReader(*it);
223 mLogger->trace(
"Reader not found\n");
229PcscPluginAdapter::getProtocolRule(
const std::string& readerProtocol)
const
231 const auto it = mProtocolRulesMap.find(readerProtocol);
232 if (it != mProtocolRulesMap.end()) {
240 throw IllegalArgumentException(
"bad protocol");
245PcscPluginAdapter::isContactless(
const std::string& readerName)
247 return mContactlessReaderIdentificationFilterPattern->matcher(readerName)
252PcscPluginAdapter::setContactlessReaderIdentificationFilterPattern(
253 const std::shared_ptr<Pattern> contactlessReaderIdentificationFilter)
255 mContactlessReaderIdentificationFilterPattern
256 = contactlessReaderIdentificationFilter;
262PcscPluginAdapter::addProtocolRulesMap(
263 const std::map<std::string, std::string> protocolRulesMap)
265 if (!protocolRulesMap.empty()) {
267 "Adding protocol identification rules [rules=%]\n",
271 "Using default protocol identification rules\n");
274 mProtocolRulesMap.insert(protocolRulesMap.begin(), protocolRulesMap.end());
280PcscPluginAdapter::setCardMonitoringCycleDuration(
281 const int cardMonitoringCycleDuration)
283 mCardMonitoringCycleDuration = cardMonitoringCycleDuration;