#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 Описатель конфигурации сетевого интерфейса.

    Непрозрачный указатель на структуру, содержащую параметры конфигурации
    сетевого интерфейса модуля E502.
    Пользовательской программе не доступны поля структуры напрямую, а только
    через функции библиотеки.
    Описатель конфигурации создается с помощью 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 Описатель сетевого сервиса

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

/** @} */

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

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

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

    Функция на данный момент не поддерживает флаг #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 Открытие модуля E502, подключенного по USB, по его серийному номеру.

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

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

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

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

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


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

    Функция устанавливает связь с модулем E502, подключенным по интерфейсу 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 модули E502 и инициализирует
    записи о каждом найденном устройстве и сохраняет их в переданный список
    (если не нулевой).
    Возвращенные в списке записи должны быть очищены после использования
    с помощью 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   Если не нулевой указатель, то в данную переменную сохраняется
                      общее число найденных модулей E502, подключенных по
                      интерфейсу 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-порт управляющего соединения модуля
    E502. Это может быть необходимо, если модуль E502  и хост, с которого
    необходимо установить соединение, находятся в разных сетях и адрес модуля
    E502 не доступен из сети хоста. В этом случае требуется настройка проброса
    портов на маршрутизаторе и при наличие более одного такого модуля E502, т.к.
    все соединения идут с маршрутизитором, то различить эти модули можно только
    по 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, соответствующему сетевому сервису, на который указывает переданный
    описатель сетевого сервиса. Этот описатель может быть получен с помощью
    функций поиска сетевых сервисов, соответствующих модулям E502, в локальной сети.
    Данная функция только создает запись, но не проверяет наличие соответствующего
    устройства. Подключение к модулю выполняется аналогично другим
    записям через 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 Перевод модуля E502 в режим загрузчика

    Функция переводит устройство в режим загрузчика для возможности обновления
    прошивки контроллера Cortex-M4 модуля E502 с помощью утилиты 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 модуля E502 выполняет сброс ПЛИС
    и загрузку прошивки ПЛИС из внутренней 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 Начало сеанса поиска модулей в локальной сети

   При вызове данной функции запускается процесс поиска сервисов, соответствующих
   модулям E502, в локальной сети и создается контекст текущего сеанса поиска.
   Этот контекст используется для дальнейших вызовов 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() контекст не содержит
   информации о наличие сетевых сервисов. Если уже есть подключенные в локальной сети
   модули E502, то информация о них будет возвращена в следующих
   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 Получить серийный номер модуля по описателю сетевого сервиса

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

    @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-адрес модуля E502, соответствующего сетевому
    сервису, на который указывает переданный описатель. Функция при необходимости
    может выполнять запросы к самому модулю для получения этого адреса, если
    информации о адресе нет в кеше.

    @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
