CellularError_t Cellular_SetPdnConfig()

in modules/sara_r4/cellular_r4_api.c [2529:2679]


CellularError_t Cellular_SetPdnConfig( CellularHandle_t cellularHandle,
                                       uint8_t contextId,
                                       const CellularPdnConfig_t * pPdnConfig )
{
    CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
    CellularError_t cellularStatus = CELLULAR_SUCCESS;
    CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
    char cmdBuf[ CELLULAR_AT_CMD_MAX_SIZE ] = { '\0' };
    char pPdpTypeStr[ CELULAR_PDN_CONTEXT_TYPE_MAX_SIZE ] = { '\0' };
    uint32_t i = 0;

    CellularPdnContextInfo_t pdpContextsInfo = { 0 };
    CellularPdnContextInfo_t * pPdpContextsInfo = &pdpContextsInfo;

    CellularAtReq_t atReqSetPdn =
    {
        NULL,
        CELLULAR_AT_NO_RESULT,
        NULL,
        NULL,
        NULL,
        0,
    };

    atReqSetPdn.pAtCmd = cmdBuf;

    if( pPdnConfig == NULL )
    {
        LogDebug( ( "Cellular_SetPdnConfig: Input parameter is NULL" ) );
        cellularStatus = CELLULAR_BAD_PARAMETER;
    }
    else
    {
        switch( pPdnConfig->pdnContextType )
        {
            case CELLULAR_PDN_CONTEXT_IPV4:
                ( void ) strncpy( pPdpTypeStr, "IP", 3U ); /* 3U is the length of "IP" + '\0'. */
                break;

            case CELLULAR_PDN_CONTEXT_IPV6:
                ( void ) strncpy( pPdpTypeStr, "IPV6", 5U ); /* 5U is the length of "IPV6" + '\0'. */
                break;

            case CELLULAR_PDN_CONTEXT_IPV4V6:
                ( void ) strncpy( pPdpTypeStr, "IPV4V6", 7U ); /* 7U is the length of "IPV4V6" + '\0'. */
                break;

            default:
                LogDebug( ( "Cellular_SetPdnConfig: Invalid pdn context type %d",
                            CELLULAR_PDN_CONTEXT_IPV4V6 ) );
                cellularStatus = CELLULAR_BAD_PARAMETER;
                break;
        }
    }

    if( cellularStatus == CELLULAR_SUCCESS )
    {
        cellularStatus = _Cellular_IsValidPdn( contextId );
    }

    if( cellularStatus == CELLULAR_SUCCESS )
    {
        /* Make sure the library is open. */
        cellularStatus = _Cellular_CheckLibraryStatus( pContext );
    }

    if( cellularStatus == CELLULAR_SUCCESS )
    {
        /* Check current APN name and IP type of contextId first to avoid unneccessary network de-registration. */
        /* TODO: This implementation currently assumes only one context in list. Need to add complete contexts list parsing */

        CellularAtReq_t atReqGetCurrentApnName =
        {
            "AT+CGDCONT?",
            CELLULAR_AT_MULTI_WITH_PREFIX,
            "+CGDCONT",
            _Cellular_RecvFuncGetPdpContextSettings,
            NULL,
            sizeof( CellularPdnContextInfo_t ),
        };
        atReqGetCurrentApnName.pData = pPdpContextsInfo;

        pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetCurrentApnName );
        cellularStatus = _Cellular_TranslatePktStatus( pktStatus );

        if( cellularStatus == CELLULAR_SUCCESS )
        {
            LogDebug( ( "Cellular_SetPdnConfig: Listing operator and context details below." ) );

            for( i = 0U; i < ( MAX_PDP_CONTEXTS - 1 ); i++ )
            {
                /* Print only those contexts that are present in +CGDCONT response */
                if( pdpContextsInfo.contextsPresent[ i ] )
                {
                    LogDebug( ( "Context [%d], IP Type [%s], APN Name [%s], IP Address [%s]\r\n", i + 1,
                                pdpContextsInfo.ipType[ i ], ( char * ) pdpContextsInfo.apnName,
                                ( char * ) pdpContextsInfo.ipAddress ) );
                }
            }
        }
    }

    if( cellularStatus == CELLULAR_SUCCESS )
    {
        /* Form the AT command. */

        /* The return value of snprintf is not used.
         * The max length of the string is fixed and checked offline. */
        /* coverity[misra_c_2012_rule_21_6_violation]. */

        if( ( strstr( pdpContextsInfo.apnName[ contextId - 1 ], pPdnConfig->apnName ) == NULL ) || ( strcmp( pdpContextsInfo.ipType[ contextId - 1 ], pPdpTypeStr ) != 0 ) )
        {
            if( strcmp( pdpContextsInfo.ipType[ contextId - 1 ], pPdpTypeStr ) != 0 )
            {
                LogInfo( ( "Cellular_SetPdnConfig: Setting new IPv (Module IPv:%s != %s)\r\n", pdpContextsInfo.ipType[ contextId - 1 ], pPdpTypeStr ) );
            }

            if( strstr( pdpContextsInfo.apnName[ contextId - 1 ], pPdnConfig->apnName ) == NULL )
            {
                LogInfo( ( "Cellular_SetPdnConfig: Setting new APN (Module APN:%s != %s)\r\n", pdpContextsInfo.apnName[ contextId - 1 ], pPdnConfig->apnName ) );
            }

            /* TODO: Add support if + UAUTHREQ is PAP / CHAP */
            ( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s%d,\"%s\",\"%s\",,0,0;%s%d,%d%s", /*,\"%s\",\"%s\"      TODO: add if +UAUTHREQ is PAP/CHAP */
                               "AT+COPS=2;+CGDCONT=",
                               contextId,
                               pPdpTypeStr,
                               pPdnConfig->apnName,
                               "+UAUTHREQ=",
                               contextId,
                               pPdnConfig->pdnAuthType,
                               ";+COPS=0" );
            /*pPdnConfig->username, */
            /*pPdnConfig->password); */

            pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetPdn );

            if( pktStatus != CELLULAR_PKT_STATUS_OK )
            {
                LogError( ( "Cellular_SetPdnConfig: can't set PDN, cmdBuf:%s, PktRet: %d", cmdBuf, pktStatus ) );
                cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
            }
        }
        else
        {
            LogInfo( ( "Cellular_SetPdnConfig: APN and IPv already set.\r\n" ) );
        }
    }

    return cellularStatus;
}