

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

#include "ComM_Priv.h"

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

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

LOCAL_INLINE void ComM_Prv_UpdateUserRequest(uint16 * RequestCounter_pu16, ComM_ModeType CurrentComMode_tu8);

#if (COMM_PNC_ENABLED != STD_OFF)
LOCAL_INLINE void ComM_Prv_UpdatePncUserRequest(uint8 * RequestCounter_pu8, ComM_ModeType CurrentComMode_tu8);
#endif  /*  #if (COMM_PNC_ENABLED != STD_OFF)  */

#define COMM_START_SEC_CODE
#include "ComM_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.*/
Std_ReturnType ComM_RequestComMode(ComM_UserHandleType User, ComM_ModeType ComMode)
{
    /* Local Variables Declaration */
    ComM_ChannelVarType_tst *   channelRamPtr_pst;
    ComM_UserVarType_tst *      userRamPtr_pst;
    const ComM_UsersType_tst *  userConfigPtr_pcst;
    ComM_ModeType               previousUserRequest_tu8;
    ComM_ModeType               currentUserRequest_tu8;
    uint8                       userId_internal_u8;

    #if (COMM_MANAGING_CHANNEL_PRESENT != STD_OFF)
    ComM_ChannelVarType_tst *   masterChannelRamPtr_pst;
    const ComM_ChannelType_tst *    channelConfigPtr_pcst;
    uint8                       masterChannelId_u8;
    #endif  /*  #if (COMM_MANAGING_CHANNEL_PRESENT != STD_OFF)  */

    #if (COMM_PNC_ENABLED != STD_OFF)
    ComM_PncRamStructType_tst *     pncRamPtr_pst;
    #endif  /*  #if (COMM_PNC_ENABLED != STD_OFF  */

    #if(COMM_INHIBITION_ENABLED)
    ComM_GlobalVarType_tst *        globalRamPtr_pst;
    #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_en!=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 COMM_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 ( ComM_Prv_ValidateUserId(User) == FALSE )
    {
        /* 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 */

    userId_internal_u8 = ComM_UserId_MappingTable_acst[User];
    userConfigPtr_pcst = &(COMM_GET_USER_LIST[userId_internal_u8]);
    userRamPtr_pst = &ComM_UserStruct[userId_internal_u8];
    previousUserRequest_tu8 = userRamPtr_pst->RequestedUserMode_u8;
    userRamPtr_pst->RequestedUserMode_u8 = ComMode;
    currentUserRequest_tu8 = ComMode ;

    if (previousUserRequest_tu8 != currentUserRequest_tu8)
    {
        uint8   loopCounter_u8;
        uint8   channelId_u8;
        uint8   numChannels_u8;

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

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

        numChannels_u8 = userConfigPtr_pcst->NumDirectChannels_u8;

        SchM_Enter_ComM_UserNoNest();

        for(loopCounter_u8 = C_ZERO;loopCounter_u8 < numChannels_u8;loopCounter_u8++)
        {
            channelId_u8 = (userConfigPtr_pcst->DirectChannels_pcu8[loopCounter_u8]);
            channelRamPtr_pst = &ComM_ChannelStruct[channelId_u8];

            #if (COMM_MANAGING_CHANNEL_PRESENT != STD_OFF)
            channelConfigPtr_pcst = &(COMM_GET_CHANNEL_LIST[channelId_u8]);
            if(channelConfigPtr_pcst->ComMMasterChannelPresent_b == TRUE)
            {
                /* Managing Channel Id is copied to a local buffer */
                masterChannelId_u8 = channelConfigPtr_pcst->masterChannelId_u8;
                masterChannelRamPtr_pst = &ComM_ChannelStruct[masterChannelId_u8];

                ComM_Prv_UpdateUserRequest(&(masterChannelRamPtr_pst->UserRequestCtr_u16), currentUserRequest_tu8);
            }
            #endif  /*  #if (COMM_MANAGING_CHANNEL_PRESENT != STD_OFF)  */

            /* Update the channel UserRequestCtr_u16 as per the user request */
            ComM_Prv_UpdateUserRequest(&(channelRamPtr_pst->UserRequestCtr_u16), currentUserRequest_tu8);
        }

        #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_pcst->Pncs_pcu8[loopCounter_u8]);
                pncRamPtr_pst = &ComM_PncRamStruct[pncId_u8];

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

        SchM_Exit_ComM_UserNoNest();
        #if ((COMM_FULLCOMREQ_NOTIF != STD_OFF)&&(COMM_RTE_SUPPORT != STD_OFF))
        ComM_Prv_UpdateFullComRequestors(User,ComMode);
        #endif

    }       /*  if (previousUserRequest_tu8 != currentUserRequest_tu8)  */

    #if(COMM_INHIBITION_ENABLED)
    globalRamPtr_pst = &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_pst->LimitToNoComCtr_u16 != C_ZERO) ||
       ((userRamPtr_pst->WakeUpInhibitionCtr_u16 != C_ZERO) && (userRamPtr_pst->numChannelsInFullCom_u8 != userConfigPtr_pcst->NumAllChannels_u8)))
    {
        if(currentUserRequest_tu8 == COMM_FULL_COMMUNICATION)
        {
            if(globalRamPtr_pst->ComM_InhibitCounter_u16 != COMM_MAX_U16)
            {
                ++(globalRamPtr_pst->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_MemMap.h"

/***************************************************************************************************
 * Function name    : ComM_Prv_UpdateUserRequest
 * Syntax           : void ComM_Prv_UpdateUserRequest
 *                         (uint16 * RequestCounter_pu16, ComM_ModeType CurrentComMode_tu8)
 * Description      : Updating the user request to the counter.
 * Parameter        : RequestCounter_pu16 -> counter to be updated (Channel)
                      CurrentComMode_tu8 -> 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 void ComM_Prv_UpdateUserRequest(uint16 * RequestCounter_pu16, ComM_ModeType CurrentComMode_tu8)
{
    /* Local variable declaration */

    /* Local variable initialization */

    if(CurrentComMode_tu8 == COMM_FULL_COMMUNICATION)
    {
        ++ (*RequestCounter_pu16);
    }
    else if (CurrentComMode_tu8 == COMM_NO_COMMUNICATION)
    {
        if((*RequestCounter_pu16) != C_ZERO_U16)
        {
            -- (*RequestCounter_pu16);
        }
        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*/
    }
}

/***************************************************************************************************
 * Function name    : ComM_Prv_UpdatePncUserRequest
 * Syntax           : void ComM_Prv_UpdatePncUserRequest
 *                          (uint8 * RequestCounter_pu8, ComM_ModeType CurrentComMode_tu8)
 * Description      : Updating the PNC user request to the counter.
 * Parameter        : RequestCounter_pu8 -> PNC user request counter to be updated
                      CurrentComMode_tu8 -> 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
 ***************************************************************************************************/

#if (COMM_PNC_ENABLED != STD_OFF)
LOCAL_INLINE void ComM_Prv_UpdatePncUserRequest(uint8 * RequestCounter_pu8, ComM_ModeType CurrentComMode_tu8)
{
    /* Local variable declaration */

    /* Local variable initialization */

    if(CurrentComMode_tu8 == COMM_FULL_COMMUNICATION)
    {
        ++ (*RequestCounter_pu8);
    }
    else if (CurrentComMode_tu8 == COMM_NO_COMMUNICATION)
    {
        if((*RequestCounter_pu8) != C_ZERO)
        {
            -- (*RequestCounter_pu8);
        }
        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*/
    }
}
#endif  /*  #if (COMM_PNC_ENABLED != STD_OFF)  */

