/***************************************************************************//**
  @addtogroup lip_core
  @{
  @file lip_defs.h
  Файл содержит общие константы (включая все коды ошибок) и типы,
  которые могут быть использованы как приложением, так и модулями lip

  @author Borisov Alexey <borisov@lcard.ru>
 ******************************************************************************/


#ifndef __LIP_H__
#define __LIP_H__

#include <stdint.h>
#include <stdbool.h>
#include <stddef.h>
#include "lip_config.h"


/** Коды ошибок */
typedef enum {
    /** Выполнено без ошибок */
    LIP_ERR_SUCCESS                     =  0,
    LIP_ERR_INIT_PHY_NOTFOUND           = -1,
    LIP_ERR_INIT_PHY_LINKUP_TIMEOUT     = -2,
    LIP_ERR_INIT_PHY_AUTONEG_TIMEOUT    = -3,
    LIP_ERR_INIT_STATE                  = -4,
    LIP_ERR_INIT_PHY_MODE               = -5,
    LIP_ERR_INIT_MAC_RESET              = -8,


    LIP_ERR_TXBUF_TOO_SMALL             = -10,
    LIP_ERR_RXBUF_TOO_SMALL             = -11,
    LIP_ERR_TXBUF_NOT_FOUND             = -12,
    LIP_ERR_BUF_NOT_PREPARED            = -13,
    LIP_ERR_PARAMETERS                  = -14,
    LIP_ERR_RX_PACKET_FORMAT            = -15,
    LIP_ERR_STACK_IN_ERROR_STATE        = -16,
    LIP_ERR_TX_NOT_INIT                 = -17,
    LIP_ERR_INTERNAL_PROCESSING         = -18,
    LIP_ERR_BUF_NOT_RDY                 = -19,

    LIP_ERR_ARP_REC_NOTFOUND            = -20,
    LIP_ERR_ARP_UNSUP_TYPE              = -21,

    LIP_ERR_IP_VERSION                  = -30,
    LIP_ERR_IP_HDR_SIZE                 = -31,
    LIP_ERR_IP_FRAG_NOT_SUPPORT         = -32,
    LIP_ERR_IP_CHECKSUM                 = -33,
    LIP_ERR_IP_UNSUP_TYPE               = -34,
    LIP_ERR_IP_RX_ADDR                  = -35,
    LIP_ERR_IP_SRC_ADDR                 = -36,
    /** Задан неверный IP-адрес для данной операции */
    LIP_ERR_IP_INVALID_ADDR             = -37,
    LIP_ERR_IP_SRC_ADDR_NOT_VALID       = -38,
    LIP_ERR_IP_HOST_UNREACHABLE         = -39,    





    LIP_ERR_ICMP_CHECKSUM               = -60,
    LIP_ERR_ICMP_UNSUP_TYPE             = -61,
    LIP_ERR_ICMP_INSUFFICIENT_SIZE      = -62,

    /** Неверная контрольная сумма в принятом UDP-пакете */
    LIP_ERR_UDP_CHECKSUM                = -70,
    /** Нет места для регистрации новой функций для прослушивания UDP-порта.
        Уже прослушивается максимальное количество портов, которое определяется
        настройкой #LIP_UDP_MAX_DYN_PORTS */
    LIP_ERR_UDP_FREE_PORT_NOT_FOUND     = -71,
    /** Нет зарегистрированной функции для принятого UDP-пакета */
    LIP_ERR_UDP_UNREACHABLE_PORT        = -72,
    /** Для заданного UDP-порта уже зарегистрирована callback-функция */
    LIP_ERR_UDP_PORT_ALREADY_LISTENED   = -73,

    LIP_ERR_TCP_CHECKSUM                = -80, /**< Неверная контрольная сумма в
                                                    принятом TCP-пакете */
    LIP_ERR_TCP_SOCK_INVALID_ID         = -81, /**< Неверный идентификатор сокета */
    LIP_ERR_TCP_SOCK_INVALID_SEQ_NUM    = -82, /**< Неверный номер последовательности
                                                    в принятом пакете (не из окна) */
    LIP_ERR_TCP_SOCK_INVALID_ACK_NUM    = -83, /**< Неверный номер подтверждения
                                                    в принятом пакете */
    LIP_ERR_TCP_SOCK_INVALID_STATE      = -84, /**< Текущее состояние сокета не
                                                    позволяет выполнить заданную операцию */
    LIP_ERR_TCP_SOCK_NO_FREE_DD         = -85, /**< Нет свободного места в очереди заданий
                                                    на обмен для данного сокета */
    LIP_ERR_TCP_SOCK_INVALID_MODE       = -86, /**< Неверный режим передачи данных сокета */
    LIP_ERR_TCP_SOCK_MAX_RETR_CNT       = -87, /**< Превышено максимальное количество
                                                    повторных передач TCP-сегмента */
    LIP_ERR_TCP_SOCK_CLOSED             = -88, /**< Нельзя выполнить операцию, так
                                                    как сокет соответствует закрытому
                                                    соединению */
    LIP_ERR_TCP_SOCK_ABORTED            = -89, /**< Нельзя выполнить операцию,
                                                    так как соединение было
                                                    аварийно разорвано */
    LIP_ERR_TCP_SOCK_UNSUP_OPTION       = -90, /**< Данная опция сокета не
                                                    поддерживается стеком */
    LIP_ERR_TCP_SOCK_INVALID_OPT_LEN    = -91, /**< Неверная длина параметров
                                                    для данной опции сокета */
    LIP_ERR_TCP_SOCK_INVALID_TS         = -92, /**< Неверная метка времени в
                                                    принятом TCP-пакете (PAWS) */
    LIP_ERR_TCP_SOCK_UPDATE_SIZE        = -93, /**< Размер обновления позиции в
                                                    буфере сокета превышает
                                                    максимально возможный */
    LIP_ERR_TCP_SOCK_UNSPEC_REM_HOST    = -94, /**< Не определены параметры удаленного
                                                    хоста для установления соединения */
    LIP_ERR_TCP_SOCK_NO_DD_IN_PROGRESS  = -95, /**< Нет ни одного задания, находящегося в процессе выполнения */
    LIP_ERR_TCP_SOCK_DD_INVALID_SIZE    = -96, /**< Размер задания на прием или передачу превышеает максимальный для настроек стека */


    LIP_ERR_DHCPC_RX_PACKET_SIZE        = -100,
    LIP_ERR_DHCPC_TX_INSUF_SIZE         = -101, /* не хватает места для помещения dhcp-сообщения */
    LIP_ERR_DHCPC_INVALID_STATE         = -102,
    LIP_ERR_DHCPC_INVALID_ADDR          = -103,


    LIP_ERR_TFTP_BLOCK_NUM              = -120, //ошибка в номере блока при передаче данных
    LIP_ERR_TFTP_SRC_TID                = -121, //неверный TID источника в принятом пакете
    LIP_ERR_TFTP_TIMEOUT                = -122,
    LIP_ERR_TFTP_TRANSFER_ABORTED       = -123,
    LIP_ERR_TFTP_NO_FREE_FILE_REQ       = -124, //нет свободной записи, чтобы начать запрос
    LIP_ERR_TFTP_PROTOCOL_ERR           = -125, //ошибка последовательности обмена по TFTP

    LIP_ERR_IGMP_INSUFFICIENT_MEMORY    = -140, //недостаточно памяти для выполнения запроса
    LIP_ERR_IGMP_NONMCAST_ADDR          = -141, //адрес не мультиксатовый
    LIP_ERR_IGMP_CHECKSUM               = -142,
    LIP_ERR_IGMP_SRC_NOT_FOUND          = -143,


    LIP_ERR_ACD_UNSUF_MEMORY            = -150,
    LIP_ERR_ACD_ADDR_IN_USE             = -151,
    LIP_ERR_ACD_ADDR_CONFLICT           = -152,



    /** Имя хоста не установлено. Необходимо вызвать lip_mdns_set_hostname() до
        вызова остальных функций @ref lip_mdns */
    LIP_ERR_MDNS_HOSTNAME_IS_NOT_SET    = -160,
    /** Недостаточно памяти для добавления записи.*/
    LIP_ERR_MDNS_INSUFFICIENT_MEMORY    = -161,
    /** Callback-функция для этого доменного имени уже зарегистрированна */
    LIP_ERR_MDNS_CB_ALREADY_SET         = -162,
    /** Количество ключей в добавляемом сервисе превышает #LIP_DNSSD_SERVICE_MAX_TXT_KEYS */
    LIP_ERR_DNSSD_TOO_MANY_TXT_KEYS     = -170,
    /** Уже зарегестрировано #LIP_DNSSD_SERVICES_CNT сервисов. новый сервис
       не может быть добавлен */
    LIP_ERR_DNSSD_NO_FREE_SERVICES      = -171,

    /** IP-дейтаграмма больше макс. размера, который можем принять */
    LIP_ERR_IP_DATAGRAMME_TOO_LARGE      = -180,
    /** неверный параметр в IP-заголовке */
    LIP_ERR_IP_HDR_PARAMETER             = -181,
    /** принят фрагмент новой IP-дейтаграммы, но нет места для сохранения */
    LIP_ERR_IP_REASSEMBLY_BUF_BUSY       = -182,


    /** Недостаточно свободных TCP-сокетов для выполнения функции */
    LIP_ERR_HTTP_INSUF_SOCKETS           = -200,
    /** Не найдено указанное http-соединение */
    LIP_ERR_HTTP_CONNECTION_NOT_FOUND    = -201,
    /** Недопустимое состояие http-соединения для этой операции */
    LIP_ERR_HTTP_CONNECTION_STATE        = -202,
    /** Неверный указатель на параметры ответа по http */
    LIP_ERR_HTTP_INVALID_RESP_POINTER    = -203,


    LIP_ERR_PTP_INVALID_RX_SIZE          = -220,
    LIP_ERR_PTP_UNSUP_DOMAIN_NUM         = -221,
    LIP_ERR_PTP_UNSUP_PTP_VER            = -222,
    LIP_ERR_PTP_INVALID_PORT             = -223,

    LIP_ERR_PHY_MDIO_NOT_RDY            = -250,
    LIP_ERR_PHY_MDIO_NO_RD_ACK          = -251,
    LIP_ERR_PHY_MDIO_NO_RD_OP           = -252,
    LIP_ERR_PHY_MDIO_OP_TOUT            = -253,
    LIP_ERR_PHY_MDIO_REG_WR_ERR         = -254,
    LIP_ERR_PHY_UNSUP_MODE              = -260,
    LIP_ERR_PHY_NO_ACC_DESCR            = -261,
    LIP_ERR_PHY_FEAT_NOT_SUPPORTED      = -262,
    LIP_ERR_PHY_INVALID_PAIR_NUM        = -263,
    LIP_ERR_PHY_RESET_TIMEOUT           = -264,

    LIP_ERR_DEV_UNSUP_DEVTYPE           = -280, /**< Тип обнаруженного устройства не поддерживается ПО */
    LIP_ERR_DEV_INVALID_PORT            = -281, /**< Неверный номер порта */
    LIP_ERR_DEV_UNSUP_FEATURE           = -282, /**< Запрашиваемая возможность не поддерживается устройством или не раелизована */
    LIP_ERR_DEV_UNSUP_PORT_FEATURE      = -283, /**< Запрашиваемая возможность не поддерживается заданным портом */
    LIP_ERR_DEV_OP_WTRDY_TOUT           = -284, /**< Ошибка ожидания завершения операции, выполняемой устройством */

    /** Пакет должен быть отбрашен по решению пользовательского обработчика */
    LIP_ERR_USER_DROP_REQUEST           = -300,


    LIP_ERR_OPCUA_INVALID_PUBID         = -320,
    LIP_ERR_OPCUA_SUB_MAX_REC           = -321,
    LIP_ERR_OPCUA_SERVER_TREE_FULL      = -322

} t_lip_errs;

typedef enum {
    LIP_PKT_PRIO_BEST_EFFORT      = 0x00,
    LIP_PKT_PRIO_LOW              = 0x10,
    LIP_PKT_PRIO_MEDIUM           = 0x20,
    LIP_PKT_PRIO_HIGH             = 0x40,
    LIP_PKT_PRIO_VHIGH            = 0x80,
    LIP_PKT_PRIO_CRITICAL         = 0xC0,
} t_lip_pkt_priorities;


/** Данное значение, переданное в качестве таймаута, означает что ожидание будет
 *  бесконечное */
#define LIP_INFINITY_TOUT    0xFFFFFFFF



#ifndef lip_printf
    #define lip_printf(module, level, err, ...)
#endif


#ifndef MAX
    #define MAX(a,b) (((a)>(b)) ? (a) : (b))
#endif

#ifndef MIN
    #define MIN(a,b) (((a)<(b)) ? (a) : (b))
#endif


#define LIP_LITTLE_ENDIAN    0
#define LIP_BIG_ENDIAN       1

#ifndef LIP_BYTE_ORDER
    #define LIP_BYTE_ORDER LIP_LITTLE_ENDIAN
#endif

#if LIP_BYTE_ORDER == LIP_BIG_ENDIAN
    #define HTON16(n) (n & 0xFFFF)
    #define HTON32(n) (n & 0xFFFFFFFFUL)
    #define HTON64(n) (n)

    #define LIP_WORD16_MAKE(b0, b1) (((uint16_t)(b0) << 8) | (b1))
    #define LIP_WORD16_B0(w) (((w) & 0xFF00) >> 8)
    #define LIP_WORD16_B1(w) ((w) & 0x00FF)
#else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
    #define HTON16(n) (uint16_t)((((uint16_t) (n) & 0xFF) << 8) \
                               | (((uint16_t) (n) & 0xFF00) >> 8))
    #define HTON32(n) (uint32_t)((((uint32_t) (n) & 0xFFUL) << 24) \
                               | (((uint32_t) (n) & 0xFF00UL) << 8) \
                               | (((uint32_t) (n) & 0xFF0000UL) >> 8) \
                               | (((uint32_t) (n) & 0xFF000000UL) >> 24))
    #define HTON64(n) (uint64_t)((((uint64_t) (n) & 0x00000000000000FFULL) << 56) \
                               | (((uint64_t) (n) & 0x000000000000FF00ULL) << 40) \
                               | (((uint64_t) (n) & 0x0000000000FF0000ULL) << 24) \
                               | (((uint64_t) (n) & 0x00000000FF000000ULL) << 8) \
                               | (((uint64_t) (n) & 0x000000FF00000000ULL) >> 8) \
                               | (((uint64_t) (n) & 0x0000FF0000000000ULL) >> 24) \
                               | (((uint64_t) (n) & 0x00FF000000000000ULL) >> 40) \
                               | (((uint64_t) (n) & 0xFF00000000000000ULL) >> 56))
    #define LIP_WORD16_MAKE(b0, b1) (((uint16_t)(b1) << 8) | (b0))
    #define LIP_WORD16_B0(w) ((w)        & 0x00FFU)
    #define LIP_WORD16_B1(w) (((w) >> 8) & 0x00FFU)

    #define LIP_WORD32_MAKE(b0, b1, b2, b3) (((uint32_t)(b3) << 24) | ((uint32_t)(b2) << 16) | ((uint32_t)(b1) << 8) | (b0))
    #define LIP_WORD32_B0(w) ((w)         & 0x000000FFU)
    #define LIP_WORD32_B1(w) (((w) >> 8)  & 0x000000FFU)
    #define LIP_WORD32_B2(w) (((w) >> 16) & 0x000000FFU)
    #define LIP_WORD32_B3(w) (((w) >> 24) & 0x000000FFU)
#endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */
#define NTOH16(n) HTON16(n)

#if LIP_BYTE_ORDER == LIP_BIG_ENDIAN

#else /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */

#endif /* UIP_BYTE_ORDER == UIP_BIG_ENDIAN */



#define NTOH32(n) HTON32(n)
#define NTOH64(n) HTON64(n)


/* диапазон динамических портов в соответствии с рекомендацией IANA */
#define LIP_DYNAMIC_PORT_FIRST  49152
#define LIP_DYNAMIC_PORT_LAST   65535


typedef uint16_t t_lip_size;
typedef  struct {
    uint8_t    *data;
    t_lip_size  size;
} t_lip_payload;


#endif /* LIP_H_ */
/** @} */
