using System;
using System.Runtime.InteropServices;
using Microsoft.Win32.SafeHandles;

namespace Rglib.Interop {
    using error_t = UInt32;



    public static class Methods {
        /// <summary>
        /// Имя библиотеки
        /// </summary>
        public const string DllName = "librgsec.dll";

        /// <summary>
        /// Выполняет инициализацию внутренних механизмов библиотеки.
        /// </summary>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_InitializeLib();

        /// <summary>
        /// Завершает работу внутренних механизмов библиотеки.
        /// </summary>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Uninitialize();


        /// <summary>
        /// Закрывает и уничтожает ранее выделенный ресурс по указанному дескриптору.
        /// </summary>
        /// <param name="handle">Дескриптор ресурса.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint RG_CloseResource([In] IntPtr handle);

        /// <summary>
        /// Выполняет поиск доступных точек подключения.
        /// </summary>
        /// <param name="pEndPointListHandle">Указатель на переменную, в которомю будет записан дескриптор списка найденных точек подключения.</param>
        /// <param name="pCount">Указатель на переменную, по которому будет сохранено колличество элементов в списке результатов.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint RG_FindEndPoints([In] [Out] ref IntPtr pEndPointListHandle, [MarshalAs(UnmanagedType.U1)]RG_ENDPOINT_TYPE endpointTypeMask, ref uint pCount);

        /// <summary>
        /// Извлекает из списка результатов, полученного с помощью функции RG_GetEndpointList, информацию о точке подключения по указанному индексу.
        /// </summary>
        /// <param name="endPointListHandle">Дескриптор списка точек подключения, полученный через RG_GetEndpointList.</param>
        /// <param name="mListIndex">Индекс в списке.</param>
        /// <param name="pEndpointInfo">Указатель на структуру информации о точке подключения.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_GetFoundEndPointInfo([In] IntPtr endPointListHandle, UInt32 mListIndex,
            [In, Out] ref RG_ENDPOINT_INFO pEndpointInfo);
        /// <summary>
        /// Выполняет поиск устройств по всем доступным точкам подключения.
        /// </summary>
        /// <param name="pDevicesListHandle">Указатель на переменную, в которомю будет записан дескриптор списка найденных устройств.</param>
        /// <param name="pCount">Указатель на переменную, по которому будет сохранено колличество элементов в списке результатов.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern uint RG_FindDevices([In] [Out] ref IntPtr pDevicesListHandle, [MarshalAs(UnmanagedType.U1)]RG_ENDPOINT_TYPE endpointTypeMask, ref uint pCount);

        /// <summary>
        /// Извлекает из списка результатов, полученного с помощью функции RG_GetDevicesList, информацию об устройстве по индексу.
        /// </summary>
        /// <param name="deviceListHandle">Дескриптор списка найденных устройств, полученный через RG_GetDevicesList.</param>
        /// <param name="mListIndex">Индекс в списке.</param>
        /// <param name="pDeviceInfoExt">Указатель на структуру расширенной информации об устройстве.</param>
        /// <param name="pEndpointInfo">Указатель на структуру информации о точке подключения.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_GetFoundDeviceInfo([In] IntPtr deviceListHandle, UInt32 mListIndex,
            [In, Out] ref RG_ENDPOINT_INFO pEndpointInfo, [In, Out] ref RG_DEVICE_INFO_EXT pDeviceInfoExt);

        /// <summary>
        /// Инициализация устройства.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_InitDevice([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Инициализация устройства.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_CloseDevice([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Сбрасывает состояние устройства. Потребуется повторная инициализация.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_ResetDevice([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Запрос расширенной информации об устройстве.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pDeviceInfo">Указатель на структуру расширенной информации об устройстве.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_GetInfoExt([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In, Out] ref RG_DEVICE_INFO_EXT pDeviceInfo);

        /// <summary>
        /// Задает для устройство типы считываемых карт. Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="mCardsFamilyMask">Маска типов считываемых карт, согласно E_RG_CARD_FAMILY_CODE.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_SetCardsMask([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In, MarshalAs(UnmanagedType.U1)] RG_CARD_FAMILY_CODE mCardsFamilyMask);

        /// <summary>
        /// Удаляет все профили из памяти устройства. Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_ClearProfiles([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Записывает профиль в память устройства. Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="mProfileNum">Номер профиля, под которым он будет записан в память устройства.</param>
        /// <param name="mBlockNum">Номер блока карты.</param>
        /// <param name="pCardAuthParams">Указатель на структуру параметров авторизации карты.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_WriteProfile([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte mProfileNum,
            byte mBlockNum, [In] ref RG_CARD_AUTH_PARAMS pCardAuthParams);

        /// <summary>
        /// Записывает кодограмму в память устройства. Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="mCodogrammNum">Номер кодограммы, под которым она будет записана в память устройства.</param>
        /// <param name="pCodogramm">Указатель на структуру представляющую кодограмму.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_WriteCodogramm([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            byte mCodogrammNum, [In] ref RG_CODOGRAMM pCodogramm);

        /// <summary>
        /// Запускает выполнение кодограмм на указанных каналах индикации на заданнном уровне приоритета.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// Кодограммы должны быть записаны в память устройства методом RG_WriteCodogramm
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="mPriority">Приоритет выполнения.</param>
        /// <param name="mSChannelNum">Номер кодограммы для звукового канала.</param>
        /// <param name="mRChannelNum">Номер кодограммы для красного канала.</param>
        /// <param name="mGChannelNum">Номер кодограммы для зеленого канала.</param>
        /// <param name="mBChannelNum">Номер кодограммы для синего канала.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_StartCodogramm([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte mPriority,
            byte mSChannelNum, byte mRChannelNum, byte mGChannelNum, byte mBChannelNum);


        /// <summary>
        /// Записывает данные в блок памяти карты по указанному номеру профиля.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// Профиль должен быть предварительно записан в память устройства методом RG_WriteProfile.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pMemory">Указатель на структуру данных блока памяти. Намоер профиля указывается в pMemory->profile_block.</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_WriteBlock([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In] ref RG_CARD_MEMORY pMemory);

        /// <summary>
        /// Записывает данные в указанный блок памяти карты используя указанные параметры авторизации.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pMemory">Указатель на структуру данных блока памяти. Намер блока указывается в pMemory->profile_block.</param>
        /// <param name="pCardAuthParams">Указатель на структуру параметров авторизации карты.</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_WriteBlockDirect([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In] ref RG_CARD_MEMORY pMemory, [In] ref RG_CARD_AUTH_PARAMS pCardAuthParams);

        /// <summary>
        /// Считывает данные из указаннного блока памяти карты используя указанные параметры авторизации.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pMemory">Указатель на структуру данных блока памяти. Намер блока указывается в pMemory->profile_block.</param>
        /// <param name="pCardAuthParams">Указатель на структуру параметров авторизации карты.</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_ReadBlockDirect([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In, Out] ref RG_CARD_MEMORY pMemory, [In] ref RG_CARD_AUTH_PARAMS pCardAuthParams);

        /// <summary>
        /// Считывает данные из указаннного блока памяти карты используя указанные параметры авторизации.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pStatusType">Указатель на переменную, по которому будет записано текущее значение татуса.</param>
        /// <param name="pPinStates">Указатель на переменную, по которому будут записаны флаги текущего состояния входов/выходов.</param>
        /// <param name="pCardInfo">Указатель на структуру информации о карте, заполняется в зависимости от текущего статуса.</param>
        /// <param name="pMemory">Указатель на структуру данных, считанных из блока памяти карты при успешной авторизации по профилю. Номер профиля сохраняется в pMemory->profile_block.</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_GetStatus([In] ref RG_ENDPOINT pEndPoint, byte mAddress,
            [In, Out, MarshalAs(UnmanagedType.U1)] ref RG_STATUS_TYPE pStatusType, [In, Out] ref byte pPinStates,
            [In, Out] ref RG_CARD_INFO pCardInfo, [In, Out] ref RG_CARD_MEMORY pMemory);

        /// <summary>
        /// Подписка на события устройства согласно маске.
        /// </summary>
        /// <param name="pDeviceEventsQueue">Указатель на переменную, в которомю будет записан дескриптор очереди событий устройства для текущей подписки.</param>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="mEventsMask">Маска типов событий устройства.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Subscribe([In, Out] ref IntPtr pDeviceEventsQueue, ref RG_ENDPOINT pEndPoint, byte mAddress, [MarshalAs(UnmanagedType.U4)] RG_DEVICE_EVENT_TYPE mEventsMask, SafeWaitHandle waitHandle);

        /// <summary>
        /// Извелкает событие из очереди событий устройства или ожидает поступления нового события при пустой очереди.
        /// </summary>
        /// <param name="deviceEventsQueue">Дескриптор очереди событий устройства.</param>
        /// <param name="pEventType">Указатель на переменную, в которую будет записан тип извлеченного события.</param>
        /// <param name="pEventMem">Указатель на указатель на область памяти, по которому будет аписан адрес текущего экземпляра события.</param>
        /// <param name="mPollWaitTimeoutMs">Время ожидания при отсутствии новых событий в очереди.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_PollEvents(IntPtr deviceEventsQueue, [In, Out, MarshalAs(UnmanagedType.U4)] ref RG_DEVICE_EVENT_TYPE pEventType, [In, Out] ref IntPtr pEventMem, UInt32 mPollWaitTimeoutMs);


        /// <summary>
        /// Изолирует устройство от потока опроса
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_IsolateDevice([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Снимает изоляцию с устройства
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_ResetIsolation([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Задает состояние управляющего выхода/порта по его номеру на указанное время.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// /// <param name="outputNum">Номер выхода.</param>
        /// <param name="state">Новое состояние. Если указано <c>true</c> выход будет подключени к подтяжке, иначе - к земле.</param>
        /// <param name="timeSec">Время переключения в секундах, 0 = постоянно.</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_SetControlOutputState([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte outputNum, bool state, byte timeSec);

        /// <summary>
        /// Снимает изоляцию с устройства
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <returns>Код ошибки</returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_ResetField([In] ref RG_ENDPOINT pEndPoint, byte mAddress);

        /// <summary>
        /// Выполняет цикл запроса карт в поле, процедуру антиколлизии и выбор карты.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// При наличии активных подписок на события, требуется вызов RG_IsolateDevice().
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pSak">Указатель на переменную для записи кода SAK (Select Acknowledge)</param>
        /// <param name="pAtq">Указатель на переменную для записи кода типа карты Mifare.</param>
        /// <param name="pUidBuf">Указатель на блок памяти для сохранения UID выбранной карты.</param>
        /// <param name="pAtq">Размер блока памяти по указателю pUidBufSize.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Iso_Ras([In] ref RG_ENDPOINT pEndPoint, byte mAddress, [In, Out] ref ushort pSak, [In, Out] ref ushort pAtqa, [In, Out] byte[] pUidBuf, int uidBufSize);

        /// <summary>
        /// Выполняет команду перехода на обмен по ISO 14443-4
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// При наличии активных подписок на события, требуется вызов RG_IsolateDevice().
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pAtsBuf">Указатель на блок памяти для записи UID выбранной карты.</param>
        /// <param name="atsBufSize">Размер блока памяти по указателю pAtsBuf</param>
        /// <param name="pAtsSize">Указатель на переменную, для записи количества байт, сохраненных в pAtsBuf.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Iso_Rats([In] ref RG_ENDPOINT pEndPoint, byte mAddress, [In, Out] byte[] pAtsBuf, int atsBufSize, ref int pAtsSize);

        /// <summary>
        /// Выполняет произвольную передачу данных по протоколу ISO14443-4.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// При наличии активных подписок на события, требуется вызов RG_IsolateDevice().
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="pDataBuf">Указатель на блок памяти, в котором хранятся передаваемые данные.</param>
        /// <param name="dataBufSize">Размер блока памяти по указателю pDataBuf.</param>
        /// <param name="pRespBuf">Указатель на блок памяти, в который будет зхаписан ответ на переданное сообщение.</param>
        /// <param name="respBufSize">Размер блока памяти по указателю respBufSize.</param>
        /// <param name="pRespSize">Указатель на переменную, для записи количества байт, сохраненных в pRespBuf.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Iso_Exchange([In] ref RG_ENDPOINT pEndPoint, byte mAddress, [In] byte[] pDataBuf, int dataBufSize, [In, Out] byte[] pRespBuf, int respBufSize, ref int pRespSize);

        /// <summary>
        /// Авторизация сектора карты Mifare.
        /// Требуется предварительная инициализация устройства методом RG_InitDevice.
        /// При наличии активных подписок на события, требуется вызов RG_IsolateDevice().
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="atsBufSize">Номер блока сектора, в который производится авторизация.</param>
        /// <param name="pKeyBuf">Указатель на блок памяти с данными ключа авторизации.</param>
        /// <param name="keyBufSize">Размер блока памяти/данных по указателю pKeyBuf (максимально допустимая длинна ключа - 16 байт).</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_Iso_Auth([In] ref RG_ENDPOINT pEndPoint, byte mAddress, ushort blockNum, [In] byte[] pKeyBuf, int keyBufSize);

        /// <summary>
        /// Выполняет авторизацию сектора карты Mifare Classic
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="blockNum">Номер блока сектора, в который производится авторизация.</param>
        /// <param name="keyType">Тип используемого ключа авторизации (A/B).</param>
        /// <param name="pKeyBuf">Указатель на блок памяти, содержащей, как минимум, 6 байт данныхъ ключа авторизации.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_MF_AuthorizeClassic([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte blockNum, byte keyType, [In] byte[] pKeyBuf);

        /// <summary>
        /// Выполняет чтение данных из блока памяти карты Mifare Classic/Plus
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="flags">ФЛаги определяющие тип карты, с которой производится чтение.</param>
        /// <param name="blockNum">Номер блока карты.</param>
        /// <param name="pDataBuf">Указатель на блок памяти, в которую будут записаны данные считанные из блока памяти карты.</param>
        /// <param name="dataBufSize">Размер блока памяти по указателю pDataBuf.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_MF_ReadBlock([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte blockNum, byte flags, [In] byte[] pDataBuf, int dataBufSize);

        /// <summary>
        /// Выполняет запись данных в блок памяти карты Mifare Classic/Plus
        /// </summary>
        /// <param name="pEndPoint">Указатель на структуру параметров подключения.</param>
        /// <param name="mAddress">Адрес устройства (0...3, в зависимости от типа подключения).</param>
        /// <param name="flags">Флаги определяющие тип карты, в память которой производится запись (Classic/Plus).</param>
        /// <param name="blockNum">Номер блока карты.</param>
        /// <param name="pDataBuf">Указатель на блок памяти содержащей данные, которые необходимо записать в блок памяти карты.</param>
        /// <param name="dataBufSize">Размер блока памяти по указателю pDataBuf.</param>
        /// <returns></returns>
        [DllImport(DllName, CallingConvention = CallingConvention.Cdecl)]
        public static extern error_t RG_MF_WriteBlock([In] ref RG_ENDPOINT pEndPoint, byte mAddress, byte blockNum, byte flags, [In] byte[] pDataBuf, int dataBufSize);
    }
}