/******************************************************************************
文 件 名：UDS_ISO14229_Server.c
功能描述：ISO 14229 规范规定的诊断服务服务器端函数库文件
作    者：张暄
版    本：V1.0
日    期：2016.11.1
******************************************************************************/
#include "UDS_ISO14229_Server.h"

UDS_APP_RX_Union      UDS_APP_RX;

extern uint8_t CAN_Current_state;

/******************************************************************************
后台服务
******************************************************************************/
/******************************************************************************
函数名：UDS_Server_Application_Service
功  能：UDS服务器应用层控制服务
参  数：无
返回值：无
*******************************************************************************
注  意：该服务函数必须被实时调用
******************************************************************************/
void UDS_Server_Application_Service ( void )
{
    UDS_Process_Service_Request();
}


/******************************************************************************
会话层下层接口及计时功能实现
******************************************************************************/

/******************************************************************************
函数名：UDS_N_USData_Request
功  能：该服务函数用于请求传输数据
        This service is used to request the transfer of data. If necessary, the
        network layer segments the data.
参  数：N_TAtype    ：目标地址类型,发送数据请使用 DIAG_ID_Tx
        MessageData ：请求传输的数据
        Length      ：数据长度
返回值：无
******************************************************************************/
void UDS_N_USData_Request ( uint32_t N_TAtype, uint8_t *MessageData, uint16_t Length )
{
    DoCAN_N_USData_Request ( N_TAtype, MessageData, Length );

    /*计时*/
}

/******************************************************************************
函数名：UDS_N_USData_Confirm
功  能：该服务函数由网络层发起,用于确认前一次使用N_USData.request服务向
        N_TAtype地址发送的数据是否发送完成
        The N_USData.confirm service is issued by the network layer. The service
        primitive confirms the completion of an N_USData.request service
        identified by the address information in N_TAtype.
参  数：N_TAtype ：N_USData.confirm服务请求的发送地址
        N_Result ：N_USData.request服务的传输状态
返回值：无
******************************************************************************/
extern void UDS_N_USData_Confirm (uint32_t N_TAtype, N_ResultEnum N_Result)
{
    if ( N_Result == N_OK )
    {
        UDS_S_Data_Confirm ( N_TAtype, S_OK );
    }
    else
    {
        UDS_S_Data_Confirm ( N_TAtype, S_NOK );
    }

    /*计时*/
}

/******************************************************************************
函数名：UDS_N_USData_FF_Indication
功  能：该服务函数由网络层发起,用于向上层指示地址为N_TAtype的一组多帧数据的首帧
        的到来
        The N_USData_FF.indication service is issued by the network layer. The
        service primitive indicates to the adjacent upper layer the arrival of
        a FirstFrame (FF) of a segmented message received from a peer protocol
        entity, identified by the address information N_TAtype.
参  数：N_TAtype ：新到的多帧数据首帧的地址信息
        Length   ：新到的多帧数据的总长度
返回值：无
******************************************************************************/
extern void UDS_N_USData_FF_Indication ( uint32_t N_TAtype, uint16_t Length )
{

    /*计时*/
}

/******************************************************************************
函数名：UDS_N_USData_Indication
功  能：该服务函数由网络层发起,用于向上层指出由N_TAtype地址发送来的长度为Length
        的MessageData数据的传送结果N_Result,并同时传递这一数据
        The N_USData.indication service is issued by the network layer. The
        service primitive indicates <N_Result> events and delivers
        <MessageData> with <Length> bytes received from a peer protocol entity
        identified by the address information in N_TAtype to the adjacent upper
        layer.
参  数：N_TAtype    ：接收到的数据地址信息
        MessageData ：接收到的数据      (仅在N_Result为N_OK时有效)
        Length      ：接收到的数据长度  (仅在N_Result为N_OK时有效)
        N_Result    ：数据的接收结果
返回值：无
******************************************************************************/
void UDS_N_USData_Indication(uint32_t N_TAtype, uint8_t *MessageData, uint16_t Length, N_ResultEnum N_Result)
{
    if ( N_Result == N_OK )
    {
        UDS_S_Data_Indication ( N_TAtype, MessageData, Length, S_OK );
    }
    else
    {
        UDS_S_Data_Indication ( N_TAtype, MessageData, Length, S_NOK );
    }

    /*计时*/
}

/******************************************************************************
会话层上层接口
******************************************************************************/

/******************************************************************************
函数名：UDS_S_Data_Request
功  能：该服务用于请求向目标地址S_TAtype发送长度为S_Length的S_Data.
        The service primitive requests transmission of S_Data with S_Length
        number of bytes from the sender to the receiver peer entities
        identified by the address information in S_TAtype.
参  数：S_TAtype ：发送数据的目标地址
        S_Data   ：发送的数据
        S_Length ：数据的长度
返回值：无
******************************************************************************/
void UDS_S_Data_Request ( uint32_t S_TAtype, uint8_t *S_Data, uint16_t S_Length )
{
    UDS_N_USData_Request ( S_TAtype, S_Data, S_Length );
}

/******************************************************************************
函数名：UDS_S_Data_Request
功  能：该服务由会话层发起,用于指出以S_TAtype为目标地址的S_Data.request发送请求
        是否完成
        The S_Data.confirm service is issued by the session layer. The service
        primitive confirms the completion of an S_Data.request service
        identified by the address information in S_TAtype.
参  数：S_TAtype ：发送数据的目标地址
        S_Result ：数据的发送结果
返回值：无
******************************************************************************/
void UDS_S_Data_Confirm ( uint32_t S_TAtype, S_Result_Enum S_Result )
{
    if (S_TAtype == DIAG_ID_Tx)
    {
        if (S_Result == S_NOK)
        {
            UDS_TP_ArTimeOutHandle();
        }
    }
}

/******************************************************************************
函数名：UDS_S_Data_Request
功  能：该服务由会话层发起,用于向上层指出S_Result接收状态以及传递从S_TAtype地址
        接收到的S_Length长度的S_Data数据

        The S_Data.indication service is issued by the session layer. The
        service primitive indicates S_Result events and delivers S_Data with
        S_Length bytes received from a peer protocol entity identified by the
        address information in S_TAtype to the adjacent upper layer.
参  数：S_TAtype ：接收到的数据地址信息
        S_Data   ：接收到的数据      (仅在S_Result为S_OK时有效)
        S_Length ：接收到的数据长度  (仅在S_Result为S_OK时有效)
        S_Result ：数据的接收结果
返回值：无
******************************************************************************/
void UDS_S_Data_Indication ( uint32_t S_TAtype, uint8_t S_Data[], uint16_t S_Length, S_Result_Enum S_Result )
{
    uint16_t i;

    if ( S_Result == S_OK )
    {
        UDS_APP_RX.Data.New     = 1u;
        UDS_APP_RX.Data.TA_type = S_TAtype;
        UDS_APP_RX.Data.Length  = S_Length - 1u;

        for ( i = 0u; i < S_Length; i++ )
        {
            UDS_APP_RX.Data.A_Data[i] = S_Data[i];
        }
    }
    else if (S_Result == S_NOK)
    {
        UDS_TP_ArTimeOutHandle();
    }
    else
    {

    }
}


/******************************************************************************
应用层服务控制
******************************************************************************/

/******************************************************************************
函数名：UDS_Process_Service_Request
功  能：该函数用于处理来自客户端的服务请求,当有新的服务请求到达时,根据SI选择相
        应的服务实现函数执行服务
参  数：无
返回值：无  SYSC0_RUNPLL2CNTR
******************************************************************************/
void UDS_Process_Service_Request ( void )
{
    uint8_t NRC = positiveResponse;
    if (UDS_APP_RX.A_PDU.New)
    {
        S3_ServiceWait();
        switch (UDS_APP_RX.A_PDU.A_PCI.SI)
        {
        case 0x10 : UDS_Service_10_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x11 : UDS_Service_11_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x14 : UDS_Service_14_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x19 : UDS_Service_19_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x22 : UDS_Service_22_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x27 : UDS_Service_27_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x28 : UDS_Service_28_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x2E : UDS_Service_2E_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x2F : UDS_Service_2F_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x31 : UDS_Service_31_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x3E : UDS_Service_3E_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        case 0x85 : UDS_Service_85_Indication(UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data);
            break;
        default   :
            if (UDS_APP_RX.A_PDU.TA_type != DIAG_ID_Rx_FUN)
            {
                NRC = serviceNotSupported;/*服务不支持*/
                UDS_Service_Response(UDS_APP_RX.A_PDU.A_PCI.SI, NEGATIVE_RSP, DIAG_ID_Tx, 1u, (uint8_t*)&NRC);
            }

            break;
        }
        S3_ServiceClear();
        UDS_APP_RX.A_PDU.New = 0u;
    }
}

/******************************************************************************
函数名：UDS_Service_Response
功  能：该函数根据反馈类型生成相应的反馈数据传递给客户端,通用于各个服务的反馈
参  数：si        ：服务ID
        RspType   ：反馈类型  POSITIVE_RSP 正反馈
                             NEGATIVE_RSP 负反馈
        A_TA_type ：目标地址类型
        A_Length  ：随反馈携带的数据的长度(仅是数据A_Data的长度)
        A_Data    ：随反馈携带的数据
返回值：无
******************************************************************************/
void UDS_Service_Response ( uint8_t si, uint8_t RspType, uint32_t A_TA_type, uint16_t A_Length, uint8_t A_Data[] )
{
    uint16_t i;
    UDS_APP_TX_Union      UDS_APP_TX;
    UDS_APP_TX_NEG_Union  UDS_APP_TX_NEG;

    if ( RspType )
    {
        UDS_APP_TX_NEG.A_PDU.TA_type     = A_TA_type;
        UDS_APP_TX_NEG.A_PDU.A_PCI.NR_SI = 0x7Fu;
        UDS_APP_TX_NEG.A_PDU.A_PCI.SI    = si;
        UDS_APP_TX_NEG.A_PDU.Length      = A_Length;

        for ( i = 0u; i < UDS_APP_TX_NEG.A_PDU.Length; i++ )
        {
            UDS_APP_TX_NEG.A_PDU.Data[i] = A_Data[i];
        }

        UDS_S_Data_Request ( UDS_APP_TX_NEG.Data.TA_type, UDS_APP_TX_NEG.Data.A_Data, UDS_APP_TX_NEG.Data.Length + 2u );
    }
    else
    {
        UDS_APP_TX.A_PDU.TA_type  = A_TA_type;
        UDS_APP_TX.A_PDU.A_PCI.SI = si | 0x40u;
        UDS_APP_TX.A_PDU.Length   = A_Length;

        for ( i = 0u; i < UDS_APP_TX.A_PDU.Length; i++ )
        {
            UDS_APP_TX.A_PDU.Data[i] = A_Data[i];
        }

        UDS_S_Data_Request ( UDS_APP_TX.Data.TA_type, UDS_APP_TX.Data.A_Data, UDS_APP_TX.Data.Length + 1u );
    }
}
