Keyple Plugin PC/SC C++ Library - 2.5.2
Component of the Keyple C++ middleware
CardTerminals.cpp
Go to the documentation of this file.
1/******************************************************************************
2 * Copyright (c) 2025 Calypso Networks Association https://calypsonet.org/ *
3 * *
4 * See the NOTICE file(s) distributed with this work for additional *
5 * information regarding copyright ownership. *
6 * *
7 * This program and the accompanying materials are made available under the *
8 * terms of the Eclipse Public License 2.0 which is available at *
9 * http://www.eclipse.org/legal/epl-2.0 *
10 * *
11 * SPDX-License-Identifier: EPL-2.0 *
12 ******************************************************************************/
13
14#include "keyple/plugin/pcsc/cpp/CardTerminals.hpp"
15
16#include <cstdint>
17#include <cstring>
18#include <string>
19
20#include "PcscUtils.hpp"
21
22#include "keyple/core/util/cpp/exception/IllegalArgumentException.hpp"
23#include "keyple/plugin/pcsc/cpp/exception/CardException.hpp"
24#include "keyple/plugin/pcsc/cpp/exception/CardTerminalException.hpp"
25
26namespace keyple {
27namespace plugin {
28namespace pcsc {
29namespace cpp {
30
31using keyple::core::util::cpp::exception::IllegalArgumentException;
32using keyple::plugin::pcsc::cpp::exception::CardException;
33using keyple::plugin::pcsc::cpp::exception::CardTerminalException;
34
35CardTerminals::CardTerminals(SCARDCONTEXT& context)
36: mContext(context)
37{
38}
39
40void
41CardTerminals::waitForChange()
42{
43 waitForChange(0);
44}
45
46bool
47CardTerminals::waitForChange(long timeout)
48{
49 if (timeout < 0) {
50 throw IllegalArgumentException(
51 "Negative timeout " + std::to_string(timeout));
52 } else if (timeout == 0) {
53 timeout = INFINITE;
54 }
55
56 mZombieReaders.clear();
57
58 for (auto& reader: mKnownReaders) {
59 reader.dwCurrentState = reader.dwEventState;
60 reader.dwEventState = 0;
61 }
62
63 LONG rv = SCardGetStatusChange(
64 mContext, timeout, mKnownReaders.data(), static_cast<DWORD>(mKnownReaders.size()));
65 if (rv == static_cast<LONG>(SCARD_E_TIMEOUT)) {
66 return false;
67 }
68
69 return true;
70}
71
72std::shared_ptr<CardTerminal>
73CardTerminals::getTerminal(const std::string& name)
74{
75 try {
76 for (const auto& terminal : list()) {
77 if (terminal->getName() == name) {
78 return terminal;
79 }
80 }
81
82 return nullptr;
83
84 } catch (const CardException&) {
85 return nullptr;
86 }
87}
88
89const std::vector<std::shared_ptr<CardTerminal>>
90CardTerminals::list()
91{
92 return list(State::ALL);
93}
94
95
96const std::vector<std::shared_ptr<CardTerminal>>
97CardTerminals::list(const State /*state*/)
98{
99 ULONG ret;
100 char* readers = NULL;
101 char* ptr = NULL;
102 DWORD len = 0;
103 static std::vector<std::shared_ptr<CardTerminal>> list;
104
105 /* Clear list */
106 list.clear();
107
108 ret = SCardListReaders(mContext, NULL, NULL, &len);
109 if (ret != SCARD_S_SUCCESS) {
110 throw CardTerminalException(pcsc_stringify_error(ret));
111 }
112
113 readers = static_cast<char*>(calloc(len, sizeof(char)));
114
115 if (readers == NULL) {
116 /* No readers to add to list */
117 return list;
118 }
119
120 ret = SCardListReaders(mContext, NULL, readers, &len);
121 if (ret != SCARD_S_SUCCESS) {
122 throw CardTerminalException(pcsc_stringify_error(ret));
123 }
124
125 ptr = readers;
126
127 if (!ptr) {
128 return list;
129 }
130
131 while (*ptr) {
132 std::string s(ptr);
133 auto terminal = std::make_shared<CardTerminal>(shared_from_this(), s);
134 list.push_back(terminal);
135 ptr += strlen(ptr) + 1;
136 }
137
138 free(readers);
139
140 return list;
141}
142
143} /* namespace cpp */
144} /* namespace pcsc */
145} /* namespace plugin */
146} /* namespace keyple */
Definition: Card.cpp:20