SDK Readers 1.0.1
SDK для связи со считывателями Iron logic
mf_plus/main.cpp

Демонстрирует работу с картами Mifare Plus SL3: поиск, чтение и запись данных карты, запись ключей аутентификации в память считывателя.

#include <assert.h>
#include <limits.h>
#include <stdio.h>
#include <unistd.h> //readlink
#include <filesystem>
#include <fstream>
#include <iomanip> // для std::put_time
#include <iostream>
#include "ilreaders.h"
// #define ILR_LOG // Раскомментируйте, чтобы включить отладочные сообщения
#define ILR_LOG_FILE // Писать лог в файл
using namespace ilr;
// Ключ аутентификации Mifare Plus
CMifarePlusKey g_AuthKey;
// True, авторизовать по ключу B, иначе - A
bool g_fAuthKeyB = false;
// True, открытая передача, иначе - зашифрованная
bool g_fOpenText = true;
// Биты ключей аутентификации считывателя
uint32_t g_nRdKeys = 0;
// Сохранённые ключи считывателя
CMifarePlusKey g_aSavedRdKeys[2][16];
// Серийный номер считывателя (устанавливается автоматически)
int g_nReaderSn = -1;
#ifdef ILR_LOG
const char kLogLevelChars[] = {'-', 'E', 'W', 'I', 'D'};
const char kLogFileName[] = "ilreaders.log"; // Путь к лог файлу
void ILR_CALL LogCallback(ilr_log_level level, const char* pContext, const char* pMessage, void*) {
#ifdef ILR_LOG_FILE // Запись в файл
std::ofstream file(kLogFileName, std::ios_base::out | std::ios_base::app);
auto& out = file;
#else // иначе в консоль
auto& out = std::cout;
#endif
auto t = std::time(nullptr);
auto tmb = std::localtime(&t);
out << std::put_time(tmb, "%d-%m-%Y %H:%M:%S") << " [" << kLogLevelChars[level] << ' '
<< pContext << "] " << pMessage << std::endl;
}
#endif
// Возвращает путь к файлу настроек
std::filesystem::path GetSettingFilePath() {
char szCfgPath[PATH_MAX];
auto count = readlink("/proc/self/exe", szCfgPath, std::size(szCfgPath) - 1);
szCfgPath[count] = '\0';
std::stringstream ss;
ss << szCfgPath << '_' << g_nReaderSn << ".txt";
return ss.str();
}
// Загружает настройки
void LoadSettings() {
auto sPath(GetSettingFilePath());
if (std::filesystem::exists(sPath)) {
std::ifstream inFile;
inFile.open(sPath);
inFile >> std::boolalpha >> g_fAuthKeyB;
inFile >> std::hex >> g_AuthKey.ll.hi >> g_AuthKey.ll.lo >> g_nRdKeys;
for (size_t i = 0; i < std::size(g_aSavedRdKeys); i++)
for (size_t j = 0; j < std::size(g_aSavedRdKeys[i]); j++)
inFile >> g_aSavedRdKeys[i][j].ll.hi >> g_aSavedRdKeys[i][j].ll.lo;
}
}
// Сохраняет настройки
void SaveSettings() {
std::filesystem::path sPath(GetSettingFilePath());
std::ofstream outFile;
outFile.open(sPath);
outFile << std::boolalpha << g_fAuthKeyB << " ";
outFile << std::hex << std::showbase << g_AuthKey.ll.hi << " " << std::noshowbase
<< g_AuthKey.ll.lo << " ";
outFile << std::showbase << g_nRdKeys;
for (size_t i = 0; i < std::size(g_aSavedRdKeys); i++) {
outFile << "\n";
for (size_t j = 0; j < std::size(g_aSavedRdKeys[i]); j++)
outFile << std::showbase << g_aSavedRdKeys[i][j].ll.hi << " " << std::noshowbase
<< g_aSavedRdKeys[i][j].ll.lo << "\n";
}
}
void PrintTrailerAccess(bool fValid, uint32_t nAreaAccess) {
// Выводим параметры доступа прицепа
std::cout << "3. Прицеп. Доступ (";
if (fValid) {
std::cout << (nAreaAccess & 1) << ' ' << ((nAreaAccess >> 1) & 1) << ' '
<< ((nAreaAccess >> 2) & 1) << "): ";
switch (nAreaAccess) {
case 0: // 0 0 0
assert(!g_fAuthKeyB);
std::cout << "Ключ A [-w]; Биты доступа [r-]; Ключ B [rw]";
break;
case 2: // 0 1 0
assert(!g_fAuthKeyB);
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [r-]";
break;
case 1: // 1 0 0
if (g_fAuthKeyB)
std::cout << "Ключ A [-w]; Биты доступа [r-]; Ключ B [-w]";
else
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [--]";
break;
case 3: // 1 1 0
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [--]";
break;
case 4: // 0 0 1
assert(!g_fAuthKeyB);
std::cout << "Ключ A [-w]; Биты доступа [rw]; Ключ B [rw]; транспортная";
break;
case 6: // 0 1 1
if (g_fAuthKeyB)
std::cout << "Ключ A [-w]; Биты доступа [rw]; Ключ B [-w]";
else
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [--]";
break;
case 5: // 1 0 1
if (g_fAuthKeyB)
std::cout << "Ключ A [--]; Биты доступа [rw]; Ключ B [-w]";
else
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [--]";
break;
case 7: // 1 1 1
std::cout << "Ключ A [--]; Биты доступа [r-]; Ключ B [--]";
break;
}
std::cout << std::endl;
}
else
std::cout << "некорректные биты доступа)" << std::endl;
}
void PrintDataAccess(size_t nAreaN, bool fValid, uint32_t nAreaAccess) {
// Выводим параметры доступа блока данных
std::cout << std::dec << nAreaN << ". Данные. Доступ (";
if (fValid) {
std::cout << (nAreaAccess & 1) << ' ' << ((nAreaAccess >> 1) & 1) << ' '
<< ((nAreaAccess >> 2) & 1) << "): ";
switch (nAreaAccess) {
case 0: // 0 0 0
std::cout << "rwidtr; транспортная";
break;
case 2: // 0 1 0
std::cout << "r-----";
break;
case 1: // 1 0 0
if (g_fAuthKeyB)
std::cout << "rw----";
else
std::cout << "r-----";
break;
case 3: // 1 1 0
if (g_fAuthKeyB)
std::cout << "rwidtr; блок-значение";
else
std::cout << "r--dtr; блок-значение";
break;
case 4: // 0 0 1
std::cout << "r--dtr; блок-значение";
break;
case 6: // 0 1 1
if (g_fAuthKeyB)
std::cout << "rw----";
else
std::cout << "------";
break;
case 5: // 1 0 1
if (g_fAuthKeyB)
std::cout << "r-----";
else
std::cout << "------";
break;
case 7: // 1 1 1
std::cout << "------";
break;
}
std::cout << std::endl;
}
else
std::cout << "некорректные биты доступа)" << std::endl;
}
const char* kOpenText[2] = {"Зашифрованная передача", "Открытая передача"};
void DoReadAllFromCard(CReader& oReader) {
size_t nRead = 0;
size_t nBlockMax = 0;
try {
oReader.GetCardInfo(rCI);
nBlockMax = GetNumberOfMfBlocks(rCI.nMemSize);
std::vector<ilr_mf_block_data> oBlocks(nBlockMax);
std::cout << "Чтение данных карты..." << std::endl;
auto tStartTime = now();
uint16_t nAuthAddress = 0x4000;
if (g_fAuthKeyB)
++nAuthAddress;
if (g_nRdKeys != 0) {
if (oReader.AuthMfCard2(nAuthAddress, g_fAuthKeyB, g_nRdKeys) == -1) {
std::cout << "Нет подходящего ключа аутентификации в памяти считывателя"
<< std::endl;
return;
}
}
else {
oReader.LoadMfPKey(g_AuthKey);
if (!oReader.AuthMfCard(nAuthAddress, g_fAuthKeyB)) {
std::cout << "Ключ аутентификации не подошёл" << std::endl;
return;
}
}
oReader.ReadMfPlus(0, oBlocks.data(), oBlocks.size(), g_fOpenText, &nRead);
std::cout << "Прочитано за " << since(tStartTime).count() << " мс" << std::endl;
size_t nSectorIdx = 0;
size_t nSBlockIdx = 0;
size_t nSTrailer;
size_t nAreaN;
uint32_t nAccessBits, nAreaAccess;
bool fAreaValid;
uint8_t nEn;
for (size_t i = 0; i < nRead; ++i) {
if (0 == nSBlockIdx) {
nSTrailer = (i < 128) ? 3 : 15;
pBData = &oBlocks[i + nSTrailer];
nAccessBits = GetMfAccessBits(*pBData);
nEn = pBData->a[5];
}
pBData = &oBlocks[i];
// Выводим байты блока
auto ff(std::cout.flags());
std::cout << std::dec << std::setfill(' ') << std::setw(3) << i << " (" << std::setw(2)
<< nSectorIdx << "). " << std::noshowbase << std::hex << std::setfill('0')
<< std::setw(2) << (uint)pBData->a[0] << ' ' << std::setw(2)
<< (uint)pBData->a[1] << ' ' << std::setw(2) << (uint)pBData->a[2] << ' '
<< std::setw(2) << (uint)pBData->a[3] << ' ' << std::setw(2)
<< (uint)pBData->a[4] << ' ' << std::setw(2) << (uint)pBData->a[5] << ' '
<< std::setw(2) << (uint)pBData->a[6] << ' ' << std::setw(2)
<< (uint)pBData->a[7] << ' ' << std::setw(2) << (uint)pBData->a[8] << ' '
<< std::setw(2) << (uint)pBData->a[9] << ' ' << std::setw(2)
<< (uint)pBData->a[10] << ' ' << std::setw(2) << (uint)pBData->a[11] << ' '
<< std::setw(2) << (uint)pBData->a[12] << ' ' << std::setw(2)
<< (uint)pBData->a[13] << ' ' << std::setw(2) << (uint)pBData->a[14] << ' '
<< std::setw(2) << (uint)pBData->a[15] << std::endl;
std::cout.flags(ff);
nAreaN = (nSBlockIdx * 3) / nSTrailer;
fAreaValid = TryGetMfAreaAccess(nAccessBits, nAreaN, nAreaAccess);
// Если это блок-прицеп,
if (nSBlockIdx == nSTrailer) {
PrintTrailerAccess(fAreaValid, nAreaAccess);
++nSectorIdx;
nSBlockIdx = 0;
}
else {
PrintDataAccess(nAreaN, fAreaValid, nAreaAccess);
++nSBlockIdx;
}
std::cout << "\t" << kOpenText[GET_BIT(nEn, nAreaN)] << std::endl;
}
std::cout << "-----" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
std::cout << "Прочитано " << std::dec << nRead << " из " << nBlockMax << " блоков"
<< std::endl;
}
}
void DoReadBlockFromCard(CReader& oReader) {
try {
// Запрашиваем номер сектора и номер блока Mifare
std::cout << "Введите номер сектора и номер блока:" << std::endl;
size_t nSectorIdx, nSBlockIdx;
std::cin >> std::dec >> nSectorIdx >> nSBlockIdx;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
size_t nBlockIdx, nSTrailer;
bool fTrailer;
if (nSectorIdx < 32) {
nBlockIdx = (nSectorIdx * 4) + nSBlockIdx;
nSTrailer = 3;
}
else {
nBlockIdx = 128 + ((nSectorIdx - 32) * 16) + nSBlockIdx;
nSTrailer = 15;
}
fTrailer = (nSTrailer == nSBlockIdx);
ilr_mf_block_data rBlockData;
size_t nAuthAddress = 0x4000U + (nSectorIdx * 2);
if (g_fAuthKeyB)
++nAuthAddress;
std::cout << "Чтение..." << std::endl;
auto tStartTime = now();
if (g_nRdKeys != 0) {
if (oReader.AuthMfCard2(nAuthAddress, g_fAuthKeyB, g_nRdKeys) == -1) {
std::cout << "Нет подходящего ключа аутентификации в памяти считывателя"
<< std::endl;
return;
}
}
else {
oReader.LoadMfCKey(g_AuthKey);
if (!oReader.AuthMfCard(nAuthAddress, g_fAuthKeyB)) {
std::cout << "Ключ аутентификации не подошёл" << std::endl;
return;
}
}
oReader.ReadMfPlus(nBlockIdx, &rBlockData, 1, g_fOpenText);
std::cout << "Прочитано за " << std::dec << since(tStartTime).count() << " мс" << std::endl;
// Выводим байты блока
auto ff(std::cout.flags());
std::cout << std::noshowbase << std::hex << std::setfill('0') << std::setw(2)
<< (uint)rBlockData.a[0] << ' ' << std::setw(2) << (uint)rBlockData.a[1] << ' '
<< std::setw(2) << (uint)rBlockData.a[2] << ' ' << std::setw(2)
<< (uint)rBlockData.a[3] << ' ' << std::setw(2) << (uint)rBlockData.a[4] << ' '
<< std::setw(2) << (uint)rBlockData.a[5] << ' ' << std::setw(2)
<< (uint)rBlockData.a[6] << ' ' << std::setw(2) << (uint)rBlockData.a[7] << ' '
<< std::setw(2) << (uint)rBlockData.a[8] << ' ' << std::setw(2)
<< (uint)rBlockData.a[9] << ' ' << std::setw(2) << (uint)rBlockData.a[10] << ' '
<< std::setw(2) << (uint)rBlockData.a[11] << ' ' << std::setw(2)
<< (uint)rBlockData.a[12] << ' ' << std::setw(2) << (uint)rBlockData.a[13] << ' '
<< std::setw(2) << (uint)rBlockData.a[14] << ' ' << std::setw(2)
<< (uint)rBlockData.a[15] << std::endl;
std::cout.flags(ff);
if (fTrailer) {
auto nAccessBits = GetMfAccessBits(rBlockData);
uint32_t nAreaAccess;
bool fAreaValid;
for (size_t i = 0; i < 4; i++) {
fAreaValid = TryGetMfAreaAccess(nAccessBits, i, nAreaAccess);
if (3 == i)
PrintTrailerAccess(fAreaValid, nAreaAccess);
else
PrintDataAccess(i, fAreaValid, nAreaAccess);
auto nEn = rBlockData.a[5];
std::cout << "\t" << kOpenText[GET_BIT(nEn, i)] << std::endl;
}
}
std::cout << "-----" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
void DoWriteBlockToCard(CReader& oReader) {
try {
// Запрашиваем номер сектора и номер блока Mifare
std::cout << "Введите номер сектора и номер блока:" << std::endl;
size_t nSectorIdx, nSBlockIdx;
std::cin >> std::dec >> nSectorIdx >> nSBlockIdx;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
// Запрашиваем значения байтов блока Mifare
std::cout << "Введите байты 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 (16-ричное):"
<< std::endl;
uint aN[16];
std::cin >> std::hex >> aN[0] >> aN[1] >> aN[2] >> aN[3] >> aN[4] >> aN[5] >> aN[6] >>
aN[7] >> aN[8] >> aN[9] >> aN[10] >> aN[11] >> aN[12] >> aN[13] >> aN[14] >> aN[15];
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
ilr_mf_block_data rBlockData;
for (size_t i = 0; i < std::size(rBlockData.a); i++)
rBlockData.a[i] = static_cast<uint8_t>(aN[i]);
size_t nBlockIdx;
bool fTrailer;
if (nSectorIdx < 32) {
nBlockIdx = (nSectorIdx * 4) + nSBlockIdx;
fTrailer = (3 == nSBlockIdx);
}
else {
nBlockIdx = 128 + ((nSectorIdx - 32) * 16) + nSBlockIdx;
fTrailer = (15 == nSBlockIdx);
}
// Если это блок-прицеп,
if (fTrailer) {
// Проверяем корректность битов доступа
uint32_t nAccessBits = GetMfAccessBits(rBlockData);
if (((nAccessBits & 0xFFF) ^ (nAccessBits >> 12)) != 0xFFF) {
std::cout << "Некорректное значение битов доступа. Запись отменена" << std::endl;
return;
}
// Проверяем корректность битов доступа En
uint8_t nEn = rBlockData.a[5];
if (((nEn & 0xF) ^ (nEn >> 4)) != 0xF) {
std::cout << "Некорректное значение битов доступа En. Запись отменена" << std::endl;
return;
}
}
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
if (g_nRdKeys != 0) {
if (oReader.AuthMfCard2(nBlockIdx, g_fAuthKeyB, g_nRdKeys) == -1) {
std::cout << "Нет подходящего ключа аутентификации" << std::endl;
return;
}
}
else {
oReader.LoadMfPKey(g_AuthKey);
if (!oReader.AuthMfCard(nBlockIdx, g_fAuthKeyB)) {
std::cout << "Ключ аутентификации не подошёл" << std::endl;
return;
}
}
size_t nWritten = 0;
oReader.WriteMfPlus(nBlockIdx, &rBlockData, 1, g_fOpenText, &nWritten);
std::cout << "Записано за " << since(tStartTime).count() << " мс" << std::endl;
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
void WriteAuthKeyToReader(CReader& oReader) {
try {
// Запрашиваем номер ключа и значение ключа аутентификации Mifare
std::cout << "Введите номер ключа (10-тичное) и значение ключа (16-тичное: старшая часть + "
"пробел + "
"младшая):"
<< std::endl;
size_t nIdx;
CMifarePlusKey rAuthKey;
std::cin >> std::dec >> nIdx >> std::hex >> rAuthKey.ll.hi >> rAuthKey.ll.lo;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
std::cout << "Запись..." << std::endl;
auto tStartTime = now();
oReader.WriteMfPKey(nIdx, g_fAuthKeyB, &rAuthKey, 1);
std::cout << "Записано за " << std::dec << since(tStartTime).count() << " мс" << std::endl;
g_aSavedRdKeys[g_fAuthKeyB][nIdx] = rAuthKey;
// Сохраняем ключ в файл настроек
SaveSettings();
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
}
void ShowSavedReaderKeys() {
for (size_t i = 0; i < std::size(g_aSavedRdKeys); ++i) {
std::cout << "Сохранённые ключи " << (i ? 'B' : 'A') << ':' << std::endl;
for (size_t j = 0; j < std::size(g_aSavedRdKeys[i]); ++j)
std::cout << std::dec << j << ": " << std::hex << std::setw(12)
<< g_aSavedRdKeys[i][j].ll.hi << ' ' << std::setw(12)
<< g_aSavedRdKeys[i][j].ll.lo << std::endl;
std::cout << std::endl;
}
}
void DoSwitchAuthKeyType() {
std::cout << "Введите тип ключа: A или B:" << std::endl;
char ch;
std::cin >> ch;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
ch = static_cast<char>(toupper(static_cast<int>(ch)));
if (ch == 'A')
g_fAuthKeyB = false;
else if (ch == 'B')
g_fAuthKeyB = true;
else {
std::cout << "Неправильный ввод" << std::endl;
return;
}
// Сохраняем тип ключа в файл настроек
SaveSettings();
}
void DoEnterAuthKey() {
std::cout << "Введите ключ аутентификации (16-ричное: старшая часть + пробел + младшая):"
<< std::endl;
CMifarePlusKey rAuthKey;
std::cin >> std::hex >> rAuthKey.ll.hi >> rAuthKey.ll.lo;
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
if (std::cin.fail()) {
std::cin.clear();
std::cout << "Неправильный ввод" << std::endl;
return;
}
g_AuthKey = rAuthKey;
// Сохраняем ключ в файл настроек
SaveSettings();
}
void DoSelectRdAuthKeys() {
std::cout << "Введите номер ключа (0..15) или '=' + битовую маске (16-ричное):" << std::endl;
std::string sInput;
std::getline(std::cin, sInput);
if (sInput.empty()) {
std::cout << "Неправильный ввод" << std::endl;
return;
}
char* p;
if (sInput.front() == '=')
g_nRdKeys = static_cast<unsigned int>(strtoul(&sInput[1], &p, 16));
else {
const char* pszDelimiters = " ,;";
p = nullptr;
char* pToken;
int nKeyIdx;
g_nRdKeys = 0;
pToken = strtok_r(sInput.data(), pszDelimiters, &p);
while (pToken != nullptr) {
nKeyIdx = atoi(pToken);
if ((nKeyIdx >= 0) && (nKeyIdx < 16))
g_nRdKeys |= (1u << nKeyIdx);
pToken = strtok_r(nullptr, pszDelimiters, &p);
}
}
// Сохраняем биты ключей в файл настроек
SaveSettings();
}
bool DoConnectTo(CILR& oILR, CReader& oReader) {
CReaderSearch oSearch(oILR.GetSearch());
// Ищем считыватели
std::cout << "Поиск считывателей..." << std::endl;
oSearch.Scan();
auto nCount = oSearch.GetReaderCount();
if (0 == nCount) {
std::cout << "Считыватель не найден" << std::endl;
return false;
}
std::cout << "Найдено " << nCount << ':' << std::endl;
bool fFound = false;
for (size_t i = 0; i < nCount; i++) {
oSearch.GetReaderInfo(i, rInfo);
// Если порт занят, пропускаем его
if (*rInfo.pszConnect != '\0')
continue;
if (CReader::GetSupportedRewrittenCardTypes(rInfo.nModel, rInfo.nFwVersion) &
fFound = true;
break;
}
}
if (!fFound) {
std::cout << "Считыватель не поддерживает чтение/запись карт Mifare Plus SL3" << std::endl;
return false;
}
// Подключаемся к считывателю
std::cout << "Подключение к считывателю [" << kPortTypeNames[rInfo.nPortType] << ": "
<< rInfo.pszPortName << "]..." << std::endl;
oReader = oILR.GetReader(rInfo.nPortType, rInfo.pszPortName);
// Отключаем авто поиск карт
oReader.SetAutoScan(false);
oReader.GetOptions(rOptions);
rOptions.nConnectModel = rInfo.nModel;
oReader.SetOptions(rOptions);
}
oReader.Connect();
oReader.GetReaderInfo(rInfo);
g_nReaderSn = rInfo.nSn;
std::stringstream ss;
ss << kReaderModelNames[rInfo.nModel];
if (rInfo.nSn != -1)
ss << " с/н:" << rInfo.nSn;
if (rInfo.nFwVersion != 0)
ss << " прошивка:" << ReaderVersionToStr(rInfo.nFwVersion);
if (rInfo.nFwBuildDate != 0)
ss << " сборка " << TimeToStr(rInfo.nFwBuildDate);
std::cout << "Считыватель успешно подключён [" << ss.str() << ']' << std::endl;
return true;
}
int main() {
try {
#ifdef ILR_LOG
#ifdef ILR_LOG_FILE
// Очищаем лог файл
std::ofstream file(kLogFileName, std::ios_base::out | std::ios_base::trunc);
file.close();
#endif
CILR::SetLogCallback(LogCallback);
CILR::SetLogLevel(ILR_LOG_LEVEL_DEBUG);
#endif
// Ищем считыватель и подключаемся к нему
CILR oILR;
CReader oReader;
if (!DoConnectTo(oILR, oReader))
return 0;
// Загружаем настройки из файла
LoadSettings();
while (true) {
std::cout << "Поиск карты Mifare Plus SL3..." << std::endl;
oReader.Scan();
oReader.GetCardInfo(rCI);
bool fCardFound = IsMfPlusSL3Mode(rCI.nType, rCI.nSL);
// Если карта Mifare Plus найдена,
if (fCardFound)
std::cout << kCardTypeNames[rCI.nType] << ' ' << CardUIDToStr(rCI.nType, rCI.rUID)
<< std::endl;
else // Mifare Plus не найдена
std::cout << "Карта не найдена" << std::endl;
std::cout << "-----" << std::endl;
std::cout << "Введите номер команды:" << std::endl;
std::cout << "1 - Искать карту снова" << std::endl;
if (fCardFound) {
std::cout << "2 - Прочитать данные из карты" << std::endl;
std::cout << "3 - Прочитать блок данных из карты..." << std::endl;
std::cout << "4 - Записать блок данных на карту..." << std::endl;
}
std::cout << "5 - Записать ключ аутентификации в считыватель..." << std::endl;
std::cout << "6 - Показать сохранённые ключи считывателя" << std::endl;
std::cout << "7 - Переключить тип ключа A или B [" << (g_fAuthKeyB ? 'B' : 'A')
<< "]..." << std::endl;
std::cout << "8 - Выбрать ключи аутентификации считывателя [" << std::hex << g_nRdKeys
<< "]..." << std::endl;
std::cout << "9 - Ввести ключ аутентификации [" << std::showbase << std::hex
<< std::setw(12) << g_AuthKey.ll.hi << ' ' << std::noshowbase << std::setw(12)
<< g_AuthKey.ll.lo << "]..." << std::endl;
std::cout << "0 - Выйти из программы" << std::endl;
int nCommand;
std::cin >> nCommand;
if (std::cin.fail()) {
std::cin.clear();
nCommand = -1;
}
std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
switch (nCommand) {
case 1:
break;
case 2:
if (fCardFound)
DoReadAllFromCard(oReader);
break;
case 3:
if (fCardFound)
DoReadBlockFromCard(oReader);
break;
case 4:
if (fCardFound)
DoWriteBlockToCard(oReader);
break;
case 5:
WriteAuthKeyToReader(oReader);
break;
case 6:
ShowSavedReaderKeys();
break;
case 7:
DoSwitchAuthKeyType();
break;
case 8:
DoSelectRdAuthKeys();
break;
case 9:
DoEnterAuthKey();
break;
case 0:
return 0;
default:
std::cout << "Неправильный ввод" << std::endl;
break;
}
}
}
catch (const std::exception& e) {
std::cerr << e.what() << std::endl;
}
return 0;
}
Класс для инициализации/финализации библиотеки SDK.
Definition: ilr_cpp_helpers.h:2607
CReaderSearch GetSearch()
Создаёт дескриптор поиска считывателей.
Definition: ilr_cpp_helpers.h:2761
CReader GetReader(ilr_port_type nPortType, const char *pszPortName)
Создаёт дескриптор считывателя.
Definition: ilr_cpp_helpers.h:2767
Ключ аутентификации Mifare Plus.
Definition: ilr_cpp_helpers.h:294
Класс поиска считывателей.
Definition: ilr_cpp_helpers.h:583
Класс считывателя.
Definition: ilr_cpp_helpers.h:996
void SetAutoScan(bool fEnable=true, bool fWait=true)
Включает/выключает автоматическое сканирование карт.
Definition: ilr_cpp_helpers.h:2242
void Connect(bool fReconnect=false)
Подключается к считывателю.
Definition: ilr_cpp_helpers.h:2197
int AuthMfCard2(size_t nAddress, bool fKeyB, uint32_t nKeys=0xFFFF)
Авторизует сектор карты Mifare Classic / Plus, используя ключи считывателя.
Definition: ilr_cpp_helpers.h:2316
bool AuthMfCard(size_t nAddress, bool fKeyB)
Авторизует сектор карты Mifare Classic/Plus.
Definition: ilr_cpp_helpers.h:2298
void SetOptions(const ilr_reader_options &rOptions)
Устанавливает параметры считывателя.
Definition: ilr_cpp_helpers.h:2189
void WriteMfPKey(size_t nIdx, bool fKeyB, const ilr_mf_plus_key *pKeys, size_t nCount, size_t *pWritten=nullptr)
Записывает ключи аутентификации Mifare Plus в память считывателя
Definition: ilr_cpp_helpers.h:2488
void Scan(bool fReset=false, bool fPowerOff=true)
Ищет карты.
Definition: ilr_cpp_helpers.h:2227
void LoadMfCKey(const ilr_mf_classic_key &nKey)
Загружает ключ для авторизации сектора Mifare Classic / Plus SL1.
Definition: ilr_cpp_helpers.h:2290
void WriteMfPlus(size_t nAddress, const ilr_mf_block_data *pData, size_t nBlockCount, bool fOpenText=true, size_t *pWritten=nullptr)
Пишет данные карты Mifare Plus SL3.
Definition: ilr_cpp_helpers.h:2382
void ReadMfPlus(size_t nAddress, ilr_mf_block_data *pBuf, size_t nBlockCount, bool fOpenText=true, size_t *pRead=nullptr)
Читает данные карты Mifare Plus SL3.
Definition: ilr_cpp_helpers.h:2364
void GetReaderInfo(ilr_reader_info &rInfo) const
Возвращает информацию о считывателе.
Definition: ilr_cpp_helpers.h:2223
void GetOptions(ilr_reader_options &rOptions) const
Возвращает параметры считывателя.
Definition: ilr_cpp_helpers.h:2193
void LoadMfPKey(const ilr_mf_plus_key &rKey)
Загружает ключ для авторизации сектора Mifare Plus SL3.
Definition: ilr_cpp_helpers.h:2294
bool GetCardInfo(ilr_card_info &rInfo) const
Возвращает информацию о карте в поле считывателя.
Definition: ilr_cpp_helpers.h:2237
@ ILR_RWCT_F_MF_PLUS_SL3
Mifare Plus SL3.
Definition: ilreaders.h:645
Заголовочный файл SDK Readers с классами-помощниками C++.
#define GET_BIT(val, bitN)
Возвращает true если бит bitN установлен в числе val.
Definition: ilr_cpp_helpers.h:2779
size_t GetNumberOfMfBlocks(uint32_t nMemSize)
Вычисляет количество блоков карты Mifare Classic/Plus по размеру её памяти.
Definition: ilr_cpp_helpers.h:2881
auto since(std::chrono::time_point< clock_t, duration_t > const &start)
Возвращает интервал времени в миллисекундах от времени start до текущего времени.
Definition: ilr_cpp_helpers.h:2802
std::chrono::steady_clock::time_point now()
Definition: ilr_cpp_helpers.h:2791
Заголовочный файл API SDK Readers.
#define ILR_CALL
Макрос, определяющий соглашение о вызове функций.
Definition: ilreaders.h:56
ilr_log_level
Уровень лога.
Definition: ilreaders.h:319
@ ILR_LOG_LEVEL_DEBUG
Отладочные сообщения.
Definition: ilreaders.h:349
@ ILR_READER_MODEL_UNKNOWN
Definition: ilreaders.h:213
Информация о карте.
Definition: ilreaders.h:596
ilr_card_type nType
Тип карты.
Definition: ilreaders.h:597
uint32_t nMemSize
Размер памяти карты (в байтах).
Definition: ilreaders.h:599
ilr_mf_plus_sl nSL
Уровень безопасности Mifare Plus.
Definition: ilreaders.h:600
ilr_card_uid rUID
Номер карты.
Definition: ilreaders.h:598
Данные блока Mifare Classic/Plus.
Definition: ilreaders.h:631
uint8_t a[16]
Байты блока.
Definition: ilreaders.h:632
uint64_t hi
Старшая часть ключа.
Definition: ilreaders.h:622
uint64_t lo
Младшая часть ключа.
Definition: ilreaders.h:621
Информация о считывателе.
Definition: ilreaders.h:295
ilr_reader_model nModel
Definition: ilreaders.h:304
uint32_t nFwVersion
Definition: ilreaders.h:310
const char * pszConnect
Definition: ilreaders.h:302
const char * pszPortName
Definition: ilreaders.h:299
int64_t nFwBuildDate
Definition: ilreaders.h:313
ilr_port_type nPortType
Definition: ilreaders.h:297
int nSn
Definition: ilreaders.h:306
Настройки считывателя.
Definition: ilreaders.h:663
ilr_reader_model nConnectModel
Definition: ilreaders.h:665