

/*
 ***************************************************************************************************
 * Includes
 ***************************************************************************************************
 */

#include "ComM_Priv.h"

/*
 ***************************************************************************************************
 * Defines
 ***************************************************************************************************
 */

/*
 ***************************************************************************************************
 * Variables
 ***************************************************************************************************
 */

LOCAL_INLINE FUNC(void,COMM_CODE) ComM_LUpdateUserRequest
                        (
                        P2VAR(uint8, AUTOMATIC,COMM_APPL_DATA) RequestCounter_u8,
                        VAR(ComM_ModeType, AUTOMATIC) CurrentComMode_t
                        );


#define COMM_START_SEC_CODE
#include "ComM_Cfg_MemMap.h"

/***************************************************************************************************
 * Function name    : ComM_RequestComMode
 * Syntax           : void ComM_RequestComMode(ComM_UserHandleType User, ComM_ModeType ComMode)
 * Description      : Requesting of a Communication Mode by a user.
 * Parameter        : User -> Handle of the user who requests a mode
                      ComMode -> COMM_FULL_COMMUNICATION / COMM_NO_COMMUNICATION
 * Return value     : E_OK: Successfully changed to the new mode
 *                    E_NOT_OK: Changing to the new mode failed
 *                    COMM_E_MODE_LIMITATION: Mode can not be granted because of mode inhibition.
 *                    COMM_E_UNINIT: ComM not initialized
 ***************************************************************************************************/
/* User Requesting Communication mode*/
/* MR12 RULE 8.3 VIOLATION:Two declarations exists for this api. One is in ComM.h & another generated by RTE. Hence,the difference in identifiers.*/
FUNC(Std_ReturnType,COMM_CODE) ComM_RequestComMode
                                                (
                                                VAR(ComM_UserHandleType, COMM_VAR) User,
                                                VAR(ComM_ModeType, COMM_VAR) ComMode
                                                )
{
    /* Local Variables Declaration */
    P2VAR(ComM_ChannelVarType, AUTOMATIC, COMM_APPL_DATA) channelRamPtr_ps;
    P2VAR(ComM_UserVarType, AUTOMATIC, COMM_APPL_DATA) userRamPtr_ps;
    P2CONST(ComM_UsersType,AUTOMATIC,COMM_APPL_CONST) userConfigPtr_pcs;
    VAR(ComM_ModeType, AUTOMATIC) previousUserRequest_t;
    VAR(ComM_ModeType, AUTOMATIC) currentUserRequest_t;

    #if (COMM_PNC_ENABLED != STD_OFF)
    P2VAR(ComM_PncRamStructType, AUTOMATIC, COMM_APPL_DATA) pncRamPtr_ps;
    #endif  /*  #if (COMM_PNC_ENABLED != STD_OFF  */

    #if(COMM_INHIBITION_ENABLED)
    P2VAR(ComM_GlobalVarType, AUTOMATIC, COMM_APPL_DATA) globalRamPtr_ps;
    #endif  /*  #if(COMM_INHIBITION_ENABLED)  */
      /* Local variable initialization */
    /*******************************************DET STARTS HERE**********************************************/

    #if (COMM_DEV_ERROR_DETECT != STD_OFF)

    /* Check for ComM Initialized */
    if (ComM_GlobalStruct.ComM_InitStatus!=COMM_INIT)
    {
        /* Report DET with ComM not initialized status*/
        (void)Det_ReportError(COMM_MODULE_ID,COMM_INSTANCE_ID,COMM_REQ_COMMODE_APIID,COMM_E_NOT_INITED);
        return E_NOT_INITIALIZED;
    }
    /* Check for requested Mode */
    if ((ComMode != COMM_NO_COMMUNICATION) && (ComMode != COMM_FULL_COMMUNICATION))
    {
        /* Report DET with ComM silent communication mode entered in request communication mode*/
        (void)Det_ReportError(COMM_MODULE_ID,COMM_INSTANCE_ID,COMM_REQ_COMMODE_APIID,COMM_E_WRONG_PARAMETERS);
        return E_NOT_OK;
    }

    /* Check for Configured User or not and if configured get the handle */
    if (User >= COMM_NO_OF_USERS)
    {
        /* Report DET with Invalid Mode parameter*/
        (void)Det_ReportError(COMM_MODULE_ID,COMM_INSTANCE_ID,COMM_REQ_COMMODE_APIID,COMM_E_WRONG_PARAMETERS);
        return E_NOT_OK;
    }
    #endif   /*  (COMM_DEV_ERROR_DETECT != STD_OFF)  */

    /********************************************DET ENDS HERE*************************************************/

    /*    Update the previous user request to check if the request has changed */
    /*  Update the requested mode for the user in it's RAM structure */

    userConfigPtr_pcs = &(COMM_GET_USER_LIST[User]);
    userRamPtr_ps = &ComM_UserStruct[User];
    previousUserRequest_t = userRamPtr_ps->RequestedUserMode_t;
    userRamPtr_ps->RequestedUserMode_t = ComMode;
    currentUserRequest_t = ComMode ;

    if (previousUserRequest_t != currentUserRequest_t)
    {
        uint8 loopCounter_u8;
        uint8 channelId_u8;
        uint8 numChannels_u8;

        #if (COMM_PNC_ENABLED != STD_OFF)
        uint8 pncId_u8;
        uint8 numPncs_u8;

        numPncs_u8 = userConfigPtr_pcs->NumPnc_u8;
        #endif  /*  #if (COMM_PNC_ENABLED != STD_OFF)  */

        numChannels_u8 = userConfigPtr_pcs->NumDirectChannels_u8;

        SchM_Enter_ComM_UserNoNest();

        for(loopCounter_u8 = C_ZERO;loopCounter_u8 < numChannels_u8;loopCounter_u8++)
        {
            channelId_u8 = (userConfigPtr_pcs->DirectChannels_p[loopCounter_u8]);
            channelRamPtr_ps = &ComM_ChannelStruct[channelId_u8];

            /* Update the channel UserRequestCnt_u8 as per the user request */
            ComM_LUpdateUserRequest(&(channelRamPtr_ps->UserRequestCtr_u8), currentUserRequest_t);
        }

        #if (COMM_PNC_ENABLED != STD_OFF)
        /* MR12 RULE 14.3 VIOLATION: The value of COMM_GET_FEATURE_PNC_ENABLED depends on the configuration therefore it will not always be true. */
        if(COMM_GET_FEATURE_PNC_ENABLED)
        {
            for(loopCounter_u8 = C_ZERO; loopCounter_u8 < numPncs_u8; loopCounter_u8++)
            {
                pncId_u8 = (userConfigPtr_pcs->Pncs_p[loopCounter_u8]);
                pncRamPtr_ps = &ComM_PncRamStruct[pncId_u8];

                /* Update the PNC UserRequestCnt_u8 as per the user request */
                ComM_LUpdateUserRequest(&(pncRamPtr_ps ->UserRequestCnt_u8), currentUserRequest_t);
            }
        }
        #endif  /*  #if (COMM_PNC_ENABLED != STD_OFF)  */

        SchM_Exit_ComM_UserNoNest();

    }       /*  if (previousUserRequest_t != currentUserRequest_t)  */

    #if(COMM_INHIBITION_ENABLED)
    globalRamPtr_ps = &ComM_GlobalStruct;

    /* If inhibition is active, then FULL_COM request for the user may not be processed for channels of the user
     * which have inhibition enabled */

    /* If inhibition is active, COMM_E_MODE_LIMITATION should be returned depending on
     * 1. If Limit to no com is active for the user(LimitToNoComCtr_u16 > 0), then always return COMM_E_MODE_LIMITATION
     * as user request is ignored for channel with LimitToNoCom enabled
     * 2. If Prevent wake up is active for the user(WakeUpInhibitionCtr_u16 > 0), then return COMM_E_MODE_LIMITATION if
     * any of the channels of the user is in NO_COM or SILENT_COM(dont return COMM_E_MODE_LIMITATION, if all channels of
     * the user are in FULL_COM mode)
     */

    if((userRamPtr_ps->LimitToNoComCtr_u16 != C_ZERO) ||
       ((userRamPtr_ps->WakeUpInhibitionCtr_u16 != C_ZERO) && (userRamPtr_ps->numChannelsInFullCom_u8 != userConfigPtr_pcs->NumAllChannels_u8)))
    {
        if(currentUserRequest_t == COMM_FULL_COMMUNICATION)
        {
            if(globalRamPtr_ps->ComM_InhibitCounter_u16 != COMM_MAX_U16)
            {
                ++(globalRamPtr_ps->ComM_InhibitCounter_u16);
            }

            return COMM_E_MODE_LIMITATION;
        }
        else
        {
            /* If the requested mode is NO_COM, then E_OK has to be returned, as the request is processed */
            return E_OK;
        }

    }
    else
    #endif  /*  #if(COMM_INHIBITION_ENABLED)  */
    {
        return E_OK;
    }

}


#define COMM_STOP_SEC_CODE
#include "ComM_Cfg_MemMap.h"

/***************************************************************************************************
 * Function name    : ComM_LUpdateUserRequest
 * Syntax           : void ComM_LUpdateUserRequest
 *                          (P2VAR(uint8, AUTOMATIC,COMM_APPL_DATA) RequestCounter_u8, VAR(ComM_ModeType, AUTOMATIC) CurrentComMode_t)
 * Description      : Updating the user request to the counter.
 * Parameter        : RequestCounter_u8 -> counter to be updated (Channel/PNC)
                      CurrentComMode_t -> COMM_FULL_COMMUNICATION / COMM_NO_COMMUNICATION
 * Return value     : E_OK: Successfully changed to the new mode
 *                    E_NOT_OK: Changing to the new mode failed
 ***************************************************************************************************/

LOCAL_INLINE FUNC(void,COMM_CODE) ComM_LUpdateUserRequest
                        (
                        P2VAR(uint8, AUTOMATIC,COMM_APPL_DATA) RequestCounter_u8,
                        VAR(ComM_ModeType, AUTOMATIC) CurrentComMode_t
                        )
{
    /* Local variable declaration */

    /* Local variable initialization */

    if(CurrentComMode_t == COMM_FULL_COMMUNICATION)
    {
        ++ (*RequestCounter_u8);
    }
    else if (CurrentComMode_t == COMM_NO_COMMUNICATION)
    {
        if((*RequestCounter_u8) != C_ZERO)
        {
            -- (*RequestCounter_u8);
        }
        else
        {
            /* Control shouldn't come here.If at all happens, report to DET */
            #if (COMM_DEV_ERROR_DETECT != STD_OFF)
            (void)Det_ReportError(COMM_MODULE_ID,COMM_INSTANCE_ID,COMM_REQ_COMMODE_APIID,COMM_E_CNTR_UNDERFLW);
            #endif   /*  (COMM_DEV_ERROR_DETECT != STD_OFF)  */
        }
    }
    else
    {
        /* Requested mode is neither FULL_COM nor NO_COM.
         * control shouldn't come here*/
    }
}

