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

UDS_APP_RX_Union     UDS_APP_RX;
UDS_APP_TX_Union     UDS_APP_TX;
UDS_APP_TX_NEG_Union UDS_APP_TX_NEG;

extern DiagSendDataNeg NegRes;
extern uint8_t         CAN_Current_state;

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

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

/******************************************************************************
函数名: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(uint16_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(uint16_t N_TAtype, uint8_t 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(uint16_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    :数据的接收结果
返回值:无
******************************************************************************/
extern void UDS_N_USData_Indication(uint16_t N_TAtype, uint8_t *MessageData, uint16_t Length, uint8_t 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(uint16_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(uint16_t S_TAtype, S_Result_Enum S_Result)
{
}

/******************************************************************************
函数名: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(uint16_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     = 1;
        UDS_APP_RX.Data.TA_type = S_TAtype;
        UDS_APP_RX.Data.Length  = S_Length - 1;

        for ( i = 0; i < S_Length; i++ )
        {
            UDS_APP_RX.Data.A_Data [ i ] = *S_Data;
            S_Data++;
        }
    }
}

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

/******************************************************************************
函数名:UDS_Process_Service_Request
功  能:该函数用于处理来自客户端的服务请求,当有新的服务请求到达时,根据SI选择相
        应的服务实现函数执行服务
参  数:无
返回值:无  SYSC0_RUNPLL2CNTR
******************************************************************************/
extern uint8_t S3_Server_refresh;
void UDS_Process_Service_Request(void)
{
    if (UDS_APP_RX.A_PDU.New)
    {
        S3_Server_refresh = 1;
        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 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 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;
        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 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;
        default:
            if (UDS_APP_RX.A_PDU.TA_type != DIAG_ID_Rx_FUN)
            {
                NegRes.code = serviceNotSupported;
                UDS_Service_Response(UDS_APP_RX.A_PDU.A_PCI.SI, NEGATIVE_RSP, DIAG_ID_Tx, 1, (uint8_t *)(&NegRes.code));
            }
            break;
        }
        UDS_APP_RX.A_PDU.New = 0;
    }
}

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

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

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

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

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

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