#ifndef E502API_H
#define E502API_H

#include "x502api.h"


#ifdef __cplusplus
extern "C" {
#endif

/***************************************************************************//**
  @addtogroup const_list
  @{
  *****************************************************************************/
/** @brief События поиска сетевых сервисов

    Коды событий, возникающих при поиске сетевых сервисов, возвращаемые
    функцией E502_EthSvcBrowseGetEvent() */
typedef enum {
    E502_ETH_SVC_EVENT_NONE     = 0, /**< Ни одного события не произошло */
    E502_ETH_SVC_EVENT_ADD      = 1, /**< Обнаружено появление нового сетевого сервиса */
    E502_ETH_SVC_EVENT_REMOVE   = 2, /**< Обнаружено исчезновение ранее доступного
                                          сетевого сервиса */
    E502_ETH_SVC_EVENT_CHANGED  = 3  /**< Изменение параметров ранее обнаруженного
                                          сетевого сервиса */
} t_e502_eth_svc_event;

/** @} */

/***************************************************************************//**
    @addtogroup type_list
    @{
*******************************************************************************/

/***************************************************************************//**
   @brief Описатель конфигурации сетевого интерфейса

    Непрозрачный указатель на структуру, содержащую параметры конфигурации
    сетевого интерфейса модуля E-502.
    Пользовательской программе не доступны поля структуры напрямую, а только
    через функции библиотеки.
    Описатель конфигурации создается с помощью E502_EthConfigCreate() и в конце работы
    освобождается с помощью E502_EthConfigFree().
    Как правило все настройки не должны заполняться пользователем вручную,
    обычно сперва они считываются из устройства с помощью E502_EthConfigRead(),
    после чего часть настроек можно изменить и сохранить в модуль через
    E502_EthConfigWrite()
  *****************************************************************************/
typedef struct st_e502_eth_config_state* t_e502_eth_config_hnd;

/**************************************************************************//**
    @brief Описатель контекста поиска устройств в сети

    Указатель на непрозрачную структуру с информацией о состоянии текущего
    сеанса поиска устройств в сети. Создается при начале поиска вызовом
    E502_EthSvcBrowseStart() и уничтожается с помощью E502_EthSvcBrowseStop()
  *****************************************************************************/
typedef struct st_e502_eth_svc_browse_context *t_e502_eth_svc_browse_hnd;
/**************************************************************************//**
    @brief Описатель сетевого сервиса

    Указатель на непрозрачную структуру с информацией о сервисе в сети,
    соответствующем одному модулю E-502. Используется при автоматическом обнаружении
    устройств в локальной сети. Создается при вызове E502_EthSvcBrowseGetEvent()
    и уничтожается с помощью E502_EthSvcRecordFree()
  *****************************************************************************/
typedef struct st_e502_eth_svc_record *t_e502_eth_svc_record_hnd;

/** @} */

/***************************************************************************//**
    @addtogroup func_open
    @{
*******************************************************************************/

/***************************************************************************//**
    @brief Получение списка серийных номеров модулей E-502, подключенных по USB

    Функция возвращает список номеров всех найденных модулей E-502, независимо от
    того, открыты они сейчас или нет.

    Функция на данный момент не поддерживает флаг #X502_GETDEVS_FLAGS_ONLY_NOT_OPENED.

 @param[in] serials   Массив размером size*#X502_SERIAL_SIZE байт, в который
                      будут сохранены серийные номера найденных модулей.
                      Может быть NULL, если size=0, а devcnt!=NULL, в случае,
                      если нужно только получить количество модулей в системе.
 @param[in] size      Определяет, сколько максимально серийных номеров может
                      быть сохранено в массив serial. Будут сохранены только
                      первые size серийных номеров.
                      Может быть 0, если serials=NULL
 @param[in] flags     Флаги из #t_x502_getdevs_flags, определяющие поведение
                      функции.
 @param[out] devcnt   Если devcnt!=NULL, то в данную переменную сохраняется
                      общее число найденных модулей E502
                      (может быть больше size).
 @return              Если <0 - код ошибки, иначе количество сохраненных
                      серийных номеров в массиве serials (всегда <= size)
*******************************************************************************/
X502_EXPORT(int32_t) E502_UsbGetSerialList(char serials[][X502_SERIAL_SIZE], uint32_t size,
                                           uint32_t flags, uint32_t *devcnt);


/***************************************************************************//**
    @brief Открытие модуля E-502, подключенного по USB, по его серийному номеру

    Функция устанавливает связь с модулем E-502, подключенным по интерфейсу USB,
    по его серийному номеру.

    После успешного выполнения этой функции, пользователь получает эксклюзивный
    доступ к модулю через описатель модуля. До закрытия связи с помощью
    X502_Close() никто другой установить связь с модулем не сможет
    (будет возвращена ошибка #X502_ERR_DEVICE_ACCESS_DENIED).

    Если в качестве серийного номера передан NULL или пустая строка, то будет
    установлена связь с первым найденным модулем, с которым получится успешно
    ее установить.
    Если в системе нет ни одного модуля, то будет возвращена ошибка
    #X502_ERR_DEVICE_NOT_FOUND. Если в системе присутствуют модули E-502, но
    соединение ни с одним из них установить не удалось, то будет возвращена
    ошибка, полученная при попытке установить соединение с последним
    найденным модулем.

    После завершения работы с устройством соединение должно быть закрыто с
    помощью X502_Close().

    @param[in] hnd     Описатель устройства.
    @param[in] serial  Указатель на строку с серийным номером открываемого
                       модуля или NULL.
    @return            Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_OpenUsb(t_x502_hnd hnd, const char *serial);


/***************************************************************************//**
    @brief Открытие модуля E-502 по IP-адресу

    Функция устанавливает связь с модулем E-502, подключенным по интерфейсу Ethernet,
    для которого установлен указанный адрес IPv4.

    После завершения работы с устройством соединение должно быть закрыто с
    помощью X502_Close().

    @param[in] hnd     Описатель устройства.
    @param[in] ip_addr IPv4 адрес модуля  в виде 32-битного слова.
                        Для адреса "a.b.c.d" ip_addr = (a<<24)|(b<<16)|(c<<8)|d.
    @param[in] flags   Флаги, управляющие работой функции. Резерв, должны быть всегда 0.
    @param[in] tout    Время на установления подключения в мс. Если подключение
                       не удастся завершить за заданное время, то функция вернет ошибку.
    @return            Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_OpenByIpAddr(t_x502_hnd hnd, uint32_t ip_addr,
                                        uint32_t flags, uint32_t tout);

/** @} */

/***************************************************************************//**
    @addtogroup func_devrec
    @{
*******************************************************************************/

/***************************************************************************//**
    @brief Получить список записей, соответствующих подключенным модулям E502

    Функция находит все подключенные по интерфейсу USB модули E-502 и инициализирует
    записи о каждом найденном устройстве и сохраняет их в переданный список
    (если не нулевой).
    Возвращенные в списке записи должны быть очищены после использования
    с помощью X502_FreeDevRecordList() (также в случае повторного
    вызов E502_UsbGetDevRecordsList() с тем же массивом записей, записи, полученные
    при предыдущем вызове, должны быть сперва очищены).

 @param[out] list     Массив для сохранения записей о найденных устройствах.
                      Должен содержать место для сохранения не менее size записей.
                      Может быть NULL, если size=0, а devcnt!=NULL, в случае,
                      если нужно только получить количество модулей в системе.
 @param[in] size      Определяет, сколько максимально записей может
                      быть сохранено в массив list. Будут сохранены только
                      первые size записей, если устройств найдено больше.
 @param[in] flags     Флаги из #t_x502_getdevs_flags, определяющие поведение
                      функции.
 @param[out] devcnt   Если не нулевой указатель, то в данную переменную сохраняется
                      общее число найденных модулей E-502, подключенных по
                      интерфейсу USB (может быть больше size).
 @return              Если <0 --- код ошибки, иначе количество сохраненных
                      записей о найденных устройствах (всегда <= size).
                      Именно на этот размер нужно сделать в дальнейшем
                      X502_FreeDevRecordList() для освобождения памяти,
                      выделенной под информацию, на которую ссылается запись.
 ******************************************************************************/
X502_EXPORT(int32_t) E502_UsbGetDevRecordsList(t_x502_devrec* list, uint32_t size,
                                               uint32_t flags, uint32_t* devcnt) ;

/***************************************************************************//**
    @brief Создание записи о устройстве с указанным IP-адресом

    Данная функция инициализирует запись о устройстве, подключенном по интерфейсу
    Ethernet, с указанным IPv4 адресом. Данная функция только создает запись, но
    не проверяет наличие соответствующего устройства. Подключение к модулю
    выполняется аналогично другим записям через X502_OpenByDevRecord().

    @param[out] devrec  Указатель на запись устройства, которая должна быть
                       создана и заполнена нужными параметрами.
    @param[in] ip_addr IPv4 адрес модуля  в виде 32-битного слова (аналогично
                        параметру ip_addr функции E502_OpenByIpAddr()).
    @param[in] flags   Флаги. Резерв, должны быть всегда 0.
    @param[in] tout    Время для установления подключения в мс.
                       Данное время сохраняется в записи и используется при
                       последующем вызове X502_OpenByDevRecord(). Если подключение
                       не удастся завершить за это время, то функция
                       X502_OpenByDevRecord() вернет ошибку.
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_MakeDevRecordByIpAddr(t_x502_devrec *devrec, uint32_t ip_addr,
                                                uint32_t flags, uint32_t tout);


/***************************************************************************//**
    @brief Установка TCP-порта управляющего соединения для записи о устройстве

    Данная функция позволяет изменить TCP-порт управляющего соединения модуля
    E-502. Это может быть необходимо, если модуль E-502  и хост, с которого
    необходимо установить соединение, находятся в разных сетях и адрес модуля
    E-502 не доступен из сети хоста. В этом случае требуется настройка проброса
    портов на маршрутизаторе и при наличие более одного такого модуля E-502, т.к
    все соединения идут с маршрутизитором, то различить эти модули можно только
    по TCP-порту, если настроить разные порты при пробросе.
    В этом случае помимо порта управляющего соединения, необходимо изменить и
    порт соединения для передачи данных, вызвав E502_EthDevRecordSetDataPort().

    Данная функция должна быть вызвана для записи, созданной до этого с помощью
    E502_MakeDevRecordByIpAddr() и до открытия соединения с помощью
    X502_OpenByDevRecord().

    @param[in] devrec   Указатель на запись устройства, в которой нужно изменить
                         управляющий TCP-порт.
    @param[in] cmd_port Новое значение TCP-порта для управляющего соединения
    @return             Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthDevRecordSetCmdPort(t_x502_devrec *devrec, uint16_t cmd_port);

/***************************************************************************//**
    @brief Установка TCP-порта соединения передачи данных для записи о устройстве

    Функция аналогична E502_EthDevRecordSetCmdPort(), но изменяет TCP-порт для
    соединения, по которому идет обмен данных потоков ввода-вывода.

    @param[in] devrec   Указатель на запись устройства, в которой нужно изменить
                         управляющий TCP-порт.
    @param[in] data_port Новое значение TCP-порта для соединения передачи данных
    @return             Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthDevRecordSetDataPort(t_x502_devrec *devrec, uint16_t data_port);



/***************************************************************************//**
    @brief Создание записи о устройстве по описателю сетевого сервиса

    Данная функция инициализирует запись о устройстве, подключенном по интерфейсу
    Ethernet, соответствующему сетевому сервису, на который указывает переданный
    описатель сетевого сервиса. Этот описатель может быть получен с помощью
    функций поиска сетевых сервисов, соответствующих модулям E-502, в локальной сети.
    Данная функция только создает запись, но не проверяет наличие соответствующего
    устройства. Подключение к модулю выполняется аналогично другим
    записям через X502_OpenByDevRecord().
    Вся необходимая информация из описателя сетевого сервиса сохраняется в записи
    о устройстве, т.е. после вызова данной фунции при желании описатель
    сетевого сервиса можно сразу освобождать с помощью E502_EthSvcRecordFree().

    @param[out] devrec  Указатель на запись устройства, которая должна быть
                       создана и заполнена нужными параметрами.
    @param[in] svc     Описатель сетевого сервиса, полученный с помощью
                       E502_EthSvcBrowseGetEvent().
    @param[in] flags   Флаги. Резерв, должны быть всегда 0.
    @param[in] tout    Время для установления подключения в мс.
                       Данное время сохраняется в записи и используется при
                       последующем вызове X502_OpenByDevRecord(). Если подключение
                       не удастся завершить за это время, то функция
                       X502_OpenByDevRecord() вернет ошибку.
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_MakeDevRecordByEthSvc(t_x502_devrec *devrec, t_e502_eth_svc_record_hnd svc,
                                                uint32_t flags, uint32_t tout);

/** @} */


/***************************************************************************//**
    @addtogroup func_eth_config Функции для настройки сетевых параметров модуля E502
    @{
*******************************************************************************/




/***************************************************************************//**
    @brief Получение текущего IP-адреса устройства

    Функция возвращает IP-адрес устройства по которому было установлено соединение.
    То есть связь с устройством должна быть уже установлена и кроме того,
    установлена именно по интерфейсу Ethernet.
    @param[in]  hnd     Описатель устройства
    @param[out] ip_addr Текущий IPv4 адрес модуля  в виде 32-битного слова (аналогично
                        параметру ip_addr функции E502_OpenByIpAddr()).

    @return  Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_GetIpAddr(t_x502_hnd hnd, uint32_t *ip_addr);



/***************************************************************************//**
    @brief Создание описателя конфигурации сетевого интерфейса

    Создание описателя конфигурации сетевого интерфейса.
    В случае успешного выделения памяти инициализирует поля описателя
    значениями по-умолчанию.
    @return NULL в случае ошибки, иначе - описатель модуля
*******************************************************************************/
X502_EXPORT(t_e502_eth_config_hnd) E502_EthConfigCreate(void);

/***************************************************************************//**
    @brief Освобождение описателя конфигурации сетевого интерфейса.

    Освобождение памяти, выделенной под описатель конфигурации сетевого интерфейса
    с помощью E502_EthConfigCreate().
    После этого описатель уже использовать нельзя, независимо от возвращенного
    значения!
    @param[in] cfg     Описатель конфигурации сетевого интерфейса
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigFree(t_e502_eth_config_hnd cfg);



/***************************************************************************//**
    @brief Чтение текущей сетевой конфигурации интерфейса

    Функция читает текущие параметры интерфейса и сохраняет их в структуру,
    на которую указывает созданный с помощью E502_EthConfigCreate() описатель
    конфигурации сетевого интерфейса.

    Соединение с устройством при этом должно быть установлено, но может быть
    установлено по любому поддерживаемому интерфейсу.

    @param[in] hnd     Описатель устройства из которого нужно считать конфигурацию
    @param[in,out] cfg Описатель конфигурации сетевого интерфейса
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigRead(t_x502_hnd hnd, t_e502_eth_config_hnd cfg);


/***************************************************************************//**
    @brief Запись сетевой конфигурации интерфейса

    Функция передает модулю конфигурацию сетевого интерфейса, которую модуль
    должен сохранить в своей энергонезависимой памяти.

    При успешном выполнении данной функции модуль отключает Ethernet-интерфейс,
    настраивает его на новые параметры и снова его инициализирует, поэтому
    если соединение с устройством установлено по сети, то дальнейшая работа
    с устройством будет уже не возможна --- необходимо закрыть связь с устройством
    и установить ее заново.

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

    @param[in] hnd     Описатель устройства из которого нужно считать конфигурацию
    @param[in] cfg     Описатель конфигурации сетевого интерфейса
    @param[in] passwd  Строка с паролем для изменения конфигурации
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigWrite(t_x502_hnd hnd, t_e502_eth_config_hnd cfg,
                                         const char *passwd);


/***************************************************************************//**
   @brief Копирование содержимого сетевой конфигурации интерфейса

   Функция выполняет копирование всех параметров одной созданной конфигурации
   в другую конфирурацию, создавая полную копию.

    @param[in]  src_cfg Описатель исходной сетевой конфигурации интерфейса,
                        содержимое которой нужно скопировать.
    @param[out] dst_cfg Описатель сетевой конфигурации интерфейса, в которую
                        нужно скопировать содержимое исходной конфигурации
    @return             Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigCopy(t_e502_eth_config_hnd src_cfg,
                                        t_e502_eth_config_hnd dst_cfg);

/***************************************************************************//**
    @brief Определение, разрешен ли интерфейс Ethernet

    Функция возвращает, разрешен ли интерфейс Ethernet в указанной конфигурации.
    Если интерфейс не разрешен, то Ethernet контроллер полностью отключен.
    @param[in]  cfg    Описатель конфигурации сетевого интерфейса
    @param[out] en     Если интерфейс разрешен, то в данной переменной возвращается 1,
                       иначе --- 0
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetEnabled(t_e502_eth_config_hnd cfg, uint32_t *en);

/***************************************************************************//**
    @brief Разрешение интерфейса Ethernet

    Функция устанавливает, разрешена ли работа по интерфейсу Ethernet.
    Если интерфейс не разрешен, то Ethernet контроллер полностью отключен.
    @param[in] cfg    Описатель конфигурации сетевого интерфейса
    @param[in] en     0 означает запрет интерфейса Ethernet, 1 --- разрешение
    @return           Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetEnabled(t_e502_eth_config_hnd cfg, uint32_t en);

/***************************************************************************//**
    @brief Определение, разрешено ли автоматическое получение параметров IP

    Функция возвращает, разрешено ли автоматическое получение параметров IP
    (IP-адрес, маска подсети, адрес шлюза) с использованием DHCP/linklocal или
    используются статически заданные параметры.
    @param[in]  cfg    Описатель конфигурации сетевого интерфейса
    @param[out] en     Если разрешено автоматическое получение параметров, то
                       возвращается 1, иначе --- 0
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetAutoIPEnabled(t_e502_eth_config_hnd cfg, uint32_t *en);
/***************************************************************************//**
    @brief Разрешение автоматического получения параметров IP

    Функция устанавливает, разрешено ли автоматическое получение параметров IP
    (IP-адрес, маска подсети, адрес шлюза) с использованием DHCP/linklocal или
    используются статически заданные параметры.
    @param[in]  cfg    Описатель конфигурации сетевого интерфейса
    @param[in]  en     Если разрешено автоматическое получение параметров, то
                       возвращается 1, иначе --- 0
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetAutoIPEnabled(t_e502_eth_config_hnd cfg, uint32_t en);

/***************************************************************************//**
    @brief Определение, разрешен ли пользовательский MAC-адрес

    Функция возвращает, разрешен ли MAC-адрес, заданный пользователем, или
    используется заводской MAC-адрес.

    @param[in]  cfg    Описатель конфигурации сетевого интерфейса.
    @param[out] en     Если разрешен пользовательский MAC-адрес, то
                       возвращается 1, иначе (если используется заводской) --- 0
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetUserMACEnabled(t_e502_eth_config_hnd cfg, uint32_t *en);
/***************************************************************************//**
    @brief Определение, разрешен ли пользовательский MAC-адрес

    Функция возвращает, разрешен ли MAC-адрес, заданный пользователем, или
    используется заводской MAC-адрес.

    @param[in] cfg    Описатель конфигурации сетевого интерфейса.
    @param[in] en     Если разрешен пользовательский MAC-адрес, то
                       возвращается 1, иначе (если используется заводской) --- 0
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetUserMACEnabled(t_e502_eth_config_hnd cfg, uint32_t en);

/***************************************************************************//**
    @brief Получение установленного статического IP-адреса

    Функция возвращает заданный в конфигурации статический IP-адрес, который
    используется устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] ip_addr  Заданный IP-адрес в виде 32-битного слова (аналогично
                         параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetIPv4Addr(t_e502_eth_config_hnd cfg, uint32_t *ip_addr);
/***************************************************************************//**
    @brief Установка статического IP-адреса

    Функция устанавливает в конфигурации заданный статический IP-адрес, который
    будет использоваться  устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[in] ip_addr   Устанавливаемый IP-адрес в виде 32-битного слова (аналогично
                         параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetIPv4Addr(t_e502_eth_config_hnd cfg, uint32_t ip_addr);

/***************************************************************************//**
    @brief Получение установленной статической маски подсети

    Функция возвращает заданное в конфигурации значение маски подсети, которая
    используется устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] mask     Маска подсети в виде 32-битного слова (аналогично
                         параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetIPv4Mask(t_e502_eth_config_hnd cfg, uint32_t *mask);
/***************************************************************************//**
    @brief Установка статической маски подсети

    Функция устанавливает в конфигурации значение маски подсети, которая будет
    использоваться устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[in]  mask     Устанавливаемое значение маски подсети в виде 32-битного слова
                         (аналогично параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetIPv4Mask(t_e502_eth_config_hnd cfg, uint32_t mask);

/***************************************************************************//**
    @brief Получение установленного статического адреса шлюза

    Функция возвращает заданное в конфигурации значение адреса шлюза, который
    используется устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] gate     Адрес шлюза в виде 32-битного слова (аналогично
                         параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetIPv4Gate(t_e502_eth_config_hnd cfg, uint32_t *gate);
/***************************************************************************//**
    @brief Установка статического адреса шлюза

    Функция устанавливает в конфигурации значение адреса шлюза, который
    будет использоваться устройством, если запрещено автоматическое получение IP-параметров.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[in]  gate     Устанавливаемое значение адреса шлюза в виде 32-битного слова
                         (аналогично параметру ip_addr функции E502_OpenByIpAddr()).
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetIPv4Gate(t_e502_eth_config_hnd cfg, uint32_t gate);

/***************************************************************************//**
    @brief Получение установленного пользовательского MAC-адреса

    Функция возвращает заданное в конфигурации значение пользовательского MAC-адреса,
    который используется устройством при явном его разрешении (см.
    E502_EthConfigSetUserMACEnabled()).

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] mac      Пользовательский MAC-адрес устройства в виде массива из
                         #X502_MAC_ADDR_SIZE байт в порядке записи адреса
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetUserMac(t_e502_eth_config_hnd cfg, uint8_t *mac);
/***************************************************************************//**
    @brief Установка пользовательского MAC-адреса

    Функция устанавливает в конфигурации значение пользовательского MAC-адреса,
    который будет использоваться устройством при явном его разрешении (см.
    E502_EthConfigSetUserMACEnabled()).

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[in]  mac      Устанавливаемое значение пользовательского MAC-адрес устройства
                         в виде массива из #X502_MAC_ADDR_SIZE байт в порядке записи адреса
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetUserMac(t_e502_eth_config_hnd cfg, const uint8_t *mac);
/***************************************************************************//**
    @brief Получение заводского MAC-адреса устройства

    Функция возвращает значение заводского MAC-адреса устройства, которому
    соответствует переданная первым параметром конфигурация.
    Заводской MAC-адрес, используемый устройством по-умолчанию, записывается
    производителем (в "Л Кард") при производстве устройства вместе с его серийным
    номером и не может быть изменен пользователем. Если пользователю нужно
    изменить MAC-адрес устройства, то он должен задать пользовательский
    MAC-адрес с помощью E502_EthConfigGetUserMac() и разрешить его использование
    через E502_EthConfigSetUserMACEnabled(). При этом всегда есть возможность
    снова вернуться к использованию оригинального заводского MAC-адреса.


    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] mac      Заводской MAC-адрес устройства в виде массива из
                         #X502_MAC_ADDR_SIZE байт в порядке записи адреса
    @return              Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetFactoryMac(t_e502_eth_config_hnd cfg, uint8_t *mac);


/***************************************************************************//**
    @brief Получение установленного имени экземпляра устройства

    Функция возвращает заданное пользователем имя экземпляра устройства. Данное
    имя может использоваться для обнаружения устройства в сети. Если не задано,
    то используется имя, образованное названием устройства и его серийным номером.
    Данное имя должно быть уникально в пределах сети.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[out] name     Оканчивающаяся нулем строка с заданным именем экземпляра устройства в формате
                         UTF-8. Массив должен быть рассчитан на #X502_INSTANCE_NAME_SIZE
                         байт данных.
    @return              Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigGetInstanceName(t_e502_eth_config_hnd cfg, char *name);
/***************************************************************************//**
    @brief Установка имени экземпляра устройства

    Функция устанавливает имя экземпляра устройства, которое  может использоваться
    для обнаружения устройства локальной в сети.

    @param[in]  cfg      Описатель конфигурации сетевого интерфейса.
    @param[in]  name     Оканчивающаяся нулем строка с заданным именем экземпляра устройства в формате
                         UTF-8. Максимальный размер массива (включая завершающий ноль)
                         составляет #X502_INSTANCE_NAME_SIZE байт данных.
    @return              Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetInstanceName(t_e502_eth_config_hnd cfg, const char *name);


/***************************************************************************//**
    @brief Установка нового пароля для смены конфигурации

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

    При этом значение при сохранении конфигурации с установленным новым паролем
    необходимо для успешной смены конфигурации в E502_EthConfigWrite() передать
    значение пароля, которое было установлено до этого. Если функция завершится
    успешно, то для последующего изменения конфигурации в E502_EthConfigWrite()
    нужно будет передавать уже новое установленное значение пароля.

    @param[in]  cfg         Описатель конфигурации сетевого интерфейса.
    @param[in]  new_passwd  Оканчивающаяся нулем строка, содержащая новое значение
                         пароля для смены конфигурации сетевого интерфейса.
                         Максимальный размер массива (включая завершающий ноль)
                         составляет #X502_PASSWORD_SIZE байт данных.
    @return              Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthConfigSetNewPassword(t_e502_eth_config_hnd cfg, const char *new_passwd);


/** @} */


/***************************************************************************//**
    @addtogroup func_misc
    @{
*******************************************************************************/


/***************************************************************************//**
    @brief Перевод модуля E-502 в режим загрузчика

    Функция переводит устройство в режим загрузчика для возможности обновления
    прошивки контроллера Cortex-M4 модуля E-502 с помощью утилиты lboot.

    В зависимости от используемого текущего интерфейса для соединения с модулем,
    модуль переводится в режим загрузки прошивки по интерфейсу USB (если соединение
    было по USB) или по TFTP (если соединение было по интерфейсу Ethernet).

    При успешном вызове данной функции дальнейшая работа с текущем соединением невозможна,
    т.е. единственным допустимым следующим вызовом является X502_Close().

    При переходе в загрузчик находится в режиме загрузчика порядка 30с после чего,
    если не поступало запросов на перепрошивку загрузчик возвращает управление штатной прошивке.
    Пока модуль находится в режиме загрузчика с ним невозможно установить соединение
    с помощью функций данной библиотеки.


    @param[in] hnd     Описатель устройства.
    @return              Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_SwitchToBootloader(t_x502_hnd hnd);

/***************************************************************************//**
    @brief Перезагрузка прошивки ПЛИС

    По данной команде контроллер Cortex-M4 модуля E-502 выполняет сброс ПЛИС
    и загрузку прошивки ПЛИС из внутренней Flash-памяти.

    Это сервисная функция, которая используется главным образом для обновления
    прошивки ПЛИС.

    @param[in] hnd     Описатель устройства.
    @return            Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_ReloadFPGA(t_x502_hnd hnd);



/***************************************************************************//**
    @brief Передача управляющей команды контроллеру Cortex-M4.

    Функция предназначена для передачи пользовательских управляющих команд
    контроллеру для случая модифицированной прошивки Cortex-M4.


    @param[in] hnd           Описатель модуля.
    @param[in] cmd_code      Код команды - определяет, что за команда выполняется.
    @param[in] par           Параметр, передаваемый с командой (значение зависит
                             от кода команды).
    @param[in] snd_data      Опциональные данные, передаваемые вместе с командой.
                             Если данные не передаются, то должен передаваться
                             нулевой указатель и snd_size = 0.
    @param[in] snd_size      Количество байт, передаваемых в snd_data
    @param[out] rcv_data     Массив, в который будут переданы данные, возвращенные
                             процессором по завершению команды. Если данные не
                             должны возвращаться, то должен передаваться нулевой
                             указатель, а rcv_size = 0.
    @param[in] rcv_size      Количество байт, которое ожидается, что
                             вернет контроллер по выполнению команды. Массив
                             rcv_data должен быть рассчитан на данное количество
                             слов.
    @param[in] tout          Таймаут в течении которого будет ожидаться, когда
                             контроллер завершит выполнение команды. Функция
                             возвратит управление либо по завершению команды,
                             либо по таймауту.
    @param[out] recvd_size   Если не является нулевым указателем, то в эту
                             переменную будет сохранено количество байт,
                             которое реально вернул контроллер после выполнения
                             команды (контроллер имеет право вернуть меньше данных,
                             чем запрашивалось в rcv_size). Если указатель нулевой,
                             то возвращаение меньшего количества данных считается
                             ошибкой.
    @return                  Код ошибки.
*******************************************************************************/
X502_EXPORT(int32_t) E502_CortexExecCmd(t_x502_hnd hnd, uint32_t cmd_code, uint32_t par,
                                        const uint8_t* snd_data, uint32_t snd_size,
                                        uint8_t* rcv_data, uint32_t rcv_size,
                                        uint32_t tout, uint32_t* recvd_size);


/** @} */



/***************************************************************************//**
    @addtogroup func_eth_svc_browse Функции для поиска модулей в локальной сети
    @{
*******************************************************************************/

/***************************************************************************//**
   @brief Начало сеанса поиска модулей в локальной сети

   При вызове данной функции запускается процесс поиска сервисов, соответствующих
   модулям E-502, в локальной сети и создается контекст текущего сеанса поиска.
   Этот контекст используется для дальнейших вызовов E502_EthSvcBrowseGetEvent().
   После завершения поиска должна быть вызвана функция E502_EthSvcBrowseStop().
   Для запуска сеанса необходима запущенная служба (демон) обнаружения ---
   поддерживаются Bonjour для ОС Windows и Avahi для ОС Linux.
   @param[out]   pcontext     Указатель, в который при успешном выполнении
                              сохраняется контекст сеанса поиска устройств.
   @param[in]    flags        Флаги (резерв). Должен всегда передаваться 0.
   @return                    Код ошибки.
 ******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcBrowseStart(t_e502_eth_svc_browse_hnd *pcontext,
                                            uint32_t flags);

/***************************************************************************//**
   @brief Получение информации о изменении присутствия модулей в локальной сети

   Данная функция позволяет как получить список присутствующих модулей
   (сетевых сервисов) в локальной сети, так и отслеживать
   в дальнейшем изменение их состояния.

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

   После начала поиска с помощью E502_EthSvcBrowseStart() контекст не содержит
   информации о наличие сетевых сервисов. Если уже есть подключенные в локальной сети
   модули E-502, то информация о них будет возвращена в следующих
   E502_EthSvcBrowseGetEvent() с событием #E502_ETH_SVC_EVENT_ADD, за
   каждый вызов по одному устройству.

   Если за заданный таймаут не произошло ни одного изменения, то функция
   завершится успешно по окончанию таймаута и вернет событие #E502_ETH_SVC_EVENT_NONE.

   При желании можно продолжать вызвать данную функцию для непрерывного отслеживания
   состояния подключения модулей.

   @param[in]   context     Описатель контекста поиска, созданный при вызове
                            E502_EthSvcBrowseStart().
   @param[out]  svc         Если возвращенное событие не равно #E502_ETH_SVC_EVENT_NONE,
                            то в данной переменной сохраняется созданный описатель
                            сетевого сервиса, соответствующего указанному событию. Этот
                            описатель должен быть всегда уничтожен вручную
                            с помощью E502_EthSvcRecordFree().
   @param[out]  event       В данную переменную сохраняется код события (один из
                            #t_e502_eth_svc_event). Если за указанное время не
                            произошло ни одного события, то возвращается код
                            #E502_ETH_SVC_EVENT_NONE.
   @param[out]  flags       В данной переменной сохраняются дополнительные коды
                            флагов (резерв). Может быть передан нулевой указатель,
                            если значение флагов не интересует.
   @param[in]   tout        Таймаут (в мс) на время ожидания события
   @return                  Код ошибки.
 ******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcBrowseGetEvent(t_e502_eth_svc_browse_hnd context,
                                                t_e502_eth_svc_record_hnd *svc ,
                                                uint32_t *event, uint32_t *flags,
                                                uint32_t tout);

/***************************************************************************//**
   @brief Останов сеанса поиска модулей в локальной сети

   При вызове данной функции процесс поиска сетевых сервисов, соответствующий
   указанному контексту, останавливается. Все ресурсы, выделенные на этапе
   E502_EthSvcBrowseStart() освобождаются. Контекст с этого момента становится
   недействительным.
   Вызову E502_EthSvcBrowseStart() всегда должен соответствовать последующий
   вызов E502_EthSvcBrowseStop() для корректного освобождения ресурсов.

   @param[in]   context     Описатель контекста поиска, созданный при вызове
                            E502_EthSvcBrowseStart().
   @return                  Код ошибки.
 ******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcBrowseStop(t_e502_eth_svc_browse_hnd context);



/***************************************************************************//**
    @brief Освобождение описателя сетевого сервиса

    Освобождение памяти, выделенной под описатель сетевого сервиса при вызове
    E502_EthSvcBrowseGetEvent().

    @param[in] svc     Описатель сетевого сервиса
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcRecordFree(t_e502_eth_svc_record_hnd svc);

/***************************************************************************//**
    @brief Получить имя экземпляра по описателю сервиса

    Функция возвращает имя экземпляра сервиса. Это имя соответствует имени,
    которое установлено в сетевых настройках модуля, соответствующего указанному
    сервису, с помощью E502_EthConfigSetInstanceName().
    Следует отметить, что данное имя, в отличие от остальных строк, представлено
    в кодировке UTF-8, которая совпадает с обычной ASCII строкой только для
    символов английского алфавита.
    Функция не выполняет запросов к самому модулю.

    @param[in] svc     Описатель сетевого сервиса
    @param[out] name   Массив на #X502_INSTANCE_NAME_SIZE байт, в который будет
                       сохранено название экземпляра
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcRecordGetInstanceName(t_e502_eth_svc_record_hnd svc, char *name);

/***************************************************************************//**
    @brief Получить серийный номер модуля по описателю сетевого сервиса

    Функция возвращает серийный номер модуля E-502, соответствующего сетевому
    сервису, на который указывает переданный описатель.
    Функция не выполняет запросов к самому модулю.

    @param[in] svc     Описатель сетевого сервиса
    @param[out] serial Массив на #X502_SERIAL_SIZE байт, в который будет
                       сохранен серийный номер
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcRecordGetDevSerial(t_e502_eth_svc_record_hnd svc, char *serial);


/***************************************************************************//**
    @brief Получить IP адрес сетевого сервиса

    Функция получает IP-адрес модуля E-502, соответствующего сетевому
    сервису, на который указывает переданный описатель. Функция при необходимости
    может выполнять запросы к самому модулю для получения этого адреса, если
    информации о адресе нет в кеше.

    @param[in] svc     Описатель сетевого сервиса
    @param[out] addr   IP-адрес модуля в виде 32-битного слова (аналогично
                       параметру ip_addr функции E502_OpenByIpAddr())
    @param[in] tout    Время ожидания ответа от модуля в случае необходимости
                       выполнить запрос для установления адреса.
    @return            Код ошибки
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcRecordResolveIPv4Addr(t_e502_eth_svc_record_hnd svc,
                                                      uint32_t *addr, uint32_t tout);


/***************************************************************************//**
    @brief Проверка, указывают ли оба описателя на один экземпляр сервиса

    Функция проверяет, указывают ли оба описателя сервисов на один и тот же
    экземпляр. Если приложение сохраняет список описателей сервисов при их
    обнаружении, то данная функция может использоваться, например, при событиях
    #E502_ETH_SVC_EVENT_REMOVE или #E502_ETH_SVC_EVENT_CHANGED, чтобы понять,
    какой записи в сохраненном списке соответствует событие (т.е. функция
    E502_EthSvcBrowseGetEvent() вернет новый описатель, но указывающий на тот
    же экземпляр, что и при событии #E502_ETH_SVC_EVENT_ADD)

    @param[in] svc1    Первый описатель сетевого сервиса для сравнения
    @param[in] svc2    Второй описатель сетевого сервиса для сравнения
    @return            Код ошибки. Возвращает #X502_ERR_OK, если оба описателя
                       указывают на один экземпляр.
*******************************************************************************/
X502_EXPORT(int32_t) E502_EthSvcRecordIsSameInstance(t_e502_eth_svc_record_hnd svc1,
                                                     t_e502_eth_svc_record_hnd svc2);

/** @} */
#ifdef __cplusplus
}
#endif

#endif // E502API_H
