/******************************************************************************
文 件 名：UDS_ISO14229_Server.c
功能描述：ISO 14229 规范规定的诊断服务服务器端函数库文件
作    者：张暄
版    本：V1.0
日    期：2016.11.1
******************************************************************************/
#include "UDS_ISO14229_Server.h"
#include "PowerManagement.h"
#include  <string.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 uint16_t S3_ServerCnt;
extern Power_Statuss  g_Power_St; 

/******************************************************************************
后台服务
******************************************************************************/
/******************************************************************************
函数名：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    ：数据的接收结果
返回值：无
******************************************************************************/
extern 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 )
{
}

/******************************************************************************
函数名：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 )
{
    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;
        (void)memcpy(UDS_APP_RX.Data.A_Data,S_Data, S_Length);
    }
}

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

/******************************************************************************
函数名：UDS_Process_Service_Request
功  能：该函数用于处理来自客户端的服务请求,当有新的服务请求到达时,根据SI选择相
        应的服务实现函数执行服务
参  数：无
返回值：无
******************************************************************************/
void UDS_Process_Service_Request ( void )
{
    if ( UDS_APP_RX.A_PDU.New )
    {
        if (IGN_Stay_ON == g_Power_St)
        {
            S3_ServerCnt = 0;
            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 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 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 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 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 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 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 0x34 : UDS_Service_34_Indication ( UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data );
                    break;

                case 0x36 : UDS_Service_36_Indication ( UDS_APP_RX.A_PDU.TA_type, UDS_APP_RX.A_PDU.Length, UDS_APP_RX.A_PDU.Data );
                    break;

                case 0x37 : UDS_Service_37_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 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 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_PHY )
                    {
                        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    ：随反馈携带的数据
返回值：无
******************************************************************************/
void UDS_Service_Response ( uint8_t si, uint8_t RspType, uint32_t A_TA_type, uint16_t A_Length, uint8_t *A_Data )
{
    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;
        (void)memcpy(UDS_APP_TX_NEG.A_PDU.Data,A_Data, UDS_APP_TX_NEG.A_PDU.Length);
        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;

        (void)memcpy(UDS_APP_TX.A_PDU.Data,A_Data, UDS_APP_TX.A_PDU.Length);

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