/*
 * Copyright(C) 2000 Проект ИОК
 *
 * Этот файл содержит информацию, являющуюся
 * собственностью компании Крипто Про.
 *
 * Любая часть этого файла не может быть скопирована,
 * исправлена, переведена на другие языки,
 * локализована или модифицирована любым способом,
 * откомпилирована, передана по сети с или на
 * любую компьютерную систему без предварительного
 * заключения соглашения с компанией Крипто Про.
 */

/*!
 * \file $RCSfile$
 * \version $Revision: 190088 $
 * \date $Date:: 2019-03-07 14:22:12 +0300#$
 * \author $Author: sagafyin $
 * \brief Связующий интерфейс от считывателя и смарт-карты к READER.
 */

#if !defined( READER_SCARD_SCARD_H )
#define READER_SCARD_SCARD_H

#include "reader.kit/reader.h"

/*!
* \ingroup scard_interface
* \def RSCARD_FUN_CONNECT_CARRIER
* \brief Функция, оповещающая о соединении со смарт-картой. 
*
* Функция, вызывается после установления соединения со смарт-картой через SCardConnect. 
* Её основная задача: передать в модуль поддержки носителя колбэки APDU, через которые можно посылать команды в карту.
*
* Также из неё возвращается число поддерживаемых данным модулем апплетов. Если ATR-у карты соответствует несколько
* модулей поддержки, то общее число апплетов, которыми будет оперировать провайдер, будет суммой чисел, возвращенных
* из каждого модуля. 
* \sa #TSCardInfoConnectCarrier
*
*/
#define RSCARD_FUN_CONNECT_CARRIER 0x2501

#define PCSC_CLA_NUM 0
#define PCSC_INS_NUM 1
#define PCSC_P1_NUM 2
#define PCSC_P2_NUM 3
#define PCSC_LC_NUM 4
#define PCSC_DATA_NUM 5

#define PCSC_APDU_HEADER 4

#define MAX_APDU_LEN 0x100

/*!
 * \ingroup rdr_ext_fkc_type
 * \defgroup rscard_specific_info Структуры передачи данных, специфичные для смарткарт
 * \brief Структуры передачи данных к функциям специфичным для библиотеки
 *  поддержки смарт-карт.
 * \{
 */

/*!
 * \brief Структура используемая для поиска объекта данных в структуре BER-TLV.
 * \sa #TSCardInfoConnectCarrier
 */
typedef struct 
{
    unsigned char class_type; //!< "Класс" поля тега BER-TLV (биты 6-8).
    unsigned char class_tag; //!< "Номер тега" поля тега BER-TLV (биты 1-5).
    unsigned char simple_tag; //!< Тег искомого объекта данных.
    TSupSysInfoUntyped input; //!< Входная структура для поиска в формате BER-TLV.
    TSupSysInfoUntyped output; //!< Найденная структура: элементарный объект. При вызове функции необходимо выделить память под максимально возможный результат и указать его размер в output.length. На выходе output.length возвращает размер найденных данных.
} TSCardInfoBerTLVSearch;

/*!
 * \brief Структура используемая для поиска объекта данных в структуре 
 * SIMPLE-TLV.
 * \sa #TSCardInfoConnectCarrier
*/
typedef struct 
{
    unsigned char simple_tag; //!< Тег искомого объекта данных.
    TSupSysInfoUntyped input; //!< Входная структура для поиска в формате SIMPLE-TLV.
    TSupSysInfoUntyped output; //!< Найденная структура: элементарный объект. При вызове функции необходимо выделить память под максимально возможный результат и указать его размер в output.length. На выходе output.length возвращает размер найденных данных.
} TSCardInfoSimpleTLVSearch;

/*!
 * \brief Указатель на функцию поиска объекта в структуре BER-TLV
 *
 * Вспомогательная функция, может использоваться для поиска объекта в 
 * структуре BER-TLV. 
 * \sa #TSCardInfoBerTLVSearch
 */
typedef DWORD (*TSCardBerTLVSearch)( TSCardInfoBerTLVSearch *);

/*!
 * \brief Указатель на функцию поиска объекта в структуре SIMPLE-TLV
 *
 * Вспомогательная функция, может использоваться для поиска объекта в 
 * структуре SIMPLE-TLV. 
 * \sa #TSCardInfoSimpleTLVSearch
 */
typedef DWORD (*TSCardSimpleTLVSearch)( TSCardInfoSimpleTLVSearch *);

/*!
 * \brief Указатель на функцию отправки APDU-команды.
 *
 * Пересылает команду в SCardTransmit ровно в том виде, как её сформировал модуль поддержки. 
 * Возвращает "сырой" ответ. 
 * \sa #TSCardInfoConnectCarrier
 */
typedef DWORD(*TSCardAPDUCmd) (TSupSysEContext *, BYTE *, size_t, BYTE *, size_t *);

/*!
 * \brief Колбэк обработки ошибки APDU.
 * Принимает на вход status-word. Должен возвращать правильную ошибку, соответствующую ситуации.
 * Может вернуть дополнительные данные размером в DWORD, если нужно. Например, число оставшихся попыток ввода пароля,
 * если карта возвращает их в status-word.
 * \sa #TSCardInfoConnectCarrier, #TSCardSimpleAPDUCmd
 */
typedef DWORD(*TGetErrorCode) (unsigned short, DWORD *);

/*!
 * \brief "Умная" функция отправки APDU.
 * Принимает на вход признак защищенного канала, колбэк обработки ошибки (#TGetErrorCode), заголовок APDU (CLA|INS|P1|P2), входные данные, их длину, буфер под выходные данные и их ожидаемую длину.
 * Сама правильно формирует команду в зависимости от протокола. По переданному callback-у обработки ошибки сама анализирует status-word.
 * \sa #TSCardInfoConnectCarrier, #TSCardSimpleAPDUCmd
 */
typedef DWORD(*TSCardSimpleAPDUCmd)(TSupSysEContext * /*reader_ctx*/,
    BOOL /*isSM*/,
    TGetErrorCode /*get_error_fun*/,
    const BYTE * /*apdu_header*/,
    const BYTE * /*apdu_in*/,
    size_t /*apdu_in_len*/,
    BYTE * /*apdu_out*/,
    size_t * /*apdu_out_len*/,
    DWORD* /*add_out_param*/);

/*!
 * \brief Колбэк проверки статуса подключения.
 * \sa #TSCardInfoConnectCarrier
 */
typedef DWORD(*TSCardGetStatusCmd) (TSupSysEContext * /*reader_ctx*/);

/*!
 * \brief Структура подключения смарт-карты.
 *
 * Передаёт информацию об установленном подключении (ATR, protocol) и колбэки для отправки APDU. Используется в #RSCARD_FUN_CONNECT_CARRIER
 */
typedef struct 
{    
    TSCardAPDUCmd apdu_cmd; //!< Функция отправки APDU-команды
    TSCardAPDUCmd secure_apdu_cmd; //!< Функция отправки защищенной APDU-команды, защищенные операции выполняет сама. Если карта в ответ на защищенную команду вернула только status word (2 байта), то функция запишем его в выходной буфер, а сама вернет CPR_ERR_RDR_SM.
    unsigned protocol; //!< Протокол, которым было произведено подключение к карте (SCARD_PROTOCOL_T0/SCARD_PROTOCOL_T1)
    TSupSysInfoUntyped atr; //!< ATR карты.
    TSupSysEContext *reader; //!< Контекст считывателя. Используется для передачи в callback'и APDU.
    TSCardBerTLVSearch ber_tlv_search; //!< Указатель на вспомогательную функцию, которая может использоваться при поиске внутри BER-TLV структуры.
    TSCardSimpleTLVSearch simple_tlv_search; //!< Указатель на вспомогательную функцию, которая может использоваться при поиске внутри SIMPLE-TLV структуры.
    TCHAR *connect; //!< Имя коннекта: раздела в реестре, по регистрации которого было произведено подключение.
    BOOL need_reset_on_disconnect; //!< [out] Признак того, что при отключении от карты, её нужно сбрасывать.
    BOOL need_reset_on_end_transaction; //!< [out] Признак того, что карту нужно сбрасывать в конце транзакции.
    BOOL need_connect_after_reconnect; //!< UNUSED, оставили только чтобы не сломать совместимость со сторонними модулями поддержки.
    unsigned int app_count;  //!< [out] Максимально возможное число апплетов, поддерживаемых данным модулем поддержки.
    TSCardSimpleAPDUCmd simple_apdu_cmd; //!< "Умная" функция отправки APDU. Предпочтительна к использованию. Сама правильно формирует команду в зависимости от протокола. По переданному callback-у обработки ошибки сама анализирует status-word.
    TSCardGetStatusCmd get_status_cmd; //!< Функция проверки состояния карты.
} TSCardInfoConnectCarrier;

/*!\}*/
#endif /* READER_SCARD_SCARD_H */
