2835 lines
103 KiB
C
2835 lines
103 KiB
C
/*
|
|
* FreeRTOS-Cellular-Interface v1.1.0
|
|
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
*
|
|
* Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
* this software and associated documentation files (the "Software"), to deal in
|
|
* the Software without restriction, including without limitation the rights to
|
|
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
|
* the Software, and to permit persons to whom the Software is furnished to do so,
|
|
* subject to the following conditions:
|
|
*
|
|
* The above copyright notice and this permission notice shall be included in all
|
|
* copies or substantial portions of the Software.
|
|
*
|
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
|
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
|
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
|
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
*
|
|
* https://www.FreeRTOS.org
|
|
* https://github.com/FreeRTOS
|
|
*/
|
|
#include "cellular_config.h"
|
|
#include "cellular_config_defaults.h"
|
|
|
|
/* Standard includes. */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
/* Cellular includes. */
|
|
#include "cellular_platform.h"
|
|
#include "cellular_types.h"
|
|
#include "cellular_api.h"
|
|
#include "cellular_common_api.h"
|
|
#include "cellular_common.h"
|
|
#include "cellular_at_core.h"
|
|
|
|
/* Cellular module incliudes. */
|
|
#include "cellular_r4.h"
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* TODO : confirm the value. */
|
|
#define PDN_ACT_PACKET_REQ_TIMEOUT_MS ( 150000UL )
|
|
|
|
#define PDN_DEACT_PACKET_REQ_TIMEOUT_MS ( 40000UL )
|
|
|
|
#define GPRS_ATTACH_REQ_TIMEOUT_MS ( 180000UL )
|
|
|
|
#define DNS_QUERY_REQ_TIMEOUT_MS ( 120000UL )
|
|
|
|
#define SOCKET_CLOSE_PACKET_REQ_TIMEOUT_MS ( 120000U )
|
|
|
|
#define SOCKET_CONNECT_PACKET_REQ_TIMEOUT_MS ( 120000U )
|
|
|
|
#define CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ( 32U )
|
|
|
|
#define DATA_SEND_TIMEOUT_MS ( 10000U )
|
|
|
|
#define PACKET_REQ_TIMEOUT_MS ( 10000U )
|
|
|
|
#define DATA_READ_TIMEOUT_MS ( 50000UL )
|
|
|
|
#define SOCKET_DATA_PREFIX_TOKEN "+USORD: "
|
|
#define SOCKET_DATA_PREFIX_TOKEN_LEN ( 8U )
|
|
#define SOCKET_DATA_PREFIX_STRING_LENGTH ( SOCKET_DATA_PREFIX_TOKEN_LEN + 9U )
|
|
#define RAT_PRIOIRTY_LIST_LENGTH ( 3U )
|
|
|
|
/**
|
|
* @brief Parameters involved in receiving data through sockets
|
|
*/
|
|
typedef struct _socketDataRecv
|
|
{
|
|
uint32_t * pDataLen;
|
|
uint8_t * pData;
|
|
} _socketDataRecv_t;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t socketRecvDataPrefix( void * pCallbackContext,
|
|
char * pLine,
|
|
uint32_t lineLength,
|
|
char ** ppDataStart,
|
|
uint32_t * pDataLength );
|
|
static CellularATError_t getDataFromResp( const CellularATCommandResponse_t * pAtResp,
|
|
const _socketDataRecv_t * pDataRecv,
|
|
uint32_t outBufSize );
|
|
static CellularPktStatus_t _Cellular_RecvFuncData( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularError_t storeAccessModeAndAddress( CellularContext_t * pContext,
|
|
CellularSocketHandle_t socketHandle,
|
|
CellularSocketAccessMode_t dataAccessMode,
|
|
const CellularSocketAddress_t * pRemoteSocketAddress );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSocketId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularError_t _Cellular_GetSocketNumber( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle,
|
|
uint8_t * pSessionId );
|
|
|
|
CellularError_t Cellular_SetPdnConfig( CellularHandle_t cellularHandle,
|
|
uint8_t contextId,
|
|
const CellularPdnConfig_t * pPdnConfig );
|
|
|
|
static CellularError_t _Cellular_GetPacketSwitchStatus( CellularHandle_t cellularHandle,
|
|
bool * pPacketSwitchStatus );
|
|
|
|
static CellularError_t _Cellular_GetContextActivationStatus( CellularHandle_t cellularHandle,
|
|
CellularPdnContextActInfo_t * pPdpContextsActInfo );
|
|
|
|
static bool _parseExtendedSignalQuality( char * pQcsqPayload,
|
|
CellularSignalInfo_t * pSignalInfo );
|
|
static bool _parseSignalQuality( char * pQcsqPayload,
|
|
CellularSignalInfo_t * pSignalInfo );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSignalInfo( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularError_t controlSignalStrengthIndication( CellularContext_t * pContext,
|
|
bool enable );
|
|
|
|
CellularError_t Cellular_SetPsmSettings( CellularHandle_t cellularHandle,
|
|
const CellularPsmSettings_t * pPsmSettings );
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t socketRecvDataPrefix( void * pCallbackContext,
|
|
char * pLine,
|
|
uint32_t lineLength,
|
|
char ** ppDataStart,
|
|
uint32_t * pDataLength )
|
|
{
|
|
char * pToken = NULL;
|
|
int32_t tempValue = 0;
|
|
CellularATError_t atResult = CELLULAR_AT_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char pLocalLine[ SOCKET_DATA_PREFIX_STRING_LENGTH + 1 ] = { '\0' };
|
|
char * pDataStart = pLocalLine;
|
|
|
|
( void ) lineLength;
|
|
|
|
/* pCallbackContext is not used in this function. It should be NULL. */
|
|
if( ( pLine == NULL ) || ( ppDataStart == NULL ) || ( pDataLength == NULL ) || ( pCallbackContext != NULL ) )
|
|
{
|
|
LogError( ( "socketRecvData: Bad parameters" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( strncmp( pLine, SOCKET_DATA_PREFIX_TOKEN, SOCKET_DATA_PREFIX_TOKEN_LEN ) != 0 )
|
|
{
|
|
/* Prefix string which is not SOCKET_DATA_PREFIX_TOKEN does't indicate data start.
|
|
* Set data length to 0.*/
|
|
*ppDataStart = NULL;
|
|
*pDataLength = 0;
|
|
}
|
|
else
|
|
{
|
|
/* The string length of "+USORD: <socket>[,<length>],"<data in text mode>". */
|
|
strncpy( pLocalLine, pLine, SOCKET_DATA_PREFIX_STRING_LENGTH );
|
|
pDataStart = &pLocalLine[ SOCKET_DATA_PREFIX_TOKEN_LEN ];
|
|
|
|
/* Skip the socket number. */
|
|
atResult = Cellular_ATGetNextTok( &pDataStart, &pToken );
|
|
|
|
/* Parse the receive data length. */
|
|
if( ( atResult == CELLULAR_AT_SUCCESS ) && ( pDataStart[ 0 ] == '"' ) )
|
|
{
|
|
/* Peek the next symbol. If it is \", then length is ommited. Received byte is 0. */
|
|
LogDebug( ( "socketRecvData: 0 received bytes." ) );
|
|
*pDataLength = 0U;
|
|
*ppDataStart = NULL;
|
|
}
|
|
else if( atResult == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Parse the length. */
|
|
atResult = Cellular_ATGetNextTok( &pDataStart, &pToken );
|
|
|
|
if( atResult == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atResult = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( ( tempValue < 0 ) && ( ( uint32_t ) tempValue > CELLULAR_MAX_RECV_DATA_LEN ) )
|
|
{
|
|
LogError( ( "socketRecvData: Bad parameters" ) );
|
|
atResult = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atResult == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Change +USROD: <socket>,<length>," to +USROD: <socket>,<length>,\r. */
|
|
pDataStart = &pLine[ pDataStart - pLocalLine ];
|
|
|
|
if( pDataStart[ 0 ] == '\"' )
|
|
{
|
|
*pDataStart = '\r';
|
|
*ppDataStart = ( char * ) &pDataStart[ 1 ];
|
|
*pDataLength = ( uint32_t ) tempValue;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "socketRecvDataPrefix : pLine [%s] with lineLength [%d] is not data prefix", pLine, lineLength ) );
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t getDataFromResp( const CellularATCommandResponse_t * pAtResp,
|
|
const _socketDataRecv_t * pDataRecv,
|
|
uint32_t outBufSize )
|
|
{
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
const char * pInputLine = NULL;
|
|
uint32_t dataLenToCopy = 0;
|
|
|
|
/* Check if the received data size is greater than the output buffer size. */
|
|
if( *pDataRecv->pDataLen > outBufSize )
|
|
{
|
|
LogError( ( "Data is turncated, received data length %u, out buffer size %u",
|
|
*pDataRecv->pDataLen, outBufSize ) );
|
|
dataLenToCopy = outBufSize;
|
|
*pDataRecv->pDataLen = outBufSize;
|
|
}
|
|
else
|
|
{
|
|
dataLenToCopy = *pDataRecv->pDataLen;
|
|
}
|
|
|
|
/* Data is stored in the next intermediate response. */
|
|
if( pAtResp->pItm->pNext != NULL )
|
|
{
|
|
pInputLine = pAtResp->pItm->pNext->pLine;
|
|
|
|
if( ( pInputLine != NULL ) && ( dataLenToCopy > 0U ) )
|
|
{
|
|
/* Copy the data to the out buffer. */
|
|
( void ) memcpy( ( void * ) pDataRecv->pData, ( const void * ) pInputLine, dataLenToCopy );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Receive Data: paramerter error, data pointer %p, data to copy %u",
|
|
pInputLine, dataLenToCopy ) );
|
|
atCoreStatus = CELLULAR_AT_BAD_PARAMETER;
|
|
}
|
|
}
|
|
else if( *pDataRecv->pDataLen == 0U )
|
|
{
|
|
/* Receive command success but no data. */
|
|
LogDebug( ( "Receive Data: no data" ) );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Receive Data: Intermediate response empty" ) );
|
|
atCoreStatus = CELLULAR_AT_BAD_PARAMETER;
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library types. */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
static CellularPktStatus_t _Cellular_RecvFuncData( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char * pInputLine = NULL, * pToken = NULL;
|
|
const _socketDataRecv_t * pDataRecv = ( _socketDataRecv_t * ) pData;
|
|
int32_t tempValue = 0;
|
|
|
|
( void ) dataLen;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "Receive Data: invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "Receive Data: response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pDataRecv == NULL ) || ( pDataRecv->pData == NULL ) || ( pDataRecv->pDataLen == NULL ) )
|
|
{
|
|
LogError( ( "Receive Data: Bad parameters" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine; /* The first item is the data prefix. */
|
|
|
|
/* Check the data prefix token "+USORD: ". */
|
|
if( strncmp( pInputLine, SOCKET_DATA_PREFIX_TOKEN, SOCKET_DATA_PREFIX_TOKEN_LEN ) != 0 )
|
|
{
|
|
LogError( ( "response item error in prefix CONNECT" ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( pAtResp->pItm->pNext == NULL )
|
|
{
|
|
/* No data response. */
|
|
*pDataRecv->pDataLen = 0;
|
|
}
|
|
else
|
|
{
|
|
/* Parse the data length. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( tempValue >= 0 )
|
|
{
|
|
*pDataRecv->pDataLen = ( uint32_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Process the data buffer. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = getDataFromResp( pAtResp, pDataRecv, *pDataRecv->pDataLen );
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t storeAccessModeAndAddress( CellularContext_t * pContext,
|
|
CellularSocketHandle_t socketHandle,
|
|
CellularSocketAccessMode_t dataAccessMode,
|
|
const CellularSocketAddress_t * pRemoteSocketAddress )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
else if( ( pRemoteSocketAddress == NULL ) || ( socketHandle == NULL ) )
|
|
{
|
|
LogDebug( ( "storeAccessModeAndAddress: Invalid socket address" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else if( socketHandle->socketState != SOCKETSTATE_ALLOCATED )
|
|
{
|
|
LogError( ( "storeAccessModeAndAddress, bad socket state %d",
|
|
socketHandle->socketState ) );
|
|
cellularStatus = CELLULAR_INTERNAL_FAILURE;
|
|
}
|
|
else if( dataAccessMode != CELLULAR_ACCESSMODE_BUFFER )
|
|
{
|
|
LogError( ( "storeAccessModeAndAddress, Access mode not supported %d",
|
|
dataAccessMode ) );
|
|
cellularStatus = CELLULAR_UNSUPPORTED;
|
|
}
|
|
else
|
|
{
|
|
socketHandle->remoteSocketAddress.port = pRemoteSocketAddress->port;
|
|
socketHandle->dataMode = dataAccessMode;
|
|
socketHandle->remoteSocketAddress.ipAddress.ipAddressType =
|
|
pRemoteSocketAddress->ipAddress.ipAddressType;
|
|
( void ) strncpy( socketHandle->remoteSocketAddress.ipAddress.ipAddress,
|
|
pRemoteSocketAddress->ipAddress.ipAddress,
|
|
CELLULAR_IP_ADDRESS_MAX_SIZE + 1U );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library types. */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSocketId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pInputLine = NULL;
|
|
uint8_t * pSessionId = pData;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
int32_t tempValue = 0;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetSocketId: Invalid handle" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pSessionId == NULL ) || ( dataLen != sizeof( uint8_t ) ) )
|
|
{
|
|
LogError( ( "GetSocketId: Bad parameters" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetSocketId: Input Line passed is NULL" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pInputLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pInputLine, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= MIN_TCP_SESSION_ID ) && ( tempValue <= MAX_TCP_SESSION_ID ) )
|
|
{
|
|
*pSessionId = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t _Cellular_GetSocketNumber( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle,
|
|
uint8_t * pSessionId )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqSocketConnect =
|
|
{
|
|
"AT+USOCR=6,0",
|
|
CELLULAR_AT_WITH_PREFIX,
|
|
"+USOCR",
|
|
_Cellular_RecvFuncGetSocketId,
|
|
NULL,
|
|
sizeof( uint8_t ),
|
|
};
|
|
|
|
( void ) socketHandle;
|
|
|
|
atReqSocketConnect.pData = pSessionId;
|
|
|
|
/* Internal function. Caller checks parameters. */
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSocketConnect );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_GetSocketNumber: get socekt number failed PktRet: %d", pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
CellularError_t Cellular_SocketRecv( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle,
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
uint8_t * pBuffer,
|
|
uint32_t bufferLength,
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
uint32_t * pReceivedDataLength )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
|
|
uint32_t recvTimeout = DATA_READ_TIMEOUT_MS;
|
|
uint32_t recvLen = bufferLength;
|
|
_socketDataRecv_t dataRecv = { 0 };
|
|
CellularAtReq_t atReqSocketRecv =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_MULTI_DATA_WO_PREFIX,
|
|
"+USORD",
|
|
_Cellular_RecvFuncData,
|
|
NULL,
|
|
0,
|
|
};
|
|
uint32_t sessionId = 0;
|
|
|
|
dataRecv.pDataLen = pReceivedDataLength;
|
|
dataRecv.pData = pBuffer;
|
|
|
|
atReqSocketRecv.pAtCmd = cmdBuf;
|
|
atReqSocketRecv.pData = ( void * ) &dataRecv;
|
|
atReqSocketRecv.dataLen = bufferLength;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_SocketRecv: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( socketHandle == NULL )
|
|
{
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
else if( ( pBuffer == NULL ) || ( pReceivedDataLength == NULL ) || ( bufferLength == 0U ) )
|
|
{
|
|
LogDebug( ( "Cellular_SocketRecv: Bad input Param" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
sessionId = _Cellular_GetSessionId( pContext, socketHandle->socketId );
|
|
|
|
if( sessionId == INVALID_SESSION_ID )
|
|
{
|
|
LogError( ( "Cellular_SocketRecv : invalid session ID for socket index %u",
|
|
socketHandle->socketId ) );
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Update recvLen to maximum module length. */
|
|
if( CELLULAR_MAX_RECV_DATA_LEN <= bufferLength )
|
|
{
|
|
recvLen = ( uint32_t ) CELLULAR_MAX_RECV_DATA_LEN;
|
|
}
|
|
|
|
/* Update receive timeout to default timeout if not set with setsocketopt. */
|
|
if( recvLen > 0 )
|
|
{
|
|
if( socketHandle->recvTimeoutMs != 0U )
|
|
{
|
|
recvTimeout = socketHandle->recvTimeoutMs;
|
|
}
|
|
|
|
/* 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]. */
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE,
|
|
"%s%u,%u", "AT+USORD=", sessionId, recvLen );
|
|
pktStatus = _Cellular_TimeoutAtcmdDataRecvRequestWithCallback( pContext,
|
|
atReqSocketRecv,
|
|
recvTimeout,
|
|
socketRecvDataPrefix,
|
|
NULL );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* Reset data handling parameters. */
|
|
LogError( ( "Cellular_SocketRecv: Data Receive fail, pktStatus: %d", pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t socketSendDataPrefix( void * pCallbackContext,
|
|
char * pLine,
|
|
uint32_t * pBytesRead )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
|
|
if( ( pLine == NULL ) || ( pBytesRead == NULL ) )
|
|
{
|
|
LogError( ( "socketSendDataPrefix: pLine is invalid or pBytesRead is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( pCallbackContext != NULL )
|
|
{
|
|
LogError( ( "socketSendDataPrefix: pCallbackContext is not NULL" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( *pBytesRead != 1U )
|
|
{
|
|
LogDebug( ( "socketSendDataPrefix: pBytesRead %u %s is not 1", *pBytesRead, pLine ) );
|
|
}
|
|
else
|
|
{
|
|
/* After the data prefix, there should not be any data in stream.
|
|
* Cellular commmon processes AT command in lines. Add a '\0' after '@'. */
|
|
if( strcmp( pLine, "@" ) == 0 )
|
|
{
|
|
pLine[ 1 ] = '\n';
|
|
*pBytesRead = 2;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
CellularError_t Cellular_SocketSend( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle,
|
|
const uint8_t * pData,
|
|
uint32_t dataLength,
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
uint32_t * pSentDataLength )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
uint32_t sendTimeout = DATA_SEND_TIMEOUT_MS;
|
|
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
|
|
CellularAtReq_t atReqSocketSend = { 0 };
|
|
CellularAtDataReq_t atDataReqSocketSend = { 0 };
|
|
uint32_t sessionId = 0;
|
|
|
|
atReqSocketSend.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReqSocketSend.pAtCmd = cmdBuf;
|
|
|
|
atDataReqSocketSend.pData = pData;
|
|
atDataReqSocketSend.dataLen = dataLength;
|
|
atDataReqSocketSend.pSentDataLength = pSentDataLength;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_SocketSend: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( socketHandle == NULL )
|
|
{
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
else if( ( pData == NULL ) || ( pSentDataLength == NULL ) || ( dataLength == 0U ) )
|
|
{
|
|
LogDebug( ( "Cellular_SocketSend: Invalid parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else if( socketHandle->socketState != SOCKETSTATE_CONNECTED )
|
|
{
|
|
/* Check the socket connection state. */
|
|
if( ( socketHandle->socketState == SOCKETSTATE_ALLOCATED ) || ( socketHandle->socketState == SOCKETSTATE_CONNECTING ) )
|
|
{
|
|
cellularStatus = CELLULAR_SOCKET_NOT_CONNECTED;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = CELLULAR_SOCKET_CLOSED;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
sessionId = _Cellular_GetSessionId( pContext, socketHandle->socketId );
|
|
|
|
if( sessionId == INVALID_SESSION_ID )
|
|
{
|
|
LogError( ( "Cellular_SocketSend : invalid session ID for socket index %u",
|
|
socketHandle->socketId ) );
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Send data length check. */
|
|
if( dataLength > ( uint32_t ) CELLULAR_MAX_SEND_DATA_LEN )
|
|
{
|
|
atDataReqSocketSend.dataLen = ( uint32_t ) CELLULAR_MAX_SEND_DATA_LEN;
|
|
}
|
|
|
|
/* Check send timeout. If not set by setsockopt, use default value. */
|
|
if( socketHandle->sendTimeoutMs != 0U )
|
|
{
|
|
sendTimeout = socketHandle->sendTimeoutMs;
|
|
}
|
|
|
|
/* 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]. */
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "%s%u,%u",
|
|
"AT+USOWR=", sessionId, atDataReqSocketSend.dataLen );
|
|
|
|
pktStatus = _Cellular_AtcmdDataSend( pContext, atReqSocketSend, atDataReqSocketSend,
|
|
socketSendDataPrefix, NULL,
|
|
PACKET_REQ_TIMEOUT_MS, sendTimeout, 200U );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
if( socketHandle->socketState == SOCKETSTATE_DISCONNECTED )
|
|
{
|
|
LogInfo( ( "Cellular_SocketSend: Data send fail, socket already closed" ) );
|
|
cellularStatus = CELLULAR_SOCKET_CLOSED;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Cellular_SocketSend: Data send fail, PktRet: %d", pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SocketClose( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
|
|
CellularAtReq_t atReqSocketClose =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
uint32_t sessionId = INVALID_SESSION_ID;
|
|
cellularModuleContext_t * pModuleContext = NULL;
|
|
|
|
atReqSocketClose.pAtCmd = cmdBuf;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_SocketClose: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( socketHandle == NULL )
|
|
{
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = _Cellular_GetModuleContext( pContext, ( void ** ) &pModuleContext );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
sessionId = _Cellular_GetSessionId( pContext, socketHandle->socketId );
|
|
|
|
if( sessionId == INVALID_SESSION_ID )
|
|
{
|
|
LogError( ( "Cellular_SocketClose : invalid session ID for socket index %u",
|
|
socketHandle->socketId ) );
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Remove the mapping. */
|
|
pModuleContext->pSessionMap[ sessionId ] = INVALID_SOCKET_INDEX;
|
|
|
|
/* Close the socket. */
|
|
if( socketHandle->socketState == SOCKETSTATE_CONNECTED )
|
|
{
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "%s%u,%d",
|
|
"AT+USOCL=", sessionId, CELLULAR_CONFIG_SET_SOCKET_CLOSE_ASYNC_MODE );
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketClose, SOCKET_CLOSE_PACKET_REQ_TIMEOUT_MS );
|
|
|
|
/* Delete the socket config. */
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogWarn( ( "Cellular_SocketClose: AT+USOCL fail, PktRet: %d", pktStatus ) );
|
|
}
|
|
}
|
|
|
|
/* Ignore the result from the info, and force to remove the socket. */
|
|
cellularStatus = _Cellular_RemoveSocketData( pContext, socketHandle );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SocketConnect( CellularHandle_t cellularHandle,
|
|
CellularSocketHandle_t socketHandle,
|
|
CellularSocketAccessMode_t dataAccessMode,
|
|
const CellularSocketAddress_t * pRemoteSocketAddress )
|
|
{
|
|
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' };
|
|
uint8_t sessionId = 0;
|
|
CellularAtReq_t atReqSocketConnect =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
cellularModuleContext_t * pModuleContext = NULL;
|
|
|
|
atReqSocketConnect.pAtCmd = cmdBuf;
|
|
|
|
/* Make sure the library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_SocketConnect: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pRemoteSocketAddress == NULL )
|
|
{
|
|
LogDebug( ( "Cellular_SocketConnect: Invalid socket address" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else if( socketHandle == NULL )
|
|
{
|
|
LogDebug( ( "Cellular_SocketConnect: Invalid socket handle" ) );
|
|
cellularStatus = CELLULAR_INVALID_HANDLE;
|
|
}
|
|
else if( socketHandle->socketProtocol != CELLULAR_SOCKET_PROTOCOL_TCP )
|
|
{
|
|
LogDebug( ( "Cellular_SocketConnect: Invalid socket protocol" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = storeAccessModeAndAddress( pContext, socketHandle, dataAccessMode, pRemoteSocketAddress );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
cellularStatus = _Cellular_GetModuleContext( pContext, ( void ** ) &pModuleContext );
|
|
}
|
|
|
|
/* Set socket config and get session id. The session id is defined by the modem. */
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Builds the Socket connect command. */
|
|
cellularStatus = _Cellular_GetSocketNumber( pContext, socketHandle, &sessionId );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Create the reverse table to store the socketIndex to sessionId. */
|
|
pModuleContext->pSessionMap[ sessionId ] = socketHandle->socketId;
|
|
}
|
|
}
|
|
|
|
/* Start the tcp connection. */
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* 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]. */
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE,
|
|
"AT+USOCO=%u,\"%s\",%d,1",
|
|
sessionId,
|
|
socketHandle->remoteSocketAddress.ipAddress.ipAddress,
|
|
socketHandle->remoteSocketAddress.port );
|
|
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketConnect,
|
|
SOCKET_CONNECT_PACKET_REQ_TIMEOUT_MS );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_SocketConnect: Socket connect failed, cmdBuf:%s, PktRet: %d", cmdBuf, pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else
|
|
{
|
|
socketHandle->socketState = SOCKETSTATE_CONNECTING;
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_GetSimCardStatus( CellularHandle_t cellularHandle,
|
|
CellularSimCardStatus_t * pSimCardStatus )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_GetSimCardStatus: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pSimCardStatus == NULL )
|
|
{
|
|
LogWarn( ( "Cellular_GetSimCardStatus: Bad input Parameter " ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* Parameters are checked in this API. */
|
|
pSimCardStatus->simCardState = CELLULAR_SIM_CARD_UNKNOWN;
|
|
pSimCardStatus->simCardLockState = CELLULAR_SIM_CARD_LOCK_UNKNOWN;
|
|
|
|
cellularStatus = Cellular_CommonGetSimCardLockStatus( cellularHandle, pSimCardStatus );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
if( ( pSimCardStatus->simCardLockState != CELLULAR_SIM_CARD_INVALID ) &&
|
|
( pSimCardStatus->simCardLockState != CELLULAR_SIM_CARD_LOCK_UNKNOWN ) )
|
|
{
|
|
pSimCardStatus->simCardState = CELLULAR_SIM_CARD_INSERTED;
|
|
}
|
|
else
|
|
{
|
|
pSimCardStatus->simCardState = CELLULAR_SIM_CARD_UNKNOWN;
|
|
}
|
|
|
|
LogInfo( ( "Cellular_GetSimCardStatus, Sim Insert State[%d], Lock State[%d]",
|
|
pSimCardStatus->simCardState, pSimCardStatus->simCardLockState ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_DeactivatePdn( CellularHandle_t cellularHandle,
|
|
uint8_t contextId )
|
|
{
|
|
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' };
|
|
bool packetSwitchStatus = false;
|
|
uint32_t i = 0;
|
|
|
|
CellularServiceStatus_t serviceStatus = { 0 };
|
|
CellularPdnContextActInfo_t pdpContextsActInfo = { 0 };
|
|
|
|
CellularAtReq_t atReqDeactPdn =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
|
|
atReqDeactPdn.pAtCmd = cmdBuf;
|
|
|
|
cellularStatus = _Cellular_IsValidPdn( contextId );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Make sure the library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Get current network operator settings. */
|
|
cellularStatus = Cellular_CommonGetServiceStatus( cellularHandle, &serviceStatus );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Check the current <Act> status of context. */
|
|
cellularStatus = _Cellular_GetContextActivationStatus( cellularHandle, &pdpContextsActInfo );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_DeactivatePdn: Listing operator and context details below." ) );
|
|
|
|
for( i = 0U; i < ( MAX_PDP_CONTEXTS - 1 ); i++ )
|
|
{
|
|
/* Print only those contexts that are present in +CGACT response */
|
|
if( pdpContextsActInfo.contextsPresent[ i ] )
|
|
{
|
|
LogDebug( ( "Context [%d], Act State [%d], Operator <Act> [%d]\r\n", i + 1,
|
|
pdpContextsActInfo.contextActState[ i ], serviceStatus.rat ) );
|
|
}
|
|
}
|
|
|
|
/* Deactivate context if active */
|
|
if( pdpContextsActInfo.contextActState[ contextId - 1 ] == true )
|
|
{
|
|
/* Don't deactivate LTE default bearer context */
|
|
/* Otherwise sending AT command "+CGACT=0,1" for deactivation will result in ERROR */
|
|
if( ( serviceStatus.rat >= CELLULAR_RAT_LTE ) && ( contextId == DEFAULT_BEARER_CONTEXT_ID ) )
|
|
{
|
|
LogInfo( ( "Cellular_DeactivatePdn: Default Bearer context %d Active. Not allowed to deactivate.", contextId ) );
|
|
cellularStatus = CELLULAR_NOT_ALLOWED;
|
|
}
|
|
else
|
|
{
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s=0,%u", "AT+CGACT", contextId );
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqDeactPdn, PDN_DEACT_PACKET_REQ_TIMEOUT_MS );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
|
|
if( ( cellularStatus != CELLULAR_SUCCESS ) && ( cellularStatus != CELLULAR_NOT_ALLOWED ) )
|
|
{
|
|
LogError( ( "Cellular_DeactivatePdn: can't deactivate PDN, PktRet: %d", pktStatus ) );
|
|
|
|
/* Sometimes +CGACT deactivation fails in 2G. Then check packet switch attach. If attached, detach packet switch. */
|
|
if( ( serviceStatus.rat == CELLULAR_RAT_GSM ) || ( serviceStatus.rat == CELLULAR_RAT_EDGE ) )
|
|
{
|
|
cellularStatus = _Cellular_GetPacketSwitchStatus( cellularHandle, &packetSwitchStatus );
|
|
|
|
if( ( cellularStatus == CELLULAR_SUCCESS ) && ( packetSwitchStatus == true ) )
|
|
{
|
|
LogError( ( "Deactivate Packet switch" ) );
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s", "AT+CGATT=0" );
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqDeactPdn, GPRS_ATTACH_REQ_TIMEOUT_MS );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "Packet switch query failed" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else
|
|
{
|
|
LogInfo( ( "Packet switch detached" ) );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogInfo( ( "Cellular_DeactivatePdn: Context id [%d] is already deactive", contextId ) );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Cellular_DeactivatePdn: Unable to list operator and context details." ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library prototype. */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
static CellularPktStatus_t _Cellular_RecvFuncPacketSwitchStatus( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pInputLine = NULL;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
bool * pPacketSwitchStatus = ( bool * ) pData;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "PacketSwitchStatus: Invalid handle" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( bool ) ) )
|
|
{
|
|
LogError( ( "GetPacketSwitchStatus: Invalid param" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetPacketSwitchStatus: Input Line passed is NULL" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
|
|
/* Remove prefix. */
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
/* Remove leading space. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pInputLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( *pInputLine == '0' )
|
|
{
|
|
*pPacketSwitchStatus = false;
|
|
}
|
|
else if( *pInputLine == '1' )
|
|
{
|
|
*pPacketSwitchStatus = true;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Get PDN context Activation state */
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetPdpContextActState( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pRespLine = NULL;
|
|
CellularPdnContextActInfo_t * pPDPContextsActInfo = ( CellularPdnContextActInfo_t * ) pData;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
const CellularATCommandLine_t * pCommnadItem = NULL;
|
|
uint8_t tokenIndex = 0;
|
|
uint8_t contextId = 0;
|
|
int32_t tempValue = 0;
|
|
char * pToken = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextActState: invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pPDPContextsActInfo == NULL ) || ( dataLen != sizeof( CellularPdnContextActInfo_t ) ) )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( pAtResp == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextActState: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextActState: no PDN context available" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
|
|
pCommnadItem = pAtResp->pItm;
|
|
|
|
while( pCommnadItem != NULL )
|
|
{
|
|
pRespLine = pCommnadItem->pLine;
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextActState: pRespLine [%s]", pRespLine ) );
|
|
|
|
/* Removing all the Spaces in the AT Response. */
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pRespLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
tokenIndex = 0;
|
|
|
|
while( ( pToken != NULL ) && ( atCoreStatus == CELLULAR_AT_SUCCESS ) )
|
|
{
|
|
switch( tokenIndex )
|
|
{
|
|
case ( CELLULAR_PDN_ACT_STATUS_POS_CONTEXT_ID ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextActState: Context Id pToken: %s", pToken ) );
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= ( int32_t ) CELLULAR_PDN_CONTEXT_ID_MIN ) &&
|
|
( tempValue <= ( int32_t ) MAX_PDP_CONTEXTS ) )
|
|
{
|
|
contextId = ( uint8_t ) tempValue;
|
|
pPDPContextsActInfo->contextsPresent[ contextId - 1 ] = true;
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextActState: Context Id: %d", contextId ) );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextActState: Invalid Context Id. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ( CELLULAR_PDN_ACT_STATUS_POS_CONTEXT_STATE ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextActState: Context <Act> pToken: %s", pToken ) );
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
pPDPContextsActInfo->contextActState[ contextId - 1 ] = ( bool ) tempValue;
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextActState: Context <Act>: %d", pPDPContextsActInfo->contextActState[ contextId - 1 ] ) );
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
tokenIndex++;
|
|
|
|
if( Cellular_ATGetNextTok( &pRespLine, &pToken ) != CELLULAR_AT_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextActState: parse %s failed", pRespLine ) );
|
|
break;
|
|
}
|
|
|
|
pCommnadItem = pCommnadItem->pNext;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Check activation status of particular context. */
|
|
|
|
static CellularError_t _Cellular_GetContextActivationStatus( CellularHandle_t cellularHandle,
|
|
CellularPdnContextActInfo_t * pPdpContextsActInfo )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
|
|
CellularAtReq_t atReqPacketSwitchStatus =
|
|
{
|
|
"AT+CGACT?",
|
|
CELLULAR_AT_MULTI_WITH_PREFIX,
|
|
"+CGACT",
|
|
_Cellular_RecvFuncGetPdpContextActState,
|
|
NULL,
|
|
sizeof( CellularPdnContextActInfo_t ),
|
|
};
|
|
|
|
atReqPacketSwitchStatus.pData = pPdpContextsActInfo;
|
|
|
|
/* Internal function. Callee check parameters. */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqPacketSwitchStatus );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t _Cellular_GetPacketSwitchStatus( CellularHandle_t cellularHandle,
|
|
bool * pPacketSwitchStatus )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqPacketSwitchStatus =
|
|
{
|
|
"AT+CGATT?",
|
|
CELLULAR_AT_WITH_PREFIX,
|
|
"+CGATT",
|
|
_Cellular_RecvFuncPacketSwitchStatus,
|
|
NULL,
|
|
sizeof( bool ),
|
|
};
|
|
|
|
atReqPacketSwitchStatus.pData = pPacketSwitchStatus;
|
|
|
|
/* Internal function. Callee check parameters. */
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqPacketSwitchStatus, PDN_ACT_PACKET_REQ_TIMEOUT_MS );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_ActivatePdn( CellularHandle_t cellularHandle,
|
|
uint8_t contextId )
|
|
{
|
|
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' };
|
|
uint32_t i = 0;
|
|
|
|
CellularPdnContextActInfo_t pdpContextsActInfo = { 0 };
|
|
|
|
CellularAtReq_t atReqActPdn =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
|
|
cellularStatus = _Cellular_IsValidPdn( contextId );
|
|
|
|
atReqActPdn.pAtCmd = cmdBuf;
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Make sure the library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Check the current <Act> status of context. If not activated, activate the PDN context ID. */
|
|
cellularStatus = _Cellular_GetContextActivationStatus( cellularHandle, &pdpContextsActInfo );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_ActivatePdn: Listing operator and context details below." ) );
|
|
|
|
for( i = 0U; i < ( MAX_PDP_CONTEXTS - 1 ); i++ )
|
|
{
|
|
/* Print only those contexts that are present in +CGACT response */
|
|
if( pdpContextsActInfo.contextsPresent[ i ] )
|
|
{
|
|
LogDebug( ( "Cellular_ActivatePdn: Context [%d], Act State [%d]\r\n", i + 1,
|
|
pdpContextsActInfo.contextActState[ i ] ) );
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Activate context if not already active */
|
|
if( pdpContextsActInfo.contextActState[ contextId - 1 ] == false )
|
|
{
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s=1,%u", "AT+CGACT", contextId );
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqActPdn, PDN_ACT_PACKET_REQ_TIMEOUT_MS );
|
|
}
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_ActivatePdn: can't activate PDN, PktRet: %d", pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogInfo( ( "Cellular_ActivatePdn: Context id [%d] is already active", contextId ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
CellularError_t Cellular_GetPdnStatus( CellularHandle_t cellularHandle,
|
|
CellularPdnStatus_t * pPdnStatusBuffers,
|
|
uint8_t numStatusBuffers,
|
|
uint8_t * pNumStatus )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
uint32_t i = 0;
|
|
|
|
CellularPdnContextActInfo_t pdpContextsActInfo = { 0 };
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Make sure the library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
}
|
|
|
|
if( ( pPdnStatusBuffers == NULL ) || ( pNumStatus == NULL ) || ( numStatusBuffers < 1u ) )
|
|
{
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
LogWarn( ( "_Cellular_GetPdnStatus: Bad input Parameter " ) );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Check the current <Act> status of contexts. */
|
|
cellularStatus = _Cellular_GetContextActivationStatus( cellularHandle, &pdpContextsActInfo );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_GetPdnStatus: Listing operator and context details below." ) );
|
|
|
|
for( i = 0U; i < ( MAX_PDP_CONTEXTS - 1 ); i++ )
|
|
{
|
|
/* Print only those contexts that are present in +CGACT response */
|
|
if( pdpContextsActInfo.contextsPresent[ i ] )
|
|
{
|
|
LogDebug( ( "Context [%d], Act State [%d]\r\n", i + 1, pdpContextsActInfo.contextActState[ i ] ) );
|
|
}
|
|
}
|
|
|
|
/* TODO: Currently only one context state can be saved in PdnStatusBuffers. */
|
|
pPdnStatusBuffers->state = pdpContextsActInfo.contextActState[ 0 ];
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SetRatPriority( CellularHandle_t cellularHandle,
|
|
const CellularRat_t * pRatPriorities,
|
|
uint8_t ratPrioritiesLength )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
uint8_t i = 0;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char cmdBuf[ CELLULAR_AT_CMD_MAX_SIZE ] = { '\0' };
|
|
|
|
CellularAtReq_t atReqSetRatPriority =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
atReqSetRatPriority.pAtCmd = cmdBuf;
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_SetRatPriority: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( ( pRatPriorities == NULL ) || ( ratPrioritiesLength == 0U ) ||
|
|
( ratPrioritiesLength > ( uint8_t ) CELLULAR_MAX_RAT_PRIORITY_COUNT ) )
|
|
{
|
|
LogWarn( ( "Cellular_SetRatPriority: Bad input Parameter " ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* In case of +UMNOPROF=0, AT+URAT set commad is not allowed */
|
|
if( CELLULAR_CONFIG_SARA_R4_SET_MNO_PROFILE != 0 )
|
|
{
|
|
( void ) strcpy( cmdBuf, "AT+CFUN=4;+URAT=" );
|
|
|
|
while( i < ratPrioritiesLength )
|
|
{
|
|
if( ( pRatPriorities[ i ] == CELLULAR_RAT_GSM ) || ( pRatPriorities[ i ] == CELLULAR_RAT_EDGE ) )
|
|
{
|
|
( void ) strcat( cmdBuf, "9" );
|
|
}
|
|
else if( pRatPriorities[ i ] == CELLULAR_RAT_CATM1 )
|
|
{
|
|
( void ) strcat( cmdBuf, "7" );
|
|
}
|
|
else if( pRatPriorities[ i ] == CELLULAR_RAT_NBIOT )
|
|
{
|
|
( void ) strcat( cmdBuf, "8" );
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
i++;
|
|
|
|
if( i < ratPrioritiesLength )
|
|
{
|
|
( void ) strcat( cmdBuf, "," );
|
|
}
|
|
}
|
|
|
|
( void ) strcat( cmdBuf, ";+CFUN=1" );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetRatPriority );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "Cellular_SetRatPriority: Automatic selection as UMNOPROF profile is 0" ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Get modem RAT priority setting. */
|
|
/* coverity[misra_c_2012_rule_8_13_violation] */
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetRatPriority( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pInputLine = NULL, * pToken = NULL;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularRat_t * pRatPriorities = NULL;
|
|
uint8_t ratIndex = 0;
|
|
uint32_t maxRatPriorityLength = ( dataLen > RAT_PRIOIRTY_LIST_LENGTH ? RAT_PRIOIRTY_LIST_LENGTH : dataLen );
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetRatPriority: Invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) ||
|
|
( pAtResp->pItm->pLine == NULL ) || ( pData == NULL ) || ( dataLen == 0U ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetRatPriority: Invalid param" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
pRatPriorities = ( CellularRat_t * ) pData;
|
|
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pInputLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
memset( pRatPriorities, CELLULAR_RAT_INVALID, dataLen );
|
|
|
|
/* pInputLine : 7,8,9. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
while( pToken != NULL && ratIndex < maxRatPriorityLength )
|
|
{
|
|
LogDebug( ( "_Cellular_RecvFuncGetRatPriority: pToken [%s]", pToken ) );
|
|
|
|
if( strcmp( pToken, "7" ) == 0 )
|
|
{
|
|
pRatPriorities[ ratIndex ] = CELLULAR_RAT_CATM1;
|
|
LogDebug( ( "_Cellular_RecvFuncGetRatPriority: CELLULAR_RAT_CATM1" ) );
|
|
}
|
|
else if( strcmp( pToken, "8" ) == 0 )
|
|
{
|
|
pRatPriorities[ ratIndex ] = CELLULAR_RAT_NBIOT;
|
|
LogDebug( ( "_Cellular_RecvFuncGetRatPriority: CELLULAR_RAT_NBIOT" ) );
|
|
}
|
|
else if( strcmp( pToken, "9" ) == 0 )
|
|
{
|
|
pRatPriorities[ ratIndex ] = CELLULAR_RAT_GSM; /* or CELLULAR_RAT_EDGE */
|
|
LogDebug( ( "_Cellular_RecvFuncGetRatPriority: CELLULAR_RAT_GSM" ) );
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "_Cellular_RecvFuncGetRatPriority: Invalid RAT string [%s]", pToken ) );
|
|
}
|
|
|
|
ratIndex++;
|
|
|
|
if( Cellular_ATGetNextTok( &pInputLine, &pToken ) != CELLULAR_AT_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_GetRatPriority( CellularHandle_t cellularHandle,
|
|
CellularRat_t * pRatPriorities,
|
|
uint8_t ratPrioritiesLength,
|
|
uint8_t * pReceiveRatPrioritesLength )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
uint8_t ratIndex = 0;
|
|
|
|
CellularAtReq_t atReqSetRatPriority =
|
|
{
|
|
"AT+URAT?",
|
|
CELLULAR_AT_WITH_PREFIX,
|
|
"+URAT",
|
|
_Cellular_RecvFuncGetRatPriority,
|
|
NULL,
|
|
0U,
|
|
};
|
|
|
|
atReqSetRatPriority.pData = pRatPriorities;
|
|
atReqSetRatPriority.dataLen = ( uint16_t ) ratPrioritiesLength;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_GetRatPriority: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( ( pRatPriorities == NULL ) || ( ratPrioritiesLength == 0U ) ||
|
|
( ratPrioritiesLength > ( uint8_t ) CELLULAR_MAX_RAT_PRIORITY_COUNT ) ||
|
|
( pReceiveRatPrioritesLength == NULL ) )
|
|
{
|
|
LogWarn( ( "Cellular_GetRatPriority: Bad input Parameter " ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* In case of +UMNOPROF=0, AT+URAT? read commad is not allowed */
|
|
if( CELLULAR_CONFIG_SARA_R4_SET_MNO_PROFILE != 0 )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetRatPriority );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
for( ratIndex = 0; ratIndex < ratPrioritiesLength; ratIndex++ )
|
|
{
|
|
if( pRatPriorities[ ratIndex ] == CELLULAR_RAT_INVALID )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pReceiveRatPrioritesLength = ratIndex;
|
|
}
|
|
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "Cellular_GetRatPriority: Automatic selection as UMNOPROF profile is 0" ) );
|
|
|
|
pRatPriorities[ ratIndex++ ] = CELLULAR_RAT_CATM1;
|
|
pRatPriorities[ ratIndex++ ] = CELLULAR_RAT_NBIOT;
|
|
pRatPriorities[ ratIndex++ ] = CELLULAR_RAT_GSM;
|
|
*pReceiveRatPrioritesLength = RAT_PRIOIRTY_LIST_LENGTH;
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseExtendedSignalQuality( char * pQcsqPayload,
|
|
CellularSignalInfo_t * pSignalInfo )
|
|
{
|
|
char * pToken = NULL, * pTmpQcsqPayload = pQcsqPayload;
|
|
int32_t tempValue = 0;
|
|
bool parseStatus = true;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( ( pSignalInfo == NULL ) || ( pQcsqPayload == NULL ) )
|
|
{
|
|
LogError( ( "_parseExtendedSignalQuality: Invalid Input Parameters" ) );
|
|
parseStatus = false;
|
|
}
|
|
|
|
/* +CESQ: <rxlev>,<ber>,<rscp>,<ecn0>,<rsrq>,<rsrp>. */
|
|
|
|
/* Skip <rxlev>. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
|
|
/* Parse <ber>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( ( atCoreStatus == CELLULAR_AT_SUCCESS ) && ( tempValue <= INT16_MAX ) && ( tempValue >= INT16_MIN ) )
|
|
{
|
|
/*
|
|
* Bit Error Rate (BER):
|
|
* 0..7: as RXQUAL values in the table in 3GPP TS 45.008 [124], subclause 8.2.4
|
|
* 99: not known or not detectable
|
|
*/
|
|
if( ( tempValue >= 0 ) && ( tempValue <= 7 ) )
|
|
{
|
|
pSignalInfo->ber = ( int16_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
pSignalInfo->ber = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseExtendedSignalQuality: Error in processing BER. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
/* Skip <rscp>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
/* Skip <ecno>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
/* Parse <rsrq>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/*
|
|
* Reference Signal Received Quality (RSRQ):
|
|
* 0: less than -19.5 dB
|
|
* 1..33: from -19.5 dB to -3.5 dB with 0.5 dB steps
|
|
* 34: -3 dB or greater
|
|
* 255: not known or not detectable
|
|
*/
|
|
if( ( tempValue >= 0 ) && ( tempValue <= 34 ) )
|
|
{
|
|
pSignalInfo->rsrq = ( int16_t ) ( ( -20 ) + ( tempValue * 0.5 ) );
|
|
}
|
|
else
|
|
{
|
|
pSignalInfo->rsrq = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseExtendedSignalQuality: Error in processing RSRP. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
|
|
/* Parse <rsrp>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/*
|
|
* Reference Signal Received Power(RSRP) :
|
|
* 0 : less than - 140 dBm
|
|
* 1..96 : from - 140 dBm to - 45 dBm with 1 dBm steps
|
|
* 97 : -44 dBm or greater
|
|
* 255 : not known or not detectable
|
|
*/
|
|
if( ( tempValue >= 0 ) && ( tempValue <= 97 ) )
|
|
{
|
|
pSignalInfo->rsrp = ( int16_t ) ( ( -141 ) + ( tempValue ) );
|
|
}
|
|
else
|
|
{
|
|
pSignalInfo->rsrp = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseExtendedSignalQuality: Error in processing RSRP. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseSignalQuality( char * pQcsqPayload,
|
|
CellularSignalInfo_t * pSignalInfo )
|
|
{
|
|
char * pToken = NULL, * pTmpQcsqPayload = pQcsqPayload;
|
|
int32_t tempValue = 0;
|
|
bool parseStatus = true;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( ( pSignalInfo == NULL ) || ( pQcsqPayload == NULL ) )
|
|
{
|
|
LogError( ( "_parseSignalQuality: Invalid Input Parameters" ) );
|
|
parseStatus = false;
|
|
}
|
|
|
|
/* +CSQ: <signal_power>,<qual>. */
|
|
|
|
/* Parse <signal_power>. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/*
|
|
* The allowed range is 0-31 and 99.
|
|
* 0 RSSI of the network <= -113 dBm
|
|
* 1 -111 dBm
|
|
* 2...30 -109 dBm <= RSSI of the network <= -53 dBm
|
|
* 31 -51 dBm <= RSSI of the network
|
|
* 99 Not known or not detectable
|
|
*/
|
|
if( ( tempValue >= 0 ) && ( tempValue <= 31 ) )
|
|
{
|
|
pSignalInfo->rssi = ( int16_t ) ( ( -113 ) + ( tempValue * 2 ) );
|
|
}
|
|
else if( tempValue == 99 )
|
|
{
|
|
pSignalInfo->rssi = -113;
|
|
}
|
|
else
|
|
{
|
|
pSignalInfo->rssi = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseSignalQuality: Error in processing RSSI. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
|
|
/* Parse <qual>. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/*
|
|
* The allowed range is 0-7 and 99 :
|
|
* In 2G RAT CS dedicated and GPRS packet transfer mode indicates the Bit Error Rate (BER) as specified in 3GPP TS 45.008
|
|
*/
|
|
if( ( tempValue >= 0 ) && ( tempValue <= 7 ) )
|
|
{
|
|
pSignalInfo->ber = ( int16_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
pSignalInfo->ber = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseSignalQuality: Error in processing ber. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* parse signal strength response */
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSignalInfo( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pInputLine = NULL;
|
|
CellularSignalInfo_t * pSignalInfo = ( CellularSignalInfo_t * ) pData;
|
|
bool parseStatus = true;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
bool isExtendedResponse = false;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pSignalInfo == NULL ) || ( dataLen != sizeof( CellularSignalInfo_t ) ) )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetSignalInfo: Input Line passed is NULL" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
|
|
if( strstr( pInputLine, "+CESQ" ) )
|
|
{
|
|
LogDebug( ( "GetSignalInfo: ExtendedResponse received." ) );
|
|
isExtendedResponse = true;
|
|
}
|
|
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pInputLine );
|
|
}
|
|
|
|
if( atCoreStatus != CELLULAR_AT_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
if( isExtendedResponse )
|
|
{
|
|
parseStatus = _parseExtendedSignalQuality( pInputLine, pSignalInfo );
|
|
}
|
|
else
|
|
{
|
|
parseStatus = _parseSignalQuality( pInputLine, pSignalInfo );
|
|
}
|
|
|
|
if( parseStatus != true )
|
|
{
|
|
pSignalInfo->rssi = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
pSignalInfo->rsrp = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
pSignalInfo->rsrq = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
pSignalInfo->ber = CELLULAR_INVALID_SIGNAL_VALUE;
|
|
pSignalInfo->bars = CELLULAR_INVALID_SIGNAL_BAR_VALUE;
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_GetSignalInfo( CellularHandle_t cellularHandle,
|
|
CellularSignalInfo_t * pSignalInfo )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularRat_t rat = CELLULAR_RAT_INVALID;
|
|
CellularAtReq_t atReqQuerySignalInfo =
|
|
{
|
|
"AT+CSQ",
|
|
CELLULAR_AT_WITH_PREFIX,
|
|
"+CSQ",
|
|
_Cellular_RecvFuncGetSignalInfo,
|
|
NULL,
|
|
sizeof( CellularSignalInfo_t ),
|
|
};
|
|
CellularAtReq_t atReqQueryExtendedSignalInfo =
|
|
{
|
|
"AT+CESQ",
|
|
CELLULAR_AT_WITH_PREFIX,
|
|
"+CESQ",
|
|
_Cellular_RecvFuncGetSignalInfo,
|
|
NULL,
|
|
sizeof( CellularSignalInfo_t ),
|
|
};
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
atReqQuerySignalInfo.pData = pSignalInfo;
|
|
atReqQueryExtendedSignalInfo.pData = pSignalInfo;
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_GetSignalInfo: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pSignalInfo == NULL )
|
|
{
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = _Cellular_GetCurrentRat( pContext, &rat );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Get +CSQ response */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqQuerySignalInfo );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* Get +CESQ response */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqQueryExtendedSignalInfo );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* If the convert failed, the API will return CELLULAR_INVALID_SIGNAL_BAR_VALUE in bars field. */
|
|
( void ) _Cellular_ComputeSignalBars( rat, pSignalInfo );
|
|
}
|
|
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SetDns( CellularHandle_t cellularHandle,
|
|
uint8_t contextId,
|
|
const char * pDnsServerAddress )
|
|
{
|
|
/* Modem use dynamic DNS addresses. Return unsupported. */
|
|
( void ) cellularHandle;
|
|
( void ) contextId;
|
|
( void ) pDnsServerAddress;
|
|
return CELLULAR_UNSUPPORTED;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t controlSignalStrengthIndication( CellularContext_t * pContext,
|
|
bool enable )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
|
|
uint8_t enable_value = 0;
|
|
CellularAtReq_t atReqControlSignalStrengthIndication =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0,
|
|
};
|
|
|
|
atReqControlSignalStrengthIndication.pAtCmd = cmdBuf;
|
|
|
|
if( enable == true )
|
|
{
|
|
enable_value = 1;
|
|
}
|
|
else
|
|
{
|
|
enable_value = 0;
|
|
}
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
if( enable_value )
|
|
{
|
|
/* Enable signal level change indication via +CIEV URC.*/
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "AT+UCIND=2" );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqControlSignalStrengthIndication );
|
|
}
|
|
else
|
|
{
|
|
/* Disable signal level change indication via +CIEV URC.*/
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "AT+UCIND=0" );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqControlSignalStrengthIndication );
|
|
}
|
|
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_RegisterUrcSignalStrengthChangedCallback( CellularHandle_t cellularHandle,
|
|
CellularUrcSignalStrengthChangedCallback_t signalStrengthChangedCallback,
|
|
void * pCallbackContext )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
|
|
/* pContext is checked in the common library. */
|
|
cellularStatus = Cellular_CommonRegisterUrcSignalStrengthChangedCallback(
|
|
cellularHandle, signalStrengthChangedCallback, pCallbackContext );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
if( signalStrengthChangedCallback != NULL )
|
|
{
|
|
cellularStatus = controlSignalStrengthIndication( pContext, true );
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = controlSignalStrengthIndication( pContext, false );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Resolve Domain name to IP address */
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncResolveDomainToIpAddress( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pRespLine = NULL;
|
|
char * pResolvedIpAddress = ( char * ) pData;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
const CellularATCommandLine_t * pCommnadItem = NULL;
|
|
char * pToken = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncResolveDomainToIpAddress: invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pResolvedIpAddress == NULL ) || ( dataLen != CELLULAR_IP_ADDRESS_MAX_SIZE ) )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( pAtResp == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncResolveDomainToIpAddress: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncResolveDomainToIpAddress: Address not resolved" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
|
|
pCommnadItem = pAtResp->pItm;
|
|
|
|
while( pCommnadItem != NULL )
|
|
{
|
|
pRespLine = pCommnadItem->pLine;
|
|
LogDebug( ( "_Cellular_RecvFuncResolveDomainToIpAddress: pRespLine [%s]", pRespLine ) );
|
|
|
|
/* Removing all the Spaces in the AT Response. */
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pRespLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
( void ) strncpy( pResolvedIpAddress, pToken, dataLen );
|
|
|
|
LogDebug( ( "_Cellular_RecvFuncResolveDomainToIpAddress: Resolved IP Address: [%s]", pResolvedIpAddress ) );
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncResolveDomainToIpAddress: parse %s failed", pRespLine ) );
|
|
break;
|
|
}
|
|
|
|
pCommnadItem = pCommnadItem->pNext;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_GetHostByName( CellularHandle_t cellularHandle,
|
|
uint8_t contextId,
|
|
const char * pcHostName,
|
|
char * pResolvedAddress )
|
|
{
|
|
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' };
|
|
|
|
CellularAtReq_t atReqQueryDns =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_MULTI_WITH_PREFIX,
|
|
"+UDNSRN",
|
|
_Cellular_RecvFuncResolveDomainToIpAddress,
|
|
NULL,
|
|
CELLULAR_IP_ADDRESS_MAX_SIZE,
|
|
};
|
|
|
|
( void ) contextId;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
atReqQueryDns.pAtCmd = cmdBuf;
|
|
atReqQueryDns.pData = pResolvedAddress;
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogDebug( ( "Cellular_GetHostByName: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( ( pcHostName == NULL ) || ( pResolvedAddress == NULL ) )
|
|
{
|
|
LogError( ( "Cellular_GetHostByName: Bad input Parameter " ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE,
|
|
"AT+UDNSRN=0,\"%s\"", pcHostName );
|
|
|
|
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqQueryDns, DNS_QUERY_REQ_TIMEOUT_MS );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_GetHostByName: couldn't resolve host name" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Get PDN context APN name*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetPdpContextSettings( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pRespLine = NULL;
|
|
CellularPdnContextInfo_t * pPDPContextsInfo = ( CellularPdnContextInfo_t * ) pData;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
const CellularATCommandLine_t * pCommnadItem = NULL;
|
|
uint8_t tokenIndex = 0;
|
|
uint8_t contextId = 0;
|
|
int32_t tempValue = 0;
|
|
char * pToken = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextSettings: invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pPDPContextsInfo == NULL ) || ( dataLen != sizeof( CellularPdnContextInfo_t ) ) )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( pAtResp == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextSettings: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextSettings: no PDN context available" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
|
|
pCommnadItem = pAtResp->pItm;
|
|
|
|
while( pCommnadItem != NULL )
|
|
{
|
|
pRespLine = pCommnadItem->pLine;
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: pRespLine [%s]", pRespLine ) );
|
|
|
|
/* Removing all the Spaces in the AT Response. */
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pRespLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
tokenIndex = 0;
|
|
|
|
while( ( pToken != NULL ) && ( atCoreStatus == CELLULAR_AT_SUCCESS ) )
|
|
{
|
|
switch( tokenIndex )
|
|
{
|
|
case ( CELLULAR_PDN_STATUS_POS_CONTEXT_ID ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: Context Id pToken: %s", pToken ) );
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= ( int32_t ) CELLULAR_PDN_CONTEXT_ID_MIN ) &&
|
|
( tempValue <= ( int32_t ) MAX_PDP_CONTEXTS ) )
|
|
{
|
|
contextId = ( uint8_t ) tempValue;
|
|
pPDPContextsInfo->contextsPresent[ contextId - 1 ] = true;
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: Context Id: %d", contextId ) );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextSettings: Invalid Context Id. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case ( CELLULAR_PDN_STATUS_POS_CONTEXT_TYPE ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: Context Type pToken: %s", pToken ) );
|
|
|
|
( void ) memcpy( ( void * ) pPDPContextsInfo->ipType[ contextId - 1 ],
|
|
( void * ) pToken, CELULAR_PDN_CONTEXT_TYPE_MAX_SIZE + 1U );
|
|
break;
|
|
|
|
case ( CELLULAR_PDN_STATUS_POS_APN_NAME ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: Context APN name pToken: %s", pToken ) );
|
|
|
|
( void ) memcpy( ( void * ) pPDPContextsInfo->apnName[ contextId - 1 ],
|
|
( void * ) pToken, CELLULAR_APN_MAX_SIZE + 1U );
|
|
break;
|
|
|
|
case ( CELLULAR_PDN_STATUS_POS_IP_ADDRESS ):
|
|
LogDebug( ( "_Cellular_RecvFuncGetPdpContextSettings: Context IP address pToken: %s", pToken ) );
|
|
|
|
( void ) memcpy( ( void * ) pPDPContextsInfo->ipAddress[ contextId - 1 ],
|
|
( void * ) pToken, CELLULAR_IP_ADDRESS_MAX_SIZE + 1U );
|
|
break;
|
|
|
|
default:
|
|
break;
|
|
}
|
|
|
|
tokenIndex++;
|
|
|
|
if( Cellular_ATGetNextTok( &pRespLine, &pToken ) != CELLULAR_AT_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPdpContextSettings: parse %s failed", pRespLine ) );
|
|
break;
|
|
}
|
|
|
|
pCommnadItem = pCommnadItem->pNext;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Set PDN APN name and Authentication setting */
|
|
|
|
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;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SetPsmSettings( CellularHandle_t cellularHandle,
|
|
const CellularPsmSettings_t * pPsmSettings )
|
|
{
|
|
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' };
|
|
|
|
CellularAtReq_t atReqSetPsm =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0
|
|
};
|
|
|
|
atReqSetPsm.pAtCmd = cmdBuf;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "Cellular_SetPsmSettings: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pPsmSettings == NULL )
|
|
{
|
|
LogError( ( "Cellular_SetPsmSettings : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if( pPsmSettings->mode == 1 )
|
|
{
|
|
/*
|
|
* SARA-R4: To change the command setting issue AT+COPS=2 or AT+CFUN=0 to deregister the module from
|
|
* network, issue the +CPSMS command and reboot the module in order to apply the new configuration. */
|
|
/* After PSM mode active, press "PWR_ON" key to awake modem or T3412 timer is expired. */
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "AT+CFUN=0" );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetPsm );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
cellularStatus = Cellular_CommonSetPsmSettings( cellularHandle, pPsmSettings );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
cellularStatus = rebootCellularModem( pContext, false, true );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Cellular_SetPsmSettings: Unable to set PSM settings." ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = Cellular_CommonSetPsmSettings( cellularHandle, pPsmSettings );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* FreeRTOS Cellular Library API. */
|
|
/* coverity[misra_c_2012_rule_8_7_violation] */
|
|
CellularError_t Cellular_SetEidrxSettings( CellularHandle_t cellularHandle,
|
|
const CellularEidrxSettings_t * pEidrxSettings )
|
|
{
|
|
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' };
|
|
|
|
CellularAtReq_t atReqSetEidrx =
|
|
{
|
|
NULL,
|
|
CELLULAR_AT_NO_RESULT,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
0
|
|
};
|
|
|
|
atReqSetEidrx.pAtCmd = cmdBuf;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "Cellular_SetEidrxSettings: _Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pEidrxSettings == NULL )
|
|
{
|
|
LogError( ( "Cellular_SetEidrxSettings : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
if( ( pEidrxSettings->mode == 1 ) || ( pEidrxSettings->mode == 2 ) )
|
|
{
|
|
/*
|
|
* SARA-R4: To change the command setting issue AT+COPS=2 or AT+CFUN=0 to deregister the module from
|
|
* network, issue the +CEDRXS command and reboot the module in order to apply the new configuration.
|
|
*/
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "AT+CFUN=0" );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetEidrx );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
cellularStatus = Cellular_CommonSetEidrxSettings( cellularHandle, pEidrxSettings );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
cellularStatus = rebootCellularModem( pContext, true, false );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Cellular_SetEidrxSettings: Unable to set Eidrx settings." ) );
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = Cellular_CommonSetEidrxSettings( cellularHandle, pEidrxSettings );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_Init( CellularHandle_t * pCellularHandle,
|
|
const CellularCommInterface_t * pCommInterface )
|
|
{
|
|
CellularTokenTable_t cellularTokenTable = { 0 };
|
|
|
|
cellularTokenTable.pCellularUrcHandlerTable = CellularUrcHandlerTable;
|
|
cellularTokenTable.cellularPrefixToParserMapSize = CellularUrcHandlerTableSize;
|
|
cellularTokenTable.pCellularSrcTokenErrorTable = CellularSrcTokenErrorTable;
|
|
cellularTokenTable.cellularSrcTokenErrorTableSize = CellularSrcTokenErrorTableSize;
|
|
cellularTokenTable.pCellularSrcTokenSuccessTable = CellularSrcTokenSuccessTable;
|
|
cellularTokenTable.cellularSrcTokenSuccessTableSize = CellularSrcTokenSuccessTableSize;
|
|
cellularTokenTable.pCellularUrcTokenWoPrefixTable = CellularUrcTokenWoPrefixTable;
|
|
cellularTokenTable.cellularUrcTokenWoPrefixTableSize = CellularUrcTokenWoPrefixTableSize;
|
|
cellularTokenTable.pCellularSrcExtraTokenSuccessTable = NULL;
|
|
cellularTokenTable.cellularSrcExtraTokenSuccessTableSize = 0;
|
|
|
|
return Cellular_CommonInit( pCellularHandle, pCommInterface, &cellularTokenTable );
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|