
/*------------------------------- includes --------------------------------*/
//#include "Global.h"
#include "Std_Types.h"
//#include "Timer.h"
#include "DiagnosticR/Comp_HAL_Autosar_Wrappers/Timer.h"

#include "Iso15765_3_Task.h"

#include "Iso15765_3.h"
//#include "Iso15765_3_CFG.h"
#include "DiagnosticR/UDS/Iso15765_layer3/Iso15765_3_CFG.h"

#define SECURED_DIAGNOSTICS_ENABLED ((UI_8)0x34)

#define SEC_NO_REQUEST  ((UI_8)0)
#define SEC_REQUEST_SEED ((UI_8)1)
#define SEC_CHECK_KEY  ((UI_8)2)
#define SEC_SESSION_CHANGED       ((UI_8)3)

static UI_8 security_status = UDS_ECU_LOCKED;
static UI_8 force_unlock = UDS_ECU_LOCKED;
static UI_8 sec_request = SEC_NO_REQUEST;
static UI_8 key_type = 0;
static UI_8 seed_type = 0;
static BOOL key_ok = FALSE;
static BOOL consecutive_seed_requests = FALSE;

/*------------------------------ user code --------------------------------*/


UI_8 UdsSecurityTaskQueryAccessStatus(void)
{
    return security_status;
}

BOOL UdsSecurityTaskQueryIfConsecutiveRequestSeed(void)
{
    return consecutive_seed_requests;
}

static void SendZeroSeed(void)
{
    UI_8 i;
    tp_uds_security_access_seed_resp resp;

    if (Iso15765_3QueryRequestSize() == (UI_16) 2) {
#ifdef ISO15765_3_GEELY  
        /* Check positive-response-not-requested flag,
         * Suppress bit not supported in Geely */
        if (iso15765_3_supress_pos_resp == FALSE) {
#endif
            resp = ISO15765_3_GET_RESP_DATA(tp_uds_security_access_seed_resp);
            resp->access_mode = seed_type;
            for (i = 0; i < SECURITY_SEED_SIZE; i++) {
                resp->seed[i] = (UI_8) 0;
            }
            Iso15765_3IncrementResponseSize((UI_8) 1 + SECURITY_SEED_SIZE);
            Iso15765_3SendResponse(ISO15765_3_POSITIVE_RESPONSE);
#ifdef ISO15765_3_GEELY   
        } else {
            /* Check positive-response-not-requested flag,
             * Suppress bit not supported in Geely */
            Iso15765_3SendResponse(UDS_ERR_REQUEST_OUT_OF_RANGE);
        }
#endif
    } else {
        Iso15765_3SendResponse(UDS_ERR_INVALID_FORMAT);
    }
}

void UdsSecurityTaskRequestSeed(UI_8 level)
{
    /* Requesting seed */
    sec_request = SEC_REQUEST_SEED;
    /* Save the level to match with the correct send key level */
    seed_type = level;
    key_type = 0;
}

void UdsSecurityTaskCheckKey(UI_8 level, UI_8* key)
{
    UI_8 i;
    /* Send Key */
    sec_request = SEC_CHECK_KEY;
    key_type = level;
    for (i = 0; i < SECURITY_KEY_SIZE; i++) {
        security_control.host_key[i] = key[i];
    }
}

void UDSSecurityTaskNotifySessionChanged(void)
{
    sec_request = SEC_SESSION_CHANGED;
}

void UdsSecurityTaskForceLockState(UI_8 state)
{
    force_unlock = state;
    security_status = state;
}

/*-------------------------------- macros ---------------------------------*/





/*------------------------------- defines ---------------------------------*/
/* Maxim valor del compteig del temps */
#define MAX_COMPTADOR_TEMPS ((UI_16)65000)

/*---------------------------- tipus de dades -----------------------------*/

typedef enum {
    ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST = 1,
    ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY = 2,
    ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY = 3,
    ESTAT_ISO15765_3_SECURITYTASK_UNLOCK = 4,
    ESTAT_ISO15765_3_SECURITYTASK_CHECKKEY = 5,
    ESTAT_ISO15765_3_SECURITYTASK_GETSEED = 6,
    ESTAT_0_ISO15765_3_SECURITYTASK = 0
} t_estat_iso15765_3_securitytask;


/*------------------------------ variables --------------------------------*/

/* Variables d estat */
static t_estat_iso15765_3_securitytask estat_iso15765_3_securitytask = ESTAT_0_ISO15765_3_SECURITYTASK;

/* Timers implicits */
static t_clock temps_iso15765_3_securitytask = (t_clock) 0;
static UI_8 response = 0;


/*------------------------- capcaleres de funcions ------------------------*/

static void Iso15765_3_SecurityTask0(void);
static void Wait_Seed_Request(void);
static void Penalty_Delay(void);
static void Wait_Tool_Key(void);
static void Unlock(void);
static void Checkkey(void);
static void GetSeed(void);


/*----------------------- funcions d'inicialitzacio -----------------------*/

/**************************************************************************** 
| Funcionalitat:                                                              
|   Inicialitzacio del diagrama d estats Iso15765_3_SecurityTask 
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades: - 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
void Iso15765_3_SecurityTaskInicialitza(void)
{
    /* Inicialitzacio de la variable d estat */
    estat_iso15765_3_securitytask = ESTAT_0_ISO15765_3_SECURITYTASK;

    /* Inicialitzacio del timer implicit */
    temps_iso15765_3_securitytask = (t_clock) 0;

    /* Execucio del cicle inicial de la maquina d estats */
    Iso15765_3_SecurityTask();
}


/*------------------------- rutines principals ---------------------------*/

/**************************************************************************** 
| Funcionalitat:                                                              
|   Rutina principal del diagrama d estats Iso15765_3_SecurityTask. 
|   Invoca a la funcio corresponent a l estat actual. 
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
void Iso15765_3_SecurityTask(void)
{
    /* Estudi per casos del estat actual */
    switch (estat_iso15765_3_securitytask) {
    case ESTAT_0_ISO15765_3_SECURITYTASK:
        Iso15765_3_SecurityTask0();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST:
        Wait_Seed_Request();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY:
        Penalty_Delay();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY:
        Wait_Tool_Key();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_UNLOCK:
        Unlock();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_CHECKKEY:
        Checkkey();
        break;
    case ESTAT_ISO15765_3_SECURITYTASK_GETSEED:
        GetSeed();
        break;
    default:
        estat_iso15765_3_securitytask = ESTAT_0_ISO15765_3_SECURITYTASK;
        break;
    }

    /* Increment del temps de cicle al timer implicit */
    if (temps_iso15765_3_securitytask < MAX_COMPTADOR_TEMPS) {
        temps_iso15765_3_securitytask += TimerDeltaCicleConsulta();
    }
}


/*------------------------- funcions d'estats -----------------------------*/

/**************************************************************************** 
| Funcionalitat: 
|   Funcio corresponent a l estat inicial del proces Iso15765_3_SecurityTask 
|---------------------------------------------------------------------------- 
| Interficie: -                                                                
 ****************************************************************************/
static void Iso15765_3_SecurityTask0(void)
{

    if (SECURITY_INIT_DELAY == SECURITY_NO_DELAY) {
        /* Avaluem condicio de start del estat Wait_Seed_Request */

        /* -- action de la transicio inicial -- */
        seed_type = (UI_8) 0;
        key_type = (UI_8) 0;
        sec_request = SEC_NO_REQUEST;
        Iso15765_3SecurityAttemptsInitialize();
        force_unlock = UDS_ECU_LOCKED;

        /* -- entry de l estat -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* Canviem l estat inicial */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if (SECURITY_INIT_DELAY == SECURITY_DELAY) {
        /* Avaluem condicio de start del estat Penalty_Delay */

        /* -- action de la transicio inicial -- */
        seed_type = (UI_8) 0;
        key_type = (UI_8) 0;
        sec_request = SEC_NO_REQUEST;
        Iso15765_3SecurityAttemptsInitialize();

        /* -- entry de l estat -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* Canviem l estat inicial */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY;
    } else {
        /* No s ha activat cap condicio inicial: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_0_ISO15765_3_SECURITYTASK;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Wait_Seed_Request.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void Wait_Seed_Request(void)
{
    /* -- during de l estat actual -- */

    security_status = UDS_ECU_LOCKED;

    if ((Iso15765_3SecurityAttemptsExceeded() == FALSE) && (sec_request == SEC_CHECK_KEY)) {
        /* Cas en que executem la transicio Asking_Key_Wrong_State */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(UDS_ERR_REQUEST_SEQUENCE_ERROR);
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((Iso15765_3SecurityAttemptsExceeded() == FALSE) && (sec_request == SEC_REQUEST_SEED)) {
        /* Cas en que executem la transicio Seed request */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat GetSeed -- */
        consecutive_seed_requests = FALSE;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_GETSEED;
    } else if ((Iso15765_3SecurityAttemptsExceeded() == FALSE) && sec_request == SEC_SESSION_CHANGED) {
        /* Cas en que executem la transicio  */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((Iso15765_3SecurityAttemptsExceeded() == FALSE) && force_unlock != UDS_ECU_LOCKED) {
        /* Cas en que executem la transicio  */

        /* -- action de la transicio -- */
        security_status = seed_type;

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else if ((Iso15765_3SecurityAttemptsExceeded() == TRUE)) {
        /* Cas en que executem la transicio  */

        /* -- entry de l estat Penalty_Delay -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Penalty_Delay.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void Penalty_Delay(void)
{
    /* -- during de l estat actual -- */

    if (sec_request != SEC_NO_REQUEST) {
        if (sec_request != SEC_SESSION_CHANGED) {
            if (sec_request == SEC_REQUEST_SEED) {
                Iso15765_3SendResponse(UDS_ERR_REQUIRED_TIME_DELAY_NOT_EXPIRED);
            } else {
                /* Send key received */
                Iso15765_3SendResponse(UDS_ERR_REQUEST_SEQUENCE_ERROR);
            }
        }
        consecutive_seed_requests = FALSE;
        sec_request = SEC_NO_REQUEST;
    }


    if (temps_iso15765_3_securitytask >= TIMER_MS_TO_TICKS(SECURITY_PENALTY_TIME)) {
        /* Cas en que executem la transicio Penalty_Ended */

        /* -- action de la transicio -- */
        Iso15765_3SecurityAttemptsDecrement();

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Wait_Tool_Key.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void Wait_Tool_Key(void)
{
    if ((Iso15765_3VariantConsecutiveSeedIncrAttempt() == TRUE) && (sec_request == SEC_REQUEST_SEED) && (Iso15765_3SecurityAttemptsReached() == FALSE) && (sec_request != SEC_SESSION_CHANGED)) {
        /* Cas en que executem la transicio Asking_Seed_Wrong_State */

        /* -- action de la transicio -- */
        /* NRC does not apply, request seed to application again */
        /* Parameter signals consectutive */
        consecutive_seed_requests = TRUE;
        response = UDS_SECURITY_REQUEST_SEED_CALLBACK(seed_type, security_control.local_seed);
        Iso15765_3SecurityAttemptsIncrement();
        Iso15765_3SendResponse(response);

        /* -- entry de l estat Wait_Tool_Key -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY;
    } else if (sec_request == SEC_SESSION_CHANGED) {
        /* Cas en que executem la transicio Locked_due_to_session_change */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((sec_request == SEC_CHECK_KEY) && (Iso15765_3QueryRequestSize() >= ((UI_16) 2 + SECURITY_KEY_SIZE)) && (sec_request != SEC_SESSION_CHANGED)) {
        /* Cas en que executem la transicio Key Received */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_CHECKKEY;
    } else if ((sec_request == SEC_CHECK_KEY) && (Iso15765_3QueryRequestSize() < ((UI_16) 2 + SECURITY_KEY_SIZE)) && (sec_request != SEC_SESSION_CHANGED)) {
        /* Cas en que executem la transicio Key Received with wrong size */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(UDS_ERR_INVALID_FORMAT);

        /* -- entry de l estat Wait_Tool_Key -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY;
    } else if ((Iso15765_3VariantConsecutiveSeedIncrAttempt() == TRUE) && (sec_request == SEC_REQUEST_SEED) && (Iso15765_3SecurityAttemptsReached() == TRUE) && (sec_request != SEC_SESSION_CHANGED)) {
        /* Cas en que executem la transicio AskingConsecutiveSeedCausesCounterToExceed */

        /* -- action de la transicio -- */
        /* NRC does not apply, request seed to application again */
        /* Parameter signals consectutive */
        consecutive_seed_requests = TRUE;
        Iso15765_3SecurityAttemptsIncrement();
        Iso15765_3SendResponse(UDS_ERR_REQUIRED_TIME_DELAY_NOT_EXPIRED);

        /* -- entry de l estat Penalty_Delay -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Unlock.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void Unlock(void)
{
    if (sec_request == SEC_SESSION_CHANGED) {
        /* Cas en que executem la transicio Locked_due_to_session_change */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;
        force_unlock = UDS_ECU_LOCKED;

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((sec_request == SEC_REQUEST_SEED) && (seed_type == security_status)) {
        /* Cas en que executem la transicio Seed_requested */

        /* -- action de la transicio -- */
        SendZeroSeed();
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else if ((sec_request == SEC_CHECK_KEY)) {
        /* Cas en que executem la transicio Send Key Unlocked */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(UDS_ERR_REQUEST_SEQUENCE_ERROR);
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else if ((sec_request == SEC_REQUEST_SEED) && (seed_type != security_status)) {
        /* Cas en que executem la transicio Another level required */

        /* -- action de la transicio -- */
        sec_request = SEC_NO_REQUEST;

        /* -- entry de l estat GetSeed -- */
        consecutive_seed_requests = FALSE;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_GETSEED;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat Checkkey.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void Checkkey(void)
{
    /* -- codi de l estat actual -- */
    key_ok = UDS_SECURITY_CHECK_KEY_CALLBACK(key_type, security_control.local_seed,
            security_control.host_key, &response);

    if ((key_ok == TRUE) && ((response == ISO15765_3_POSITIVE_RESPONSE) || (response == UDS_ERR_RESPONSE_PENDING))) {
        /* Cas en que executem la transicio Key Valid */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(response);
        sec_request = SEC_NO_REQUEST;
        Iso15765_3SecurityAttemptsClear();
        security_status = seed_type;

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else if ((security_status == UDS_ECU_LOCKED) && (key_ok == FALSE) && (Iso15765_3SecurityAttemptsReached() == FALSE)) {
        /* Cas en que executem la transicio Key Invalid && ECU locked */

        /* -- action de la transicio -- */
        Iso15765_3SecurityAttemptsIncrement();
        Iso15765_3SendResponse(UDS_ERR_INVALID_KEY);

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((key_ok == FALSE) && (Iso15765_3SecurityAttemptsReached() == TRUE)) {
        /* Cas en que executem la transicio Key Invalid, max attempts reached */

        /* -- action de la transicio -- */
        Iso15765_3SecurityAttemptsIncrement();
        Iso15765_3SendResponse(UDS_ERR_EXCEEDED_NUMBER_OF_ATTEMPTS);

        /* -- entry de l estat Penalty_Delay -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_PENALTY_DELAY;
    } else if ((response != ISO15765_3_POSITIVE_RESPONSE) && (response != UDS_ERR_INVALID_KEY) && (response != UDS_ERR_RESPONSE_PENDING) && (Iso15765_3SecurityAttemptsReached() == FALSE)) {
        /* Cas en que executem la transicio Invalid key type */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(response);

        /* -- entry de l estat Wait_Tool_Key -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY;
    } else if ((security_status != UDS_ECU_LOCKED) && (key_ok == FALSE) && (Iso15765_3SecurityAttemptsReached() == FALSE)) {
        /* Cas en que executem la transicio Key failed && ecu unlocked */

        /* -- action de la transicio -- */
        Iso15765_3SecurityAttemptsIncrement();
        Iso15765_3SendResponse(response);
        sec_request = SEC_NO_REQUEST;
        seed_type = security_status;

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_CHECKKEY;
    }
}

/**************************************************************************** 
| Funcionalitat:                                                              
|   Funcio corresponent a l estat GetSeed.                              
|---------------------------------------------------------------------------- 
| Interficie:                                                                 
|   Entrades:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       tool_key
|       access_mode
|       security_failed_attempts 
|   Sortides:
|       estat_iso15765_3_securitytask
|       temps_iso15765_3_securitytask
|       local_seed
|       security_failed_attempts 
 ****************************************************************************/
static void GetSeed(void)
{
    /* -- during de l estat actual -- */

    response = UDS_SECURITY_REQUEST_SEED_CALLBACK(seed_type, security_control.local_seed);

    if ((response == ISO15765_3_POSITIVE_RESPONSE) || (response == UDS_ERR_RESPONSE_PENDING)) {
        /* Cas en que executem la transicio  */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(response);

        /* -- entry de l estat Wait_Tool_Key -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_TOOL_KEY;
    } else if ((response != ISO15765_3_POSITIVE_RESPONSE) && (response != UDS_ERR_RESPONSE_PENDING) && (security_status == UDS_ECU_LOCKED)) {
        /* Cas en que executem la transicio Wrong seed type */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(response);

        /* -- entry de l estat Wait_Seed_Request -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_WAIT_SEED_REQUEST;
    } else if ((response != ISO15765_3_POSITIVE_RESPONSE) && (response != UDS_ERR_RESPONSE_PENDING) && (security_status != UDS_ECU_LOCKED)) {
        /* Cas en que executem la transicio Wrong seed access when unlocked */

        /* -- action de la transicio -- */
        Iso15765_3SendResponse(response);

        /* -- entry de l estat Unlock -- */
        sec_request = SEC_NO_REQUEST;

        /* Inicialitzacio del timer implicit */
        temps_iso15765_3_securitytask = (t_clock) 0;

        /* -- canviem l estat -- */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_UNLOCK;
    } else {

        /* No s ha activat cap transicio: ens quedem a l estat actual */
        estat_iso15765_3_securitytask = ESTAT_ISO15765_3_SECURITYTASK_GETSEED;
    }
}


/********************************** FI **************************************/
