Жизненный RFID

Последний месяц выдался не слишком продуктивным, так как приходилось много ездить по разнообразным медицинским учреждениям. На вторую неделю поездок выяснилось, что большинство учреждений используют RFID-карты для разграничения доступа во внутренних помещениях. Таким образом, под конец месяца у меня набралось великое множество таких карт, что было дико неудобно: приехал в очередное место, открыл рюкзак, достал кипу карт и ищешь где именно та, которую тебе дали на прошлой неделе местные сотрудники. Ещё одним негативным моментом этих поездок было время, которое приходилось проводить в транспорте. В итоге я решил избавиться от одного из неудобств, а именно купить программатор и написать программу-менеджер, которая избавит от необходимости таскать с собой кучу карт (все равно ношу в рюкзаке нетбук, а программатор много веса не добавит) и позволит вести базу, по которой можно будет быстро найти карту от нужного помещения для заданного учреждения, записать идентификатор на болванку и воспользоваться им по назначению. Сказано - сделано, вчера, во время очередной серии поездок, написал соответствующую программку, которую далее и рассмотрю подробнее.
Также обозначим формат карт, который, как оказалось, является доминирующим по неведомой мне причине - это EM-4100. Мимоходом, в магазине со всякой электроникой, был куплен программатор китайского производства, к которому прилагались драйвера для USB-UART моста модели CP210x производства Silicon Laboratories и стремный софт с китайским интерфейсом (имеющий в своем арсенале только функции чтения и записи идентификатора карты), который все же пригодился в дальнейшем.

Первым делом встал вопрос, чем пользоваться для взаимодействия с устройством. Беглый обзор доступных библиотек не особо меня вдохновил, поэтому я решил взять дизассемблер и посмотреть как устроен прилагающийся продукт. Софт оказался написан на Visual Basic, о чем намекнула секция импорта, состоящая из одной MSVBVM60.DLL.

VB Decompiler показал, что используются следующие функции из сторонних библиотек:

Таким образом, софт оказался завязан на некую MasterRD.dll, которая, в свою очередь, использовала MasterCom.dll. С помощью отладчика я выяснил, что для подключения к устройству использовалась функция rf_init_com(int port, int baud_rate), для отключения rf_ClosePort(void), для чтения идентификатора карты Read_Em4001(void * dst) и для записи Standard_Write(char a1, char a2, const void * src, char a4). Также обнаружилась полезная функция rf_beep(unsigned short hz, unsigned char ms) и обращение к Reset_Command(void) непонятно зачем.

Результирующий перечень прототипов:

Аргументы первых пяти функций не вызвали затруднений, однако с последней сначала возникло некоторое недопонимание. Через некоторое время выяснилось, что для записи десятизначного идентификатора карты (10 символов в hex или 5 байт данных) эта функция вызывается три раза примерно следующим образом:

Поэксперементировав с записью, обнаружил, что в третьем вызове в ptr всегда хранится следующая последовательность байт:

0x00, 0x14, 0x80, 0x40

Закономерность для первых двух вызовов оставалась загадкой. На помощь пришел гугл, который помог найти формат кодирования данных. Все оказалось довольно просто:

Допустим, мы хотим записать последовательность 123456789A на карту. По сути это 5 байтов или 40 бит данных (D00..D39), которые дополняются статичным заголовком (9 единичных битов), битом четности для каждых четырех байт (P0..P9) и стоп-битом в конце (S0). Плюс считается бит четности для каждого из столбцов бит (PC0..PC3). Далее все это складывается в здоровенное 64 битное число, которое и передается в два захода (по 4 байта) первыми двумя вызовами Standard_Write. Подробнее о протоколе можно почитать тут (отсюда и была взята картинка для наглядности).
Теперь перейдем к коду. Первоочередной задачей является написание функции, которая будет преобразовывать записываемый идентификатор вышеописанным образом.

Костяк взаимодействия готов, реализуем небольшой GUI с маджонгом и гейшами WinAPI и говнокодом. Результат будет выглядеть примерно так:

Начнем, как обычно, с заголовочного файла и вспомогательных функций:

Теперь WinMain и DlgProc:

INI-файл, как видно из кода выше, хранит в себе сохраненные идентификаторы карт и дополнительные пользовательские данные, которые можно указать в интерфейсе программы. То есть можно довольно быстро найти нужную карту, записать на пустую болванку и воспользоваться.
Опишем формат хранения данных в INI-файле, класс для работы с которыми (CIniFile) использовался в коде выше:

И, наконец, файл ресурсов (за вычетом студийной генеренки), который можно было и не приводить, но пусть будет.

Не были рассмотрены реализация класса для работы с INI-файлами, так как она была найдена в интернете, и небольшой вспомогательный файл для работы со строками.
Итак, поставленная цель достигнута всего-то за день поездок, что не может не радовать.

Проект для MSVC 2010 и скомпилированный экзешник: скачать
GitHub: rfid-card-manager

Жизненный RFID: 10 комментариев

  1. Вот так запросто взял и сделал. Очень круто.
    P.s. Kaimi, какой у тебя нетбук? Хард не страдает от постоянной тряски?

  2. Немного не в тему, но всё же: почему везде только windows? Почему не используешь linux или что-то подобное? Сила привычки, идеология или просто лень уходить с уже изученного места?

    1. Не использую где? Для себя мне неудобно, т.к. я предпочитаю, чтобы все из коробки работало без дополнительных манипуляций, настроек и прочих заморочек, не говоря уже о том, что ПО под Win субъективно больше.

      1. >>Не использую где?
        Не используешь для написания десктопного софта, типа того, что описан здесь.
        А про "из коробки" - да в той же убунте уже давно не нужны пляски с бубном. Даже в старом дебиане - всё работает из коробки.
        Ладно, ответ на свой вопрос я получил, спасибо.

        Тогда другой вопрос: можешь описать какие ide\редакторы ты юзаешь для разработки? Было бы классно услышать ответ по каждому языку + используемые плагины в этих редакторах, если таковые есть.

        1. Нужны, когда речь заходит о времени автономной работы или видеокартах.
          Редакторы/IDE... MSVC 10 (С/C++) и Notepad++ (все остальное), плагинами в общем-то не пользуюсь, достаточно подсветки синтаксиса.

        2. Добавлю свое мнение по линуксу: он работает из коробки до тех пор, пока ты не обновляешь его или не ставишь новый софт. Потом наверняка что-то поедет вплоть до кернел паников. Знаком лично с такими проблемами.

  3. *ответ на диалог выше. вп кидает мне ошибку "ОШИБКА: пожалуйста, введите комментарий."*

    Возможно, время автономной работы для меня сейчас не критично. А последние версии видеокарт на последнем ядре прекрасно взлетают после установки оф. драйвера: всё как в винде - зашел, скачал, в два клика поставил.

    Хм. Я кернел паник последний раз видел года 4 назад. А падения после обновлений - года два. Хотя, обновления системы в целом на новую версию - действительно часто приводят к фейлу.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *