/*
 * Copyright (c) 2022, Shenzhen CVA Innovation CO.,LTD
 * All rights reserved.
 *
 * Shenzhen CVA Innovation CO.,LTD (CVA chip) is supplying this file for use
 * exclusively with CVA's microcontroller products. This file can be freely
 * distributed within development tools that are supporting such microcontroller
 * products.
 *
 * THIS SOFTWARE IS PROVIDED "AS IS".  NO WARRANTIES, WHETHER EXPRESS, IMPLIED
 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
 * CVA SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL,
 * OR CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
 */

/*******************************************************************************
 * the includes
 ******************************************************************************/

#include "uds_user.h"
#include "bootloader_cfg.h"
/*******************************************************************************
 * the defines
 ******************************************************************************/

/*******************************************************************************
 * the typedefs
 ******************************************************************************/

/*! \brief The Data-by-ID definition of UDS
 */
typedef struct _Uds_DidBuffer_
{
    uint8_t buffer_F186[1];
    uint8_t buffer_F187[8];//ecu name
    uint8_t buffer_F180[8];//boot version
    uint8_t buffer_F191[24];//buildtime
    uint8_t buffer_F193[4];//hw version
    uint8_t buffer_F195[8];//sw version
} Uds_DidBuffer;

/*******************************************************************************
 * the globals
 ******************************************************************************/

Uds_DidBuffer udsDidBuf;

/*******************************************************************************
 * the constants
 ******************************************************************************/

static const Uds_ServiceType udsServiceTable[UDS_SERVICE_NUM] = {
    {0x10, 2, true,  UdsService10_SessionControl       },
    {0x11, 2, true,  UdsService11_ResetEcu             },
    {0x27, 2, true,  UdsService27_SecurityAccess       },
    {0x28, 3, true,  UdsService28_CommunicationControl },
    {0x3E, 2, true,  UdsService3E_TesterPresent        },
    {0x85, 2, true,  UdsService85_ControlDtcSetting    },
    {0x22, 3, false, UdsService22_ReadDataByIdentifier },
    {0x2E, 4, false, UdsService2E_WriteDataByIdentifier},
    {0x14, 4, false, UdsService14_ClearDiagInfo        },
    {0x19, 3, true,  UdsService19_ReadDtcInformation   },
    {0x2F, 3, false, UdsService2F_InputOutputCtrlById  },
    {0x31, 4, true,  UdsService31_RoutineControl       },
    {0x34, 5, false, UdsService34_RequestDownload      },
    {0x36, 2, false, UdsService36_TransferData         },
    {0x37, 1, false, UdsService37_RequestTransferExit  },
};

static const bool udsSecurityTable[UDS_SERVICE_NUM][UDS_SA_LEVEL_NUM] = {
    {false, false, false}, /* 0x10 */
    {false, false, false}, /* 0x11 */
    {false, false, false}, /* 0x27 */
    {false, false, false}, /* 0x28 */
    {false, false, false}, /* 0x3E */
    {false, false, false}, /* 0x85 */
    {false, false, false}, /* 0x22 */
    {false, false, false}, /* 0x2E */
    {false, false, false}, /* 0x14 */
    {false, false, false}, /* 0x19 */
    {false, false, false}, /* 0x2F */
    {false, false, false}, /* 0x31 */
    {false, false, false}, /* 0x34 */
    {false, false, false}, /* 0x36 */
    {false, false, false}, /* 0x37 */
};

Uds_DidType udsDidTable[] = {
    {0xF186, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F186, BYTES_OF(udsDidBuf.buffer_F186),DID_F186_func},
    {0xF187, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F187, BYTES_OF(udsDidBuf.buffer_F187),DID_F187_func},
    {0xF180, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F180, BYTES_OF(udsDidBuf.buffer_F180),DID_F180_func},
    {0xF191, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F191, BYTES_OF(udsDidBuf.buffer_F191),DID_F191_func},
    {0xF193, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F193, BYTES_OF(udsDidBuf.buffer_F193),DID_F193_func},
    {0xF195, UDS_DID_TYPE_RAM_RW, UDS_SESSION_DEFAULT,  UDS_SA_NONE,     udsDidBuf.buffer_F195, BYTES_OF(udsDidBuf.buffer_F195),DID_F195_func},
};

/*******************************************************************************
 * the functions
 ******************************************************************************/

void Uds_UserInit(UdsType *obj, const Uds_ParamsType *pParams)
{
    Uds_Init(obj, pParams);

    obj->seviceTable   = udsServiceTable;
    obj->securityTable = &udsSecurityTable[0][0];
    obj->serviceNum    = UDS_SERVICE_NUM;
    obj->didTable      = udsDidTable;
    obj->didNum        = sizeof(udsDidTable) / sizeof(Uds_DidType);
}

/******************************DID FUNC****************************************/
void DID_F180_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    Bootloade_CfgInfoType * PBootInfo;
    PBootInfo = (Bootloade_CfgInfoType *)0x0000400;
    memcpy(dataBuf, &(PBootInfo->BLVersion), dataLen);
}
void DID_F186_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    dataBuf[0] = obj->session;
}
void DID_F187_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    Bootloade_CfgInfoType * PBootInfo;
    PBootInfo = (Bootloade_CfgInfoType *)0x0000400;
    memcpy(dataBuf, &(PBootInfo->ECUName), dataLen);
}
void DID_F191_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    Bootloade_CfgInfoType * PBootInfo;
    PBootInfo = (Bootloade_CfgInfoType *)0x0000400;
    //memcpy(dataBuf, &(PBootInfo->HWVersion), dataLen);
    memcpy(dataBuf, &(PBootInfo->bootBuildDate), 12);
    memcpy(dataBuf + 12,  &(PBootInfo->bootBuildTime), 8);
    dataBuf[11] = ' ';
}
void DID_F193_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    Bootloade_CfgInfoType * PBootInfo;
    PBootInfo = (Bootloade_CfgInfoType *)0x0000400;
    memcpy(dataBuf, &(PBootInfo->HWVersion), dataLen);
}
void DID_F195_func(UdsType *obj,uint8_t dataBuf[], uint8_t dataLen)
{
    for (uint8_t i = 0; i < dataLen; i++)
    {
        dataBuf[i] = 0x20;//TODO
    }
    
}