// +FHDR------------------------------------------------------------
//                 Copyright (c) 2022 SmartLogic.
//                       ALL RIGHTS RESERVED
// -----------------------------------------------------------------
// Filename      : test.c
// Author        : xianfeng.du
// Created On    : 2022-11-25
// Last Modified :
// -----------------------------------------------------------------
// Description:
//
//
// -FHDR------------------------------------------------------------

#include <stddef.h>
#include <string.h>
#include <sys/time.h>
#include <unistd.h>

#include "typedef.h"
#include "msg_transfer_layer.h"
#include "ucp_handshake.h"
#include "typedef.h"
#include "ucp_printf.h"
#include "msg_transfer_mem.h"
#include "pet_sm_mgt.h"
#include "ucp_handshake.h"
#include "ospShell.h"
#include "ospLog.h"
#include "ospDump.h"

#define SPU_OAM_BASE_DELAY_SET_REQ     0x200  // 0x200
#define SPU_OAM_BASE_DELAY_SET_RSP     0x201
#define SPU_OAM_BASE_DELAY_QRY_REQ     0x202
#define SPU_OAM_BASE_DELAY_QRY_RSP     0x203
#define SPU_OAM_FIBER_DELAY_QRY_REQ    0x204
#define SPU_OAM_FIBER_DELAY_QRY_RSP    0x205
#define MSG_TRANSFER_OAM_MSG_TYPE      0x125

extern uint8_t guc_oam;

typedef struct tOamMsgTransferHeader {
	uint8_t numMsg;
	uint8_t cellIndex;
	uint16_t rsv;
	uint32_t msgType;
	uint32_t msgLen;
	uint32_t msgData[0];
} OamMsgTransferHeader_t;

typedef struct tSpuOamBaseDelaySetReq {
	uint8_t  u8fiber_port;
    uint8_t  u8rsv[3];
	uint32_t u32dl_frame_offset;
	uint32_t u32ul_frame_offset;
} SpuOamBaseDelaySetReq_t;

typedef struct tSpuOamBaseDelaySetRsp {
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
} SpuOamBaseDelaySetRsp_t;

typedef struct tSpuOamBaseDelayQryReq {
	uint8_t  u8fiber_port;
    uint8_t  u8rsv[3];
} SpuOamBaseDelayQryReq_t;

typedef struct tSpuOamBaseDelayQryRsp {
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
	uint32_t u32dl_frame_offset;
	uint32_t u32ul_frame_offset;
} SpuOamBaseDelayQryRsp_t;

typedef struct tSpuOamFiberDelayQryReq {
	uint8_t  u8fiber_port;
    uint8_t  u8rsv[3];
} SpuOamFiberDelayQryReq_t;

typedef struct tSpuOamFiberDelayQryRsp {
	uint8_t  u8fiber_port;
    uint8_t  u8result;
    uint8_t  u8rsv[2];
	uint32_t u32t14_val;
} SpuOamFiberDelayQryRsp_t;

uint32_t rx_callback_oam_spu(const char* buf,uint32_t payloadSize)
{
    OamMsgTransferHeader_t *header_ptr = NULL;
    SpuOamBaseDelaySetRsp_t  *oam_base_delay_set_rsp_ptr     = NULL;
    SpuOamBaseDelayQryRsp_t  *oam_base_delay_qry_rsp_ptr     = NULL;
    SpuOamFiberDelayQryRsp_t *oam_fiber_delay_qry_rsp_ptr    = NULL;
    
    header_ptr         = (OamMsgTransferHeader_t *)buf;
    header_ptr->msgLen = payloadSize;

    //UCP_PRINT_ERROR("rx_callback_oam_spu msgType: 0x%x payloadSize:%d buf:%p\n", header_ptr->msgType, payloadSize, buf);

    switch(header_ptr->msgType)
    {
        case MSG_TRANSFER_LOG_MSG_TYPE:
            rx_callback_oam(buf, payloadSize);
            break;
        case SPU_OAM_BASE_DELAY_SET_RSP:
            oam_base_delay_set_rsp_ptr = (SpuOamBaseDelaySetRsp_t  *)(buf+sizeof(OamMsgTransferHeader_t));
            UCP_PRINT_SHELL("cellIndex:%d u8result:%u u8fiber_port:%u\n", \
                             header_ptr->cellIndex,\
                             oam_base_delay_set_rsp_ptr->u8result, \
                             oam_base_delay_set_rsp_ptr->u8fiber_port);
            //memset((void *)buf, 0, payloadSize);
            break;
        case SPU_OAM_BASE_DELAY_QRY_RSP:
            oam_base_delay_qry_rsp_ptr = (SpuOamBaseDelayQryRsp_t  *)(buf+sizeof(OamMsgTransferHeader_t));
            UCP_PRINT_SHELL("u8fiber_port:%u u8result:%u u32dl_frame_offset:0x%x u32ul_frame_offset:0x%x\n", \
                           oam_base_delay_qry_rsp_ptr->u8fiber_port, oam_base_delay_qry_rsp_ptr->u8result, \
                           oam_base_delay_qry_rsp_ptr->u32dl_frame_offset, oam_base_delay_qry_rsp_ptr->u32ul_frame_offset);
            //memset((void *)buf, 0, payloadSize);
            break;
        case SPU_OAM_FIBER_DELAY_QRY_RSP:
            oam_fiber_delay_qry_rsp_ptr = (SpuOamFiberDelayQryRsp_t *)(buf+sizeof(OamMsgTransferHeader_t));
            UCP_PRINT_SHELL("u8fiber_port:%u u8result:%u u8rsv[0]:%d u8rsv[1]:%d u32t14_val:0x%x\n", \
                   oam_fiber_delay_qry_rsp_ptr->u8fiber_port, oam_fiber_delay_qry_rsp_ptr->u8result, \
                   oam_fiber_delay_qry_rsp_ptr->u8rsv[0], oam_fiber_delay_qry_rsp_ptr->u8rsv[1], oam_fiber_delay_qry_rsp_ptr->u32t14_val);
            //memset((void *)buf, 0, payloadSize);
            break;
    }
    
    return payloadSize;
}

static inline void get_msg_transfer_info(uint16_t port_index, uint16_t inst_id, uint16_t transfer_type, transfer_type_info_s* transfer_type_info_ptr)
{
    queue_info_s c_plane,u_plane;

    switch (transfer_type) {
        case CU_SPLIT:
            c_plane.rx_block_size = 0x25800;
            c_plane.rx_block_num = 32;
            c_plane.rx_callback = NULL;
            c_plane.tx_block_size = 0x8000;
            c_plane.tx_block_num = 8;
            c_plane.tx_callback = NULL;

            u_plane.rx_block_size = 0x28000;
            u_plane.rx_block_num = 8;
            //u_plane.rx_callback = rx_callback_data;
            if (0 == inst_id)
            {
                u_plane.rx_callback = NULL;
            }
            else
            {
                u_plane.rx_callback = NULL;
            }
            u_plane.tx_block_size = 0x28000;
            u_plane.tx_block_num = 8;
            u_plane.tx_callback = NULL;

            transfer_type_info_ptr->queue_cplane_info = c_plane;
            transfer_type_info_ptr->queue_uplane_info = u_plane;
            break;
        case OAM:
            c_plane.rx_block_size = 0x100000;
            c_plane.rx_block_num = 32;
            c_plane.rx_callback = rx_callback_oam_spu;
            //c_plane.rx_callback = rx_callback_oam;
            c_plane.tx_block_size = 0x8000;
            c_plane.tx_block_num = 8;
            c_plane.tx_callback = NULL;

            transfer_type_info_ptr->queue_cplane_info = c_plane;
            break;
        default:
            UCP_PRINT_ERROR("get_msg_queue_cfg doesn't support transfer_type[%d] .",transfer_type);
            break;
    }

    return;
}

static inline void msg_transfer_cfg(void)
{
    uint8_t port_id = 0;
    uint16_t inst_id = 0;
    uint16_t transfer_type = 0;
    int32_t handle_id = 0;
    transfer_type_info_s transfer_type_info;

    for (inst_id=0; inst_id<MAX_INSTANCE_NUM; inst_id++) {
        /*********************************transfer_type = CU_SPLIT**********************************/
        transfer_type = CU_SPLIT;
        get_msg_transfer_info(port_id,inst_id,transfer_type, &transfer_type_info);
        handle_id = msg_transfer_init(port_id, transfer_type, inst_id, &transfer_type_info);
        if (handle_id < 0) {
            UCP_PRINT_ERROR("phy_cfg_init transfer_type:CU_SPLIT, handle_id[0x%08x] error.",handle_id);
        }

        /*********************************transfer_type = OAM**********************************/
        transfer_type = OAM;
        get_msg_transfer_info(port_id,inst_id,transfer_type, &transfer_type_info);
        handle_id = msg_transfer_init(port_id, transfer_type, inst_id, &transfer_type_info);
        if (handle_id < 0) {
            UCP_PRINT_ERROR("phy_cfg_init transfer_type:OAM, handle_id[0x%08x] error.",handle_id);
        }
    }

        PetSmLocalMgt_t* pPetSmLocalMgt = get_pet_sm_local_mgt();
    //EcsSmLocalMgt_t* pEcsSmLocalMgt = get_ecs_sm_local_mgt();
    MsgQueueLocalMgt_t* pMsgQueueLocalMgt = get_msg_queue_local_mgt();
    pPetSmLocalMgt ->pSyncInfo->queueCfgFlag = ++pMsgQueueLocalMgt->localSyncInfo.queueCfgFlag;

    return;
}

static inline void msg_transfer_queue_polling(void)
{
    uint8_t port_id = 0;
    HandleId_t handler;
    uint16_t cu_flag;
    uint32_t offset = 0;
    uint32_t len = 0;
    uint8_t* msg_ptr;

    for (uint32_t i = 0; i < MAX_INSTANCE_NUM; i++) {
        handler.port_id = port_id;
        handler.inst_id = i;
        handler.type_id = CU_SPLIT;
        cu_flag = C_PLANE;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);

        cu_flag = U_PLANE;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);

        handler.type_id = OAM;
        msg_transfer_receive(handler.value, cu_flag, offset, len, &msg_ptr);
    }

    return;
}

void oam_msg_base_delay_set_test()
{
    uint32_t size = 24;
    char* buf;
    uint32_t availableSize,offset;
    OamMsgTransferHeader_t stOamMsg;
    SpuOamBaseDelaySetReq_t  stOamDelayReq;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = OAM;

    int32_t ret = msg_transfer_send_start(handler.value, cu_flag);

    /************C_PLANE***************/
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("oam_msg_test call msg_transfer_alloc_msg err.");
        return ;
    }


    stOamMsg.cellIndex = 0;
    stOamMsg.numMsg    = 1;
    stOamMsg.msgType   = SPU_OAM_BASE_DELAY_SET_REQ;
    stOamMsg.msgLen    = size;

    stOamDelayReq.u8fiber_port = 2;
    stOamDelayReq.u32dl_frame_offset = 0xab;
    stOamDelayReq.u32ul_frame_offset = 0xcd;

    //memset(buf, 0, size);
    //memcpy((uint8_t *)stOamMsg.msgData, (uint8_t *)&stOamDelayReq, sizeof(SpuOamBaseDelaySetReq_t));
    memcpy(buf, (uint8_t *)&stOamMsg, sizeof(OamMsgTransferHeader_t));
    memcpy((uint8_t *)(buf+sizeof(OamMsgTransferHeader_t)), (uint8_t *)&stOamDelayReq, sizeof(SpuOamBaseDelaySetReq_t));

    ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("msg_transfer_send_msg send error\r\n");
    }
    msg_transfer_send_end(handler.value,cu_flag);
    
    printf("\n-----------------------------------------------------------\n");
    for (int i = 0; i < size;i++)
    {
        printf("%02x  ", buf[i]);
    
        if ((i & 0x7) == 0x7)
        {
            printf("\n");
        }
    }

    return;
}

void oam_msg_base_delay_qry_test()
{
    uint32_t size = sizeof(OamMsgTransferHeader_t)+sizeof(SpuOamBaseDelayQryReq_t);
    char* buf;
    uint32_t availableSize,offset;
    OamMsgTransferHeader_t stOamMsg;
    SpuOamBaseDelayQryReq_t  stOamBaseDelayReq;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = OAM;

    int32_t ret = msg_transfer_send_start(handler.value, cu_flag);

    /************C_PLANE***************/
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("oam_msg_test call msg_transfer_alloc_msg err.");
        return ;
    }

    stOamMsg.cellIndex = 0;
    stOamMsg.numMsg    = 1;
    stOamMsg.msgType   = SPU_OAM_BASE_DELAY_QRY_REQ;
    stOamMsg.msgLen    = size;

    stOamBaseDelayReq.u8fiber_port = 3;
    stOamBaseDelayReq.u8rsv[0] = 0;
    stOamBaseDelayReq.u8rsv[1] = 0;
    stOamBaseDelayReq.u8rsv[2] = 0;

    //memcpy((uint8_t *)stOamMsg.msgData, (uint8_t *)&stOamBaseDelayReq, sizeof(SpuOamBaseDelayQryReq_t));
    memcpy(buf, (uint8_t *)&stOamMsg, size);
    memcpy((uint8_t *)(buf+sizeof(OamMsgTransferHeader_t)), (uint8_t *)&stOamBaseDelayReq, sizeof(SpuOamBaseDelayQryReq_t));

    ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("msg_transfer_send_msg send error\r\n");
    }
    
    msg_transfer_send_end(handler.value, cu_flag);
    
    printf("\n-----------------------------------------------------------\n");
    for (int i = 0; i < size;i++)
    {
        printf("%02x  ", buf[i]);
    
        if ((i & 0x7) == 0x7)
        {
            printf("\n");
        }
    }

    return;
}

void oam_msg_fiber_deley_qry_test()
{
    uint32_t size = sizeof(OamMsgTransferHeader_t) + sizeof(SpuOamFiberDelayQryReq_t);
    char* buf;
    uint32_t availableSize,offset;
    OamMsgTransferHeader_t stOamMsg;
    SpuOamFiberDelayQryReq_t stOamFiberDelayQryReq;

    uint16_t cu_flag = C_PLANE;
    HandleId_t handler;
    handler.port_id = 0;
    handler.inst_id = 0;
    handler.type_id = OAM;

    int32_t ret = msg_transfer_send_start(handler.value, cu_flag);

    /************C_PLANE***************/
    ret = msg_transfer_alloc_msg(handler.value, cu_flag, size, &buf, &availableSize, &offset);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("oam_msg_test call msg_transfer_alloc_msg err.");
        return ;
    }

    stOamMsg.cellIndex = 0;
    stOamMsg.numMsg     = 1;
    stOamMsg.msgType   = SPU_OAM_FIBER_DELAY_QRY_REQ;
    stOamMsg.msgLen    = size;

    stOamFiberDelayQryReq.u8fiber_port = 4;
    stOamFiberDelayQryReq.u8rsv[0] = 0;
    stOamFiberDelayQryReq.u8rsv[1] = 0;
    stOamFiberDelayQryReq.u8rsv[2] = 0;

    //memcpy((uint8_t *)stOamMsg.msgData, (uint8_t *)&stOamFiberDelayQryReq, sizeof(SpuOamFiberDelayQryReq_t));
    memcpy(buf, (uint8_t *)&stOamMsg, size);
    memcpy((uint8_t *)(buf+sizeof(OamMsgTransferHeader_t)), (uint8_t *)&stOamFiberDelayQryReq, sizeof(SpuOamFiberDelayQryReq_t));

    ret = msg_transfer_send_msg(handler.value, cu_flag, (uint8_t *)buf, offset, size);
    if ( SUCCESS != ret) {
        UCP_PRINT_ERROR("msg_transfer_send_msg send error\r\n");
    }
    msg_transfer_send_end(handler.value, cu_flag);
    
    printf("\n-----------------------------------------------------------\n");
    for (int i = 0; i < size;i++)
    {
        printf("%02x  ", buf[i]);
    
        if ((i & 0x7) == 0x7)
        {
            printf("\n");
        }
    }

    return;
}


int32_t test_case(uint32_t argc, int32_t* argvp)
{
	UCP_PRINT_DEBUG("start running testcase 4.");

    msg_transfer_mem_init();
    msg_transfer_cfg();
    ucp_handshake();
	
	UCP_PRINT_DEBUG("start transfering message.");

    while(1) 
    {
        switch(guc_oam)
        {
            case 1:
            oam_msg_base_delay_set_test();
            break;
            case 2:
            oam_msg_base_delay_qry_test();
            break;
            case 3:
            oam_msg_fiber_deley_qry_test();
            break;
        }
        guc_oam = 0;
        usleep(500);
        msg_transfer_queue_polling();
    }
    
    return 0;
}

