You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
FreeRTOS/FreeRTOS-Plus/Source/FreeRTOS-Cellular-Modules/FreeRTOS-Cellular-Interface.../cellular_hl7802_api.c

2789 lines
102 KiB
C

/*
* FreeRTOS-Cellular-Interface v1.3.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 <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
/* Cellular includes. */
#include "cellular_types.h"
#include "cellular_api.h"
#include "cellular_common_api.h"
#include "cellular_common.h"
#include "cellular_at_core.h"
/* Cellular module includes. */
#include "cellular_hl7802.h"
/*-----------------------------------------------------------*/
#define CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ( 32U )
#define SOCKET_END_PATTERN "--EOF--Pattern--"
#define SOCKET_END_PATTERN_LEN ( 16U )
#define SOCKET_DATA_CONNECT_TOKEN "CONNECT"
#define SOCKET_DATA_CONNECT_TOKEN_LEN ( 7U )
#define CELLULAR_CEDRXS_POS_ACT ( 0U )
#define CELLULAR_CEDRXS_POS_RAT ( 1U )
#define CELLULAR_CEDRXS_POS_REQUESTED_EDRX_VALUE ( 2U )
#define CELLULAR_CEDRXS_POS_NW_PROVIDED_EDRX_VALUE ( 3U )
#define CELLULAR_CEDRXS_POS_REQUESTED_PTW_VALUE ( 4U )
#define CELLULAR_CEDRXS_POS_NW_PROVIDED_PTW_VALUE ( 5U )
#define RAT_PRIOIRTY_LIST_LENGTH ( 3U )
#define SIGNAL_QUALITY_CSQ_UNKNOWN ( 99 )
#define SIGNAL_QUALITY_CSQ_BER_MIN ( 0 )
#define SIGNAL_QUALITY_CSQ_BER_MAX ( 7 )
#define INVALID_PDN_INDEX ( 0xFFU )
#define CELLULAR_PDN_STATUS_POS_CONTEXT_ID ( 0U )
#define CELLULAR_PDN_STATUS_POS_GPRS ( 1U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_APN ( 2U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_LOGIN ( 3U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_PASSWORD ( 4U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_AF ( 5U )
#define CELLULAR_PDN_STATUS_POS_IP ( 6U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_DNS1 ( 7U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_DNS2 ( 8U ) /* Ignored pos. */
#define CELLULAR_PDN_STATUS_POS_STATE ( 9U )
#define CELLULAR_PDN_STATE_DISCONNECTED ( 0U )
#define CELLULAR_PDN_STATE_CONNECTING ( 1U )
#define CELLULAR_PDN_STATE_CONNECTED ( 2U )
#define CELLULAR_PDN_STATE_IDLE ( 3U )
#define CELLULAR_PDN_STATE_DISCONNECTING ( 4U )
#define KSELACQ_RAT_CATM_CHAR ( '1' )
#define KSELACQ_RAT_NBIOT_CHAR ( '2' )
#define KSELACQ_RAT_GSM_CHAR ( '3' )
#define CELLULAR_PORT_NUM_CHAR_LEN ( 6 )
#define CELLULAR_REMOTE_IP_ADDR_MAX_LENGTH ( 127 )
/*-----------------------------------------------------------*/
/**
* @brief Parameters involved in receiving data through sockets
*/
typedef struct _socketDataRecv
{
uint32_t * pDataLen;
uint8_t * pData;
} _socketDataRecv_t;
typedef struct socketStat
{
tcpSocketState_t status; /* TCP socket state. */
tcpConnectionFailure_t tcpNotif; /* 1 if socket/connection is OK, <tcp_notif> if an error has happened. */
uint16_t remData; /* Remaining bytes in the socket buffer, waiting to be sent. */
uint16_t rcvData; /* Received bytes, can be read with +KTCPRCV command. */
} socketStat_t;
/*-----------------------------------------------------------*/
static const char * _socketSendSuccesTokenTable[] = { SOCKET_DATA_CONNECT_TOKEN };
static const uint32_t _socketSendSuccesTokenTableLength = 1;
/*-----------------------------------------------------------*/
static CellularPktStatus_t _Cellular_RecvFuncGetSocketStat( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen );
static CellularError_t _Cellular_GetSocketStat( CellularHandle_t cellularHandle,
CellularSocketHandle_t socketHandle,
socketStat_t * pSocketStat );
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 buildSocketConfig( CellularSocketHandle_t socketHandle,
char * pCmdBuf );
static CellularError_t storeAccessModeAndAddress( CellularContext_t * pContext,
CellularSocketHandle_t socketHandle,
CellularSocketAccessMode_t dataAccessMode,
const CellularSocketAddress_t * pRemoteSocketAddress );
static CellularPktStatus_t _Cellular_RecvFuncGetTcpCfgSessionId( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen );
static CellularError_t _Cellular_getTcpCfgSessionId( CellularHandle_t cellularHandle,
CellularSocketHandle_t socketHandle,
uint8_t * pSessionId );
static CellularATError_t parseEidrxToken( char * pToken,
uint8_t tokenIndex,
CellularEidrxSettingsList_t * pEidrxSettingsList,
uint8_t count );
static CellularATError_t parseEidrxLine( char * pInputLine,
uint8_t count,
CellularEidrxSettingsList_t * pEidrxSettingsList );
static CellularPktStatus_t _Cellular_RecvFuncGetEidrxSettings( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen );
static CellularRat_t convertKselacqIndexToRat( char ratIndex );
static CellularPktStatus_t _Cellular_RecvFuncGetRatPriority( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen );
static int16_t convertCesqSignalRxlev( int32_t rxlevValue );
static int16_t convertCesqSignalRsrq( int32_t rsrqValue );
static int16_t convertCesqSignalRsrp( int32_t rsrpValue );
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 );
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library types. */
/* coverity[misra_c_2012_rule_8_13_violation] */
static CellularPktStatus_t _Cellular_RecvFuncGetSocketStat( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen )
{
char * pInputLine = NULL, * pToken = NULL;
socketStat_t * pSocketStat = ( socketStat_t * ) pData;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
int32_t tempValue = 0;
if( pContext == NULL )
{
LogError( ( "GetSocketStat: Invalid handle" ) );
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
}
else if( ( pSocketStat == NULL ) || ( dataLen != sizeof( socketStat_t ) ) )
{
LogError( ( "GetSocketStat: Bad parameters" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
{
LogError( ( "GetSocketStat: Input Line passed is NULL" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else
{
/* +KTCPSTAT: <session_id>,<status>,<tcp_notif>,<rem_data>,<rcv_data>. */
/* Remove prefix and leading space. */
pInputLine = pAtResp->pItm->pLine;
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pInputLine );
}
/* Get token status. */
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= TCP_SOCKET_STATE_NOT_DEFINED ) && ( tempValue < TCP_SOCKET_STATE_MAX ) )
{
pSocketStat->status = ( tcpSocketState_t ) tempValue;
}
else
{
LogError( ( "GetSocketStat unknown status %d", tempValue ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
}
/* Get token tcp_notif. */
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= TCP_NOTIF_OK ) && ( tempValue < TCP_NOTIF_MAX ) )
{
pSocketStat->tcpNotif = ( tcpConnectionFailure_t ) tempValue;
}
else
{
LogError( ( "GetSocketStat unknown tcp_notif %d", tempValue ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
}
/* Get token rem_data. */
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) && ( tempValue < UINT16_MAX ) )
{
pSocketStat->remData = ( uint16_t ) tempValue;
}
else
{
LogError( ( "GetSocketStat unknown rem_data %d", tempValue ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
}
/* Get token rcv_data. */
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) && ( tempValue < UINT16_MAX ) )
{
pSocketStat->rcvData = ( uint16_t ) tempValue;
}
else
{
LogError( ( "GetSocketStat unknown rcvData %d", tempValue ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
}
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
}
return pktStatus;
}
/*-----------------------------------------------------------*/
static CellularError_t _Cellular_GetSocketStat( CellularHandle_t cellularHandle,
CellularSocketHandle_t socketHandle,
socketStat_t * pSocketStat )
{
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
CellularAtReq_t atReqSocketStat =
{
cmdBuf,
CELLULAR_AT_WITH_PREFIX,
"+KTCPSTAT",
_Cellular_RecvFuncGetSocketStat,
pSocketStat,
sizeof( socketStat_t ),
};
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
CellularError_t cellularStatus = CELLULAR_SUCCESS;
uint32_t sessionId = _Cellular_GetSessionId( pContext, socketHandle->socketId );
/* Internal function. Caller checks parameters. */
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "AT+KTCPSTAT=%lu", sessionId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketStat,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
return cellularStatus;
}
/*-----------------------------------------------------------*/
static CellularPktStatus_t socketRecvDataPrefix( void * pCallbackContext,
char * pLine,
uint32_t lineLength,
char ** ppDataStart,
uint32_t * pDataLength )
{
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
uint32_t * pRecvDataLength = ( uint32_t * ) pCallbackContext;
if( ( pLine == NULL ) || ( ppDataStart == NULL ) || ( pDataLength == NULL ) || ( pCallbackContext == NULL ) )
{
LogError( ( "socketRecvData: Bad parameters" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else if( ( lineLength < ( SOCKET_DATA_CONNECT_TOKEN_LEN + 2U ) ) && ( *pRecvDataLength > 0 ) )
{
/* Need more data to decide the data prefix. */
pktStatus = CELLULAR_PKT_STATUS_SIZE_MISMATCH;
}
else
{
if( strncmp( pLine, SOCKET_DATA_CONNECT_TOKEN, SOCKET_DATA_CONNECT_TOKEN_LEN ) == 0 )
{
/* The string length of "CONNECT\r\n". */
*ppDataStart = ( char * ) &pLine[ SOCKET_DATA_CONNECT_TOKEN_LEN + 2 ]; /* Indicate the data start in pLine. */
*pDataLength = *pRecvDataLength; /* Return the data length from pCallbackContext. */
*pRecvDataLength = 0;
}
else
{
/* Prefix string which is not "CONNECT" does't indicate data start. Set data length to 0.*/
*pDataLength = 0;
}
}
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 %d, out buffer size %d",
*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 %d",
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, * pEndPatternLine = NULL;
const _socketDataRecv_t * pDataRecv = ( _socketDataRecv_t * ) pData;
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( ( pAtResp->pItm->pNext == NULL ) || ( pAtResp->pItm->pNext->pNext == NULL ) )
{
LogError( ( "Receive Data: response data or end pattern 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. */
pEndPatternLine = pAtResp->pItm->pNext->pNext->pLine; /* The third item is the end pattern. */
/* Check the data prefix token "CONNECT". */
if( strncmp( pInputLine, SOCKET_DATA_CONNECT_TOKEN, SOCKET_DATA_CONNECT_TOKEN_LEN ) != 0 )
{
LogError( ( "response item error in prefix CONNECT" ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
/* Check the data end pattern. */
if( strncmp( pEndPatternLine, SOCKET_END_PATTERN, SOCKET_END_PATTERN_LEN ) != 0 )
{
LogError( ( "response item error in end pattern"SOCKET_END_PATTERN ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
/* Process the data buffer. */
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = getDataFromResp( pAtResp, pDataRecv, dataLen );
}
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
}
return pktStatus;
}
/*-----------------------------------------------------------*/
static CellularError_t buildSocketConfig( CellularSocketHandle_t socketHandle,
char * pCmdBuf )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;
/* +1 size in buffer for ',' */
char portBuf[ CELLULAR_PORT_NUM_CHAR_LEN + 1 ] = { 0 };
if( pCmdBuf == NULL )
{
LogDebug( ( "buildSocketConfig: Invalid command buffer" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else if( socketHandle->socketProtocol != CELLULAR_SOCKET_PROTOCOL_TCP )
{
LogError( ( "buildSocketConfig: socket protocol unsupported %d",
socketHandle->socketProtocol ) );
cellularStatus = CELLULAR_UNSUPPORTED;
}
else if( strlen( socketHandle->remoteSocketAddress.ipAddress.ipAddress ) > CELLULAR_REMOTE_IP_ADDR_MAX_LENGTH )
{
/* The maximum length of domain name is 127 in HL7802. */
LogError( ( "buildSocketConfig: the remote server's address is too long, length=%u",
strlen( socketHandle->remoteSocketAddress.ipAddress.ipAddress ) ) );
cellularStatus = CELLULAR_UNSUPPORTED;
}
else
{
/* Form the AT command. */
/* The return value of snprintf is not used.
* The max length of the string is fixed and checked offline.
* Reserve buffer for port setting. */
/* coverity[misra_c_2012_rule_21_6_violation]. */
( void ) snprintf( pCmdBuf, CELLULAR_AT_CMD_MAX_SIZE - sizeof( portBuf ),
"AT+KTCPCFG=%u,0,\"%s\",%u",
socketHandle->contextId,
socketHandle->remoteSocketAddress.ipAddress.ipAddress,
socketHandle->remoteSocketAddress.port );
/* Set the local port in the end of command buffer string if localPort is not 0. */
if( socketHandle->localPort > 0 )
{
( void ) snprintf( portBuf, sizeof( portBuf ),
",%u",
socketHandle->localPort );
/* Because the length of host's IP address is limited,
* the buffer size must be enough for port setting. */
strcat( pCmdBuf, portBuf );
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
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_RecvFuncGetTcpCfgSessionId( 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( ( "GetTcpCfgSessionId: Invalid handle" ) );
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
}
else if( ( pSessionId == NULL ) || ( dataLen != sizeof( uint8_t ) ) )
{
LogError( ( "GetTcpCfgSessionId: Bad parameters" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
{
LogError( ( "GetTcpCfgSessionId: 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_getTcpCfgSessionId( 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;
char cmdBuf[ CELLULAR_AT_CMD_MAX_SIZE ] = { '\0' };
CellularAtReq_t atReqSocketConnect =
{
cmdBuf,
CELLULAR_AT_WITH_PREFIX,
"+KTCPCFG",
_Cellular_RecvFuncGetTcpCfgSessionId,
pSessionId,
sizeof( uint8_t ),
};
/* Internal function. Caller checks parameters. */
cellularStatus = buildSocketConfig( socketHandle, cmdBuf );
if( cellularStatus == CELLULAR_SUCCESS )
{
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketConnect,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_SocketConnect: Socket connect failed, cmdBuf:%s, PktRet: %d", cmdBuf, pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t parseEidrxToken( char * pToken,
uint8_t tokenIndex,
CellularEidrxSettingsList_t * pEidrxSettingsList,
uint8_t count )
{
int32_t tempValue = 0;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
switch( tokenIndex )
{
case CELLULAR_CEDRXS_POS_ACT:
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) &&
( tempValue <= ( int32_t ) UINT8_MAX ) )
{
pEidrxSettingsList->eidrxList[ count ].mode = ( uint8_t ) tempValue;
}
else
{
LogError( ( "Error in processing mode value. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
break;
case CELLULAR_CEDRXS_POS_RAT:
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) &&
( tempValue <= ( int32_t ) UINT8_MAX ) )
{
pEidrxSettingsList->eidrxList[ count ].rat = ( uint8_t ) tempValue;
}
else
{
LogError( ( "Error in processing Requested rat value. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
break;
case CELLULAR_CEDRXS_POS_REQUESTED_EDRX_VALUE:
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) &&
( tempValue <= ( int32_t ) UINT8_MAX ) )
{
pEidrxSettingsList->eidrxList[ count ].requestedEdrxVaue = ( uint8_t ) tempValue;
}
else
{
LogError( ( "Error in processing Requested Edrx value. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
break;
case CELLULAR_CEDRXS_POS_NW_PROVIDED_EDRX_VALUE:
/* Unused value. */
break;
case CELLULAR_CEDRXS_POS_REQUESTED_PTW_VALUE:
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) &&
( tempValue <= ( int32_t ) UINT8_MAX ) )
{
pEidrxSettingsList->eidrxList[ count ].pagingTimeWindow = ( uint8_t ) tempValue;
}
else
{
LogError( ( "Error in processing Requested paging time window value. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
break;
case CELLULAR_CEDRXS_POS_NW_PROVIDED_PTW_VALUE:
/* Unused value. */
break;
default:
LogDebug( ( "Unknown Parameter Position %u in AT+CEDRXS Response", tokenIndex ) );
atCoreStatus = CELLULAR_AT_ERROR;
break;
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t parseEidrxLine( char * pInputLine,
uint8_t count,
CellularEidrxSettingsList_t * pEidrxSettingsList )
{
char * pToken = NULL;
char * pLocalInputLine = pInputLine;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
uint8_t tokenIndex = 0;
atCoreStatus = Cellular_ATRemovePrefix( &pLocalInputLine );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pLocalInputLine );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pLocalInputLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
tokenIndex = 0;
while( pToken != NULL )
{
if( parseEidrxToken( pToken, tokenIndex, pEidrxSettingsList, count ) != CELLULAR_AT_SUCCESS )
{
LogInfo( ( "parseEidrxToken %s index %d failed", pToken, tokenIndex ) );
}
tokenIndex++;
if( Cellular_ATGetNextTok( &pLocalInputLine, &pToken ) != CELLULAR_AT_SUCCESS )
{
break;
}
}
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library prototype. */
/* coverity[misra_c_2012_rule_8_13_violation] */
static CellularPktStatus_t _Cellular_RecvFuncGetEidrxSettings( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen )
{
char * pInputLine = NULL;
uint8_t count = 0;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
CellularEidrxSettingsList_t * pEidrxSettingsList = NULL;
const CellularATCommandLine_t * pCommnadItem = NULL;
if( pContext == NULL )
{
LogError( ( "GetEidrxSettings: Invalid context" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else if( ( pAtResp == NULL ) ||
( pAtResp->pItm == NULL ) ||
( pAtResp->pItm->pLine == NULL ) ||
( pData == NULL ) ||
( dataLen != CELLULAR_EDRX_LIST_MAX_SIZE ) )
{
LogError( ( "GetEidrxSettings: Invalid param" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else
{
pEidrxSettingsList = ( CellularEidrxSettingsList_t * ) pData;
pCommnadItem = pAtResp->pItm;
while( pCommnadItem != NULL )
{
pInputLine = pCommnadItem->pLine;
atCoreStatus = parseEidrxLine( pInputLine, count, pEidrxSettingsList );
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "GetEidrx: Parsing Error encountered, atCoreStatus: %d", atCoreStatus ) );
}
else
{
LogDebug( ( "GetEidrx setting[%d]: RAT: %d, Value: 0x%x",
count, pEidrxSettingsList->eidrxList[ count ].rat, pEidrxSettingsList->eidrxList[ count ].requestedEdrxVaue ) );
}
pCommnadItem = pCommnadItem->pNext;
count++;
pEidrxSettingsList->count = count;
}
}
return pktStatus;
}
/*-----------------------------------------------------------*/
static CellularRat_t convertKselacqIndexToRat( char ratIndex )
{
CellularRat_t rat = CELLULAR_RAT_INVALID;
switch( ratIndex )
{
case KSELACQ_RAT_CATM_CHAR:
rat = CELLULAR_RAT_CATM1;
break;
case KSELACQ_RAT_NBIOT_CHAR:
rat = CELLULAR_RAT_NBIOT;
break;
case KSELACQ_RAT_GSM_CHAR:
rat = CELLULAR_RAT_GSM;
break;
default:
break;
}
return rat;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library types. */
/* 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;
uint32_t ratIndex = 0;
uint32_t maxRatPriorityLength = ( dataLen > RAT_PRIOIRTY_LIST_LENGTH ? RAT_PRIOIRTY_LIST_LENGTH : dataLen );
if( pContext == NULL )
{
LogError( ( "GetRatPriority: Invalid context" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) ||
( pAtResp->pItm->pLine == NULL ) || ( pData == NULL ) || ( dataLen == 0U ) )
{
LogError( ( "GetRatPriority: Invalid param" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else
{
pInputLine = pAtResp->pItm->pLine;
pRatPriorities = ( CellularRat_t * ) pData;
/* Response string "+KSELACQ: 1,2,3". */
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
for( ratIndex = 0; ratIndex < maxRatPriorityLength; ratIndex++ )
{
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pToken );
}
if( ( atCoreStatus == CELLULAR_AT_SUCCESS ) && ( strlen( pToken ) == 1 ) )
{
pRatPriorities[ ratIndex ] = convertKselacqIndexToRat( pToken[ 0 ] );
}
else
{
pRatPriorities[ ratIndex ] = CELLULAR_RAT_INVALID;
}
}
}
for( ; ratIndex < dataLen; ratIndex++ )
{
pRatPriorities[ ratIndex ] = CELLULAR_RAT_INVALID;
}
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
}
return pktStatus;
}
/*-----------------------------------------------------------*/
/* Received signal strength level (see 3GPP TS 45.008 [20] subclause 8.1.4)
* 0 rssi < -110 dBm : assume -111 dBm to indicate the signal is detectable but fairly week.
* 1 -110 dBm <= rssi < -109 dBm
* 2 -109 dBm <= rssi < -108 dBm
* ...
* 61 -50 dBm <= rssi < -49 dBm
* 62 -49 dBm <= rssi < -48 dBm
* 63 -48 dBm <= rssi
* 99 not known or not detectable */
static int16_t convertCesqSignalRxlev( int32_t rxlevValue )
{
int16_t rssidBm = 0;
if( ( rxlevValue >= 0 ) && ( rxlevValue <= 63 ) )
{
rssidBm = ( int16_t ) ( ( -111 ) + ( rxlevValue ) );
}
else
{
rssidBm = CELLULAR_INVALID_SIGNAL_VALUE;
}
return rssidBm;
}
/*-----------------------------------------------------------*/
/* 0 rsrq < -19.5 dB
* 1 -19.5 dB <= rsrq < -19 dB
* 2 -19 dB <= rsrq < -18.5 dB
* ...
* 32 -4 dB <= rsrq < -3.5 dB
* 33 -3.5 dB <= rsrq < -3 dB
* 34 -3 dB <= rsrq
* 255 Not known or not detectable. */
static int16_t convertCesqSignalRsrq( int32_t rsrqValue )
{
int16_t rsrqDb = 0;
if( ( rsrqValue >= 0 ) && ( rsrqValue <= 34 ) )
{
rsrqDb = ( int16_t ) ( ( -20 ) + ( rsrqValue * 0.5 ) );
}
else
{
rsrqDb = CELLULAR_INVALID_SIGNAL_VALUE;
}
return rsrqDb;
}
/*-----------------------------------------------------------*/
/* 0 rsrp < -140 dBm
* 1 -140 dBm <= rsrp < -139 dBm
* 2 -139 dBm <= rsrp < -138 dBm
* ...
* 95 -46 dBm <= rsrp < -45 dBm
* 96 -45 dBm <= rsrp < -44 dBm
* 97 -44 dBm <= rsrp
* 255 Not known or not detectable. */
static int16_t convertCesqSignalRsrp( int32_t rsrpValue )
{
int16_t rsrpDb = 0;
if( ( rsrpValue >= 0 ) && ( rsrpValue <= 97 ) )
{
rsrpDb = ( int16_t ) ( ( -141 ) + ( rsrpValue ) );
}
else
{
rsrpDb = CELLULAR_INVALID_SIGNAL_VALUE;
}
return rsrpDb;
}
/*-----------------------------------------------------------*/
static bool _parseSignalQuality( char * pQcsqPayload,
CellularSignalInfo_t * pSignalInfo )
{
char * pToken = NULL, * pTmpQcsqPayload = pQcsqPayload;
int32_t tempValue = 0;
int16_t berValue = 0;
bool parseStatus = true;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
CellularError_t cellularStatus = CELLULAR_SUCCESS;
/* The cesq payload format is <rxlev>,<ber>,<rscp>,<ecno>,<rsrq>,<rsrp>. */
/* rxlev. */
atCoreStatus = Cellular_ATGetNextTok( &pTmpQcsqPayload, &pToken );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
pSignalInfo->rssi = convertCesqSignalRxlev( tempValue );
}
else
{
LogError( ( "_parseSignalQuality: Error in processing RXLEV. Token %s", pToken ) );
parseStatus = false;
}
}
/* 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 ) )
{
/* As RXQUAL values in the table in 3GPP TS 45.008 [20] subclause 8.2.4.
* The CESQ ber signal value has the same scale with the AT+CSQ ber signal value. */
cellularStatus = _Cellular_ConvertCsqSignalBer( ( int16_t ) tempValue, &berValue );
if( cellularStatus == CELLULAR_SUCCESS )
{
pSignalInfo->ber = berValue;
}
else
{
atCoreStatus = CELLULAR_AT_ERROR;
}
}
else
{
LogError( ( "_parseSignalQuality: 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 );
}
/* 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 )
{
pSignalInfo->rsrq = convertCesqSignalRsrq( tempValue );
}
else
{
LogError( ( "_parseSignalQuality: Error in processing RSRQ. Token %s", pToken ) );
parseStatus = false;
}
}
/* 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 )
{
pSignalInfo->rsrp = convertCesqSignalRsrp( tempValue );
}
else
{
LogError( ( "_parseSignalQuality: Error in processing RSRP. Token %s", pToken ) );
parseStatus = false;
}
}
return parseStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library types. */
/* coverity[misra_c_2012_rule_8_13_violation] */
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;
if( pContext == NULL )
{
LogError( ( "GetSignalInfo: Invalid handle" ) );
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
}
else if( ( pSignalInfo == NULL ) || ( dataLen != sizeof( CellularSignalInfo_t ) ) )
{
LogError( ( "GetSignalInfo: Invalid param" ) );
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;
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pInputLine );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
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;
}
/*-----------------------------------------------------------*/
/* 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 )
{
( void ) cellularHandle;
( void ) contextId;
( void ) pDnsServerAddress;
/* Modem use dynamic DNS addresses. Return unsupported. */
return CELLULAR_UNSUPPORTED;
}
/*-----------------------------------------------------------*/
/* 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 = CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_MS;
uint32_t recvLen = bufferLength;
_socketDataRecv_t dataRecv =
{
pReceivedDataLength,
pBuffer
};
CellularAtReq_t atReqSocketRecv =
{
cmdBuf,
CELLULAR_AT_MULTI_DATA_WO_PREFIX,
"CONNECT",
_Cellular_RecvFuncData,
( void * ) &dataRecv,
bufferLength,
};
socketStat_t socketStat = { 0 };
uint32_t socktCmdDataLength = 0;
uint32_t sessionId = 0;
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogError( ( "_Cellular_CheckLibraryStatus failed." ) );
}
else if( socketHandle == NULL )
{
LogError( ( "_Cellular_RecvData: Invalid socket handle." ) );
cellularStatus = CELLULAR_INVALID_HANDLE;
}
else if( ( pBuffer == NULL ) || ( pReceivedDataLength == NULL ) || ( bufferLength == 0U ) )
{
LogError( ( "_Cellular_RecvData: Bad input Param." ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else if( ( socketHandle->socketState != SOCKETSTATE_CONNECTED ) && ( socketHandle->socketState != SOCKETSTATE_DISCONNECTED ) )
{
/* Check the socket connection state. */
/* For SOCKETSTATE_DISCONNECTED, there may be packets that can be read even though socket is disconnected by remote. */
LogInfo( ( "Cellular_SocketRecv: socket state %d is not connected.", socketHandle->socketState ) );
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_SocketRecv : invalid session ID for socket index %u",
socketHandle->socketId ) );
cellularStatus = CELLULAR_INVALID_HANDLE;
}
}
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Calculate the read length. */
cellularStatus = _Cellular_GetSocketStat( cellularHandle, socketHandle, &socketStat );
if( cellularStatus == CELLULAR_SUCCESS )
{
socktCmdDataLength = socketStat.rcvData;
}
else
{
socktCmdDataLength = 0;
}
/* Update recvLen to maximum module length. */
if( CELLULAR_MAX_RECV_DATA_LEN <= bufferLength )
{
recvLen = ( uint32_t ) CELLULAR_MAX_RECV_DATA_LEN;
}
/* Update the recvLen to available data length in cellular module. */
if( recvLen > socktCmdDataLength )
{
recvLen = socktCmdDataLength;
}
*pReceivedDataLength = recvLen;
socktCmdDataLength = recvLen;
/* 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+KTCPRCV=", sessionId, recvLen );
pktStatus = _Cellular_TimeoutAtcmdDataRecvRequestWithCallback( pContext,
atReqSocketRecv, recvTimeout, socketRecvDataPrefix, &socktCmdDataLength );
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;
}
/*-----------------------------------------------------------*/
/* 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 = CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_MS;
char cmdBuf[ CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ] = { '\0' };
CellularAtReq_t atReqSocketSend =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
CellularAtDataReq_t atDataReqSocketSend =
{
pData,
dataLength,
pSentDataLength,
( const uint8_t * ) SOCKET_END_PATTERN,
SOCKET_END_PATTERN_LEN
};
uint32_t sessionId = 0;
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogError( ( "_Cellular_CheckLibraryStatus failed." ) );
}
else if( socketHandle == NULL )
{
LogError( ( "Cellular_SocketSend: Invalid socket handle." ) );
cellularStatus = CELLULAR_INVALID_HANDLE;
}
else if( ( pData == NULL ) || ( pSentDataLength == NULL ) || ( dataLength == 0U ) )
{
LogError( ( "Cellular_SocketSend: Invalid parameter." ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else if( socketHandle->socketState != SOCKETSTATE_CONNECTED )
{
/* Check the socket connection state. */
LogInfo( ( "Cellular_SocketSend: socket state %d is not connected.", socketHandle->socketState ) );
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;
}
/* 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]. */
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "%s%u,%u",
"AT+KTCPSND=", sessionId, atDataReqSocketSend.dataLen );
pktStatus = _Cellular_TimeoutAtcmdDataSendSuccessToken( pContext, atReqSocketSend, atDataReqSocketSend,
CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_MS, sendTimeout,
_socketSendSuccesTokenTable, _socketSendSuccesTokenTableLength );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
if( socketHandle->socketState == SOCKETSTATE_DISCONNECTED )
{
LogWarn( ( "Cellular_SocketSend: Data send fail. Socket is closed during the send operation." ) );
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 =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
uint32_t sessionId = 0U;
cellularModuleContext_t * pModuleContext = NULL;
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( socketHandle == NULL )
{
cellularStatus = CELLULAR_INVALID_HANDLE;
}
else
{
if( socketHandle->socketState == SOCKETSTATE_CONNECTING )
{
LogWarn( ( "Cellular_SocketClose: Socket state is SOCKETSTATE_CONNECTING." ) );
}
cellularStatus = _Cellular_GetModuleContext( pContext, ( void ** ) &pModuleContext );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
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 )
{
/* 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%lu,1",
"AT+KTCPCLOSE=", sessionId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketClose,
CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_MS );
/* Delete the socket config. */
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogWarn( ( "Cellular_SocketClose: AT+KTCPCLOSE fail, PktRet: %d", pktStatus ) );
}
}
if( ( socketHandle->socketState == SOCKETSTATE_CONNECTED ) ||
( socketHandle->socketState == SOCKETSTATE_CONNECTING ) ||
( socketHandle->socketState == SOCKETSTATE_DISCONNECTED ) )
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "%s%lu",
"AT+KTCPDEL=", sessionId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketClose,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_SocketClose: AT+KTCPDEL fail, PktRet: %d", pktStatus ) );
}
}
/* Ignore the result from the info, and force to remove the socket. */
cellularStatus = _Cellular_RemoveSocketData( pContext, socketHandle );
}
return CELLULAR_SUCCESS;
}
/*-----------------------------------------------------------*/
/* 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 =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
cellularModuleContext_t * pModuleContext = NULL;
/* Make sure the library is open. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogError( ( "_Cellular_CheckLibraryStatus failed." ) );
}
else if( pRemoteSocketAddress == NULL )
{
LogError( ( "Cellular_SocketConnect: Invalid socket address." ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else if( socketHandle == NULL )
{
LogError( ( "Cellular_SocketConnect: Invalid socket handle." ) );
cellularStatus = CELLULAR_INVALID_HANDLE;
}
else if( ( socketHandle->socketState == SOCKETSTATE_CONNECTED ) || ( socketHandle->socketState == SOCKETSTATE_CONNECTING ) )
{
LogError( ( "Cellular_SocketConnect: Not allowed in state %d.", socketHandle->socketState ) );
cellularStatus = CELLULAR_NOT_ALLOWED;
}
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_getTcpCfgSessionId( 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 )
{
/* Set the socket state to connecting state. If cellular modem returns error,
* revert the state to allocated state. */
socketHandle->socketState = SOCKETSTATE_CONNECTING;
/* 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+KTCPCNX=%u", sessionId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSocketConnect,
CELLULAR_HL7802_AT_TIMEOUT_30_SECONDS_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_SocketConnect: Socket connect failed, cmdBuf:%s, PktRet: %d", cmdBuf, pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
/* Revert the state to allocated state. */
socketHandle->socketState = SOCKETSTATE_ALLOCATED;
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library API. */
/* coverity[misra_c_2012_rule_8_7_violation] */
CellularError_t Cellular_GetSimCardStatus( CellularHandle_t cellularHandle,
CellularSimCardStatus_t * pSimCardStatus )
{
CellularError_t cellularStatus = CELLULAR_SUCCESS;
/* Parameters are checked in this API. */
cellularStatus = Cellular_CommonGetSimCardLockStatus( cellularHandle, pSimCardStatus );
if( cellularStatus == CELLULAR_SUCCESS )
{
cellularStatus = Cellular_CommonGetSimCardLockStatus( cellularHandle, pSimCardStatus );
if( ( cellularStatus == CELLULAR_SUCCESS ) &&
( 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;
}
}
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 )
{
( void ) cellularHandle;
( void ) signalStrengthChangedCallback;
( void ) pCallbackContext;
return CELLULAR_UNSUPPORTED;
}
/*-----------------------------------------------------------*/
/* 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 )
{
( void ) cellularHandle;
( void ) contextId;
( void ) pcHostName;
( void ) pResolvedAddress;
return CELLULAR_UNSUPPORTED;
}
/*-----------------------------------------------------------*/
/* 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' };
CellularAtReq_t atReqDeactPdn =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
cellularStatus = _Cellular_IsValidPdn( contextId );
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Make sure the library is open. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s=%u", "AT+KCNXDOWN", contextId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqDeactPdn,
CELLULAR_HL7802_AT_KCNXDOWN_TIMEOUT_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_DeactivatePdn: can't deactivate PDN, PktRet: %d", pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
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;
}
/*-----------------------------------------------------------*/
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,
pPacketSwitchStatus,
sizeof( bool ),
};
/* Internal function. Callee check parameters. */
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqPacketSwitchStatus,
CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_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' };
bool packetSwitchStatus = false;
CellularAtReq_t atReqActPdn =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
cellularStatus = _Cellular_IsValidPdn( contextId );
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Make sure the library is open. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Check packet switch attach first. If not attached, attach packet switch first. */
cellularStatus = _Cellular_GetPacketSwitchStatus( cellularHandle, &packetSwitchStatus );
if( ( cellularStatus == CELLULAR_SUCCESS ) && ( packetSwitchStatus == false ) )
{
LogError( ( "Activate Packet switch" ) );
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s", "AT+CGATT=1" );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqActPdn,
CELLULAR_HL7802_AT_TIMEOUT_60_SECONDS_MS );
}
else if( cellularStatus != CELLULAR_SUCCESS )
{
LogError( ( "Packet switch query failed" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else
{
LogInfo( ( "Packet switch attached" ) );
}
/* Check the current attach status. If not activated, activate the PDN context ID. */
if( pktStatus == CELLULAR_PKT_STATUS_OK )
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s=%u", "AT+KCNXUP", contextId );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqActPdn,
CELLULAR_HL7802_AT_KCNXUP_TIMEOUT_MS );
}
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_ActivatePdn: can't activate PDN, PktRet: %d", pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t parsePdnStatusContextId( char * pToken,
CellularPdnStatus_t * pPdnStatusBuffers )
{
int32_t tempValue = 0;
CellularATError_t atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= ( int32_t ) CELLULAR_PDN_CONTEXT_ID_MIN ) &&
( tempValue <= ( int32_t ) CELLULAR_PDN_CONTEXT_ID_MAX ) )
{
pPdnStatusBuffers->contextId = ( uint8_t ) tempValue;
}
else
{
LogError( ( "Error in Processing Context Id. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t parsePdnStatusContextState( char * pToken,
CellularPdnStatus_t * pPdnStatusBuffers )
{
int32_t tempValue = 0;
CellularATError_t atCoreStatus = Cellular_ATStrtoi( pToken, 10, &tempValue );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
if( ( tempValue >= 0 ) &&
( tempValue <= ( int32_t ) UINT8_MAX ) )
{
/* Remap the status. */
switch( tempValue )
{
case CELLULAR_PDN_STATE_CONNECTED:
pPdnStatusBuffers->state = 1;
break;
case CELLULAR_PDN_STATE_DISCONNECTED:
case CELLULAR_PDN_STATE_CONNECTING:
case CELLULAR_PDN_STATE_IDLE:
case CELLULAR_PDN_STATE_DISCONNECTING:
pPdnStatusBuffers->state = 0;
break;
default:
LogError( ( "parsePdnStatusContextState unknown status : %d", tempValue ) );
atCoreStatus = CELLULAR_AT_ERROR;
break;
}
}
else
{
LogError( ( "Error in processing PDN Status Buffer state. Token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t parsePdnStatusContextType( char * pToken,
CellularPdnStatus_t * pPdnStatusBuffers )
{
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
if( strcmp( pToken, "IPV4" ) == 0 )
{
pPdnStatusBuffers->pdnContextType = CELLULAR_PDN_CONTEXT_IPV4;
pPdnStatusBuffers->ipAddress.ipAddressType = CELLULAR_IP_ADDRESS_V4;
}
else if( strcmp( pToken, "IPV6" ) == 0 )
{
pPdnStatusBuffers->pdnContextType = CELLULAR_PDN_CONTEXT_IPV6;
pPdnStatusBuffers->ipAddress.ipAddressType = CELLULAR_IP_ADDRESS_V6;
}
else if( strcmp( pToken, "IPV4V6" ) == 0 )
{
pPdnStatusBuffers->pdnContextType = CELLULAR_PDN_CONTEXT_IPV4V6;
/* The IP address depends on the format returned. */
}
else
{
LogError( ( "parsePdnStatusContextType : unknown token %s", pToken ) );
atCoreStatus = CELLULAR_AT_ERROR;
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t getPdnStatusParseToken( char * pToken,
uint8_t tokenIndex,
CellularPdnStatus_t * pPdnStatusBuffers )
{
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
switch( tokenIndex )
{
case ( CELLULAR_PDN_STATUS_POS_CONTEXT_ID ):
LogDebug( ( "CELLULAR_PDN_STATUS_POS_CONTEXT_ID: %s", pToken ) );
atCoreStatus = parsePdnStatusContextId( pToken, pPdnStatusBuffers );
break;
case ( CELLULAR_PDN_STATUS_POS_AF ):
LogDebug( ( "CELLULAR_PDN_STATUS_POS_AF: %s", pToken ) );
atCoreStatus = parsePdnStatusContextType( pToken, pPdnStatusBuffers );
break;
case ( CELLULAR_PDN_STATUS_POS_STATE ):
LogDebug( ( "CELLULAR_PDN_STATUS_POS_STATE: %s", pToken ) );
atCoreStatus = parsePdnStatusContextState( pToken, pPdnStatusBuffers );
break;
case ( CELLULAR_PDN_STATUS_POS_APN ):
case ( CELLULAR_PDN_STATUS_POS_LOGIN ):
case ( CELLULAR_PDN_STATUS_POS_PASSWORD ):
case ( CELLULAR_PDN_STATUS_POS_IP ):
case ( CELLULAR_PDN_STATUS_POS_GPRS ):
case ( CELLULAR_PDN_STATUS_POS_DNS1 ):
case ( CELLULAR_PDN_STATUS_POS_DNS2 ):
LogDebug( ( "CELLULAR_PDN_STATUS Ignored index %d : %s", tokenIndex, pToken ) );
atCoreStatus = CELLULAR_AT_SUCCESS;
break;
default:
LogError( ( "Unknown token in getPdnStatusParseToken %s %d",
pToken, tokenIndex ) );
atCoreStatus = CELLULAR_AT_ERROR;
break;
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
static CellularATError_t getPdnStatusParseLine( char * pRespLine,
CellularPdnStatus_t * pPdnStatusBuffers )
{
char * pToken = NULL;
char * pLocalRespLine = pRespLine;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
uint8_t tokenIndex = 0;
atCoreStatus = Cellular_ATRemovePrefix( &pLocalRespLine );
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pLocalRespLine );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
atCoreStatus = Cellular_ATGetNextTok( &pLocalRespLine, &pToken );
}
if( atCoreStatus == CELLULAR_AT_SUCCESS )
{
tokenIndex = 0;
while( ( pToken != NULL ) && ( atCoreStatus == CELLULAR_AT_SUCCESS ) )
{
atCoreStatus = getPdnStatusParseToken( pToken, tokenIndex, pPdnStatusBuffers );
if( atCoreStatus != CELLULAR_AT_SUCCESS )
{
LogError( ( "getPdnStatusParseToken %s index %d failed", pToken, tokenIndex ) );
}
tokenIndex++;
if( pLocalRespLine[ 0 ] == ',' )
{
pToken = pLocalRespLine;
pLocalRespLine[ 0 ] = '\0';
pLocalRespLine = &pLocalRespLine[ 1 ];
}
else
{
if( Cellular_ATGetNextTok( &pLocalRespLine, &pToken ) != CELLULAR_AT_SUCCESS )
{
break;
}
}
}
}
return atCoreStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library types. */
/* coverity[misra_c_2012_rule_8_13_violation] */
static CellularPktStatus_t _Cellular_RecvFuncGetPdnStatus( CellularContext_t * pContext,
const CellularATCommandResponse_t * pAtResp,
void * pData,
uint16_t dataLen )
{
char * pRespLine = NULL;
CellularPdnStatus_t * pPdnStatusBuffers = ( CellularPdnStatus_t * ) pData;
uint8_t numStatusBuffers = ( uint8_t ) dataLen;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
const CellularATCommandLine_t * pCommnadItem = NULL;
if( pContext == NULL )
{
LogError( ( "GetPdnStatus: invalid context" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else if( ( pAtResp == NULL ) )
{
LogError( ( "GetPdnStatus: Response is invalid" ) );
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
}
else if( ( pPdnStatusBuffers == NULL ) || ( numStatusBuffers < 1U ) )
{
LogError( ( "GetPdnStatus: PDN Status bad parameters" ) );
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
}
else if( ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
{
LogError( ( "GetPdnStatus: no activated PDN" ) );
pPdnStatusBuffers[ 0 ].contextId = INVALID_PDN_INDEX;
pktStatus = CELLULAR_PKT_STATUS_OK;
}
else
{
pRespLine = pAtResp->pItm->pLine;
pCommnadItem = pAtResp->pItm;
while( ( numStatusBuffers != 0U ) && ( pCommnadItem != NULL ) )
{
pRespLine = pCommnadItem->pLine;
atCoreStatus = getPdnStatusParseLine( pRespLine, pPdnStatusBuffers );
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "getPdnStatusParseLine parse %s failed", pRespLine ) );
break;
}
pPdnStatusBuffers++;
numStatusBuffers--;
pCommnadItem = pCommnadItem->pNext;
}
}
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_GetPdnStatus( CellularHandle_t cellularHandle,
CellularPdnStatus_t * pPdnStatusBuffers,
uint8_t numStatusBuffers,
uint8_t * pNumStatus )
{
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
const CellularPdnStatus_t * pTempPdnStatusBuffer = pPdnStatusBuffers;
uint8_t numBuffers = 0;
CellularAtReq_t atReqGetPdnStatus =
{
"AT+KCNXCFG?",
CELLULAR_AT_WITH_PREFIX,
"+KCNXCFG",
_Cellular_RecvFuncGetPdnStatus,
pPdnStatusBuffers,
numStatusBuffers,
};
/* Make sure the library is open. */
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( ( pTempPdnStatusBuffer == NULL ) || ( pNumStatus == NULL ) || ( numStatusBuffers < 1u ) )
{
LogDebug( ( "_Cellular_GetPdnStatus: Bad input Parameter " ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqGetPdnStatus,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Populate the Valid number of statuses. */
*pNumStatus = 0;
numBuffers = numStatusBuffers;
while( numBuffers != 0U )
{
/* Check if the PDN state is valid. The context ID of the first
* invalid PDN status is set to FF. */
if( pTempPdnStatusBuffer->contextId <= CELLULAR_PDN_CONTEXT_ID_MAX )
{
( *pNumStatus ) += 1U;
}
else
{
break;
}
numBuffers--;
pTempPdnStatusBuffer++;
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library API. */
/* coverity[misra_c_2012_rule_8_7_violation] */
CellularError_t Cellular_GetEidrxSettings( CellularHandle_t cellularHandle,
CellularEidrxSettingsList_t * pEidrxSettingsList )
{
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
CellularError_t cellularStatus = CELLULAR_SUCCESS;
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
CellularAtReq_t atReqGetEidrx =
{
"AT+KEDRXCFG?",
CELLULAR_AT_MULTI_WITH_PREFIX,
"+KEDRXCFG",
_Cellular_RecvFuncGetEidrxSettings,
pEidrxSettingsList,
CELLULAR_EDRX_LIST_MAX_SIZE,
};
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( pEidrxSettingsList == NULL )
{
LogDebug( ( "Cellular_GetEidrxSettings : Bad parameter" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
( void ) memset( pEidrxSettingsList, 0, sizeof( CellularEidrxSettingsList_t ) );
/* Query the pEidrxSettings from the network. */
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqGetEidrx,
CELLULAR_HL7802_AT_KEDRXCFG_TIMEOUT_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_GetEidrxSettings: couldn't retrieve Eidrx settings" ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
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 =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( pEidrxSettings == NULL )
{
LogDebug( ( "Cellular_SetEidrxSettings : Bad parameter" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
/* 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]. */
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "%s%u,%u,%u,%u",
"AT+KEDRXCFG=",
pEidrxSettings->mode,
pEidrxSettings->rat,
pEidrxSettings->requestedEdrxVaue,
pEidrxSettings->pagingTimeWindow );
LogDebug( ( "Eidrx setting: %s ", cmdBuf ) );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSetEidrx,
CELLULAR_HL7802_AT_KEDRXCFG_TIMEOUT_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "_Cellular_SetEidrxSettings: couldn't set Eidrx settings" ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
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 =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( ( pRatPriorities == NULL ) || ( ratPrioritiesLength == 0U ) ||
( ratPrioritiesLength > ( uint8_t ) CELLULAR_MAX_RAT_PRIORITY_COUNT ) )
{
LogDebug( ( "Cellular_SetRatPriority : Bad parameter" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
/* Reboot is required for this command. */
( void ) strcpy( cmdBuf, "AT+KSELACQ=0," );
for( i = 0; i < ratPrioritiesLength; i++ )
{
if( pRatPriorities[ i ] == CELLULAR_RAT_CATM1 )
{
( void ) strcat( cmdBuf, "1" );
}
else if( pRatPriorities[ i ] == CELLULAR_RAT_NBIOT )
{
( void ) strcat( cmdBuf, "2" );
}
else if( pRatPriorities[ i ] == CELLULAR_RAT_GSM )
{
( void ) strcat( cmdBuf, "3" );
}
else
{
LogDebug( ( "Cellular_SetRatPriority : unsupported mode %d", pRatPriorities[ i ] ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
break;
}
if( i != ( ratPrioritiesLength - 1 ) )
{
( void ) strcat( cmdBuf, "," );
}
}
LogError( ( " setRatPriority cmdbuf %s", cmdBuf ) );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSetRatPriority,
CELLULAR_HL7802_AT_KSELACQ_TIMEOUT_MS );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
/* 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;
uint32_t ratIndex = 0;
CellularAtReq_t atReqSetRatPriority =
{
"AT+KSELACQ?",
CELLULAR_AT_WITH_PREFIX,
"+KSELACQ",
_Cellular_RecvFuncGetRatPriority,
pRatPriorities,
( uint16_t ) ratPrioritiesLength,
};
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( ( pRatPriorities == NULL ) || ( ratPrioritiesLength == 0U ) ||
( ratPrioritiesLength > ( uint8_t ) CELLULAR_MAX_RAT_PRIORITY_COUNT ) ||
( pReceiveRatPrioritesLength == NULL ) )
{
LogDebug( ( "Cellular_GetRatPriority : Bad parameter" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atReqSetRatPriority,
CELLULAR_HL7802_AT_KSELACQ_TIMEOUT_MS );
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 );
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
/* FreeRTOS Cellular Library API. */
/* coverity[misra_c_2012_rule_8_7_violation] */
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+CESQ",
CELLULAR_AT_WITH_PREFIX,
"+CESQ",
_Cellular_RecvFuncGetSignalInfo,
pSignalInfo,
sizeof( CellularSignalInfo_t ),
};
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
if( cellularStatus != CELLULAR_SUCCESS )
{
LogDebug( ( "_Cellular_CheckLibraryStatus failed" ) );
}
else if( pSignalInfo == NULL )
{
LogDebug( ( "Cellular_GetSignalInfo : Bad parameter" ) );
cellularStatus = CELLULAR_BAD_PARAMETER;
}
else
{
cellularStatus = _Cellular_GetCurrentRat( pContext, &rat );
}
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Init the signal value. */
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_TimeoutAtcmdRequestWithCallback( pContext, atReqQuerySignalInfo,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
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_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' };
CellularAtReq_t atGprsConnectionConfighReq =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
/* Parameters are also checked in Cellular_CommonSetPdnConfig. */
cellularStatus = Cellular_CommonSetPdnConfig( cellularHandle, contextId, pPdnConfig );
/* Set the GPRS connection configuration. */
if( cellularStatus == CELLULAR_SUCCESS )
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "AT+KCNXCFG=%u,\"GPRS\",\"%s\"",
contextId, pPdnConfig->apnName );
LogDebug( ( "cmd %s", cmdBuf ) );
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atGprsConnectionConfighReq,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_PacketSwitchAttach: failed, PktRet: %d", pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
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 atKsleepReq =
{
cmdBuf,
CELLULAR_AT_NO_RESULT,
NULL,
NULL,
NULL,
0,
};
/* Parameters are checked in this function. */
cellularStatus = Cellular_CommonSetPsmSettings( cellularHandle, pPsmSettings );
if( cellularStatus == CELLULAR_SUCCESS )
{
/* Sleep mode driven by a HW signal (DTR). Sleep level is hibernate.
* Can be woken up by WAKE_UP signal or T3412 timer expiration. */
if( pPsmSettings->mode == 1 )
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "AT+KSLEEP=0,2,30" );
}
else
{
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_MAX_SIZE, "AT+KSLEEP=2" );
}
pktStatus = _Cellular_TimeoutAtcmdRequestWithCallback( pContext, atKsleepReq,
CELLULAR_HL7802_AT_TIMEOUT_2_SECONDS_MS );
if( pktStatus != CELLULAR_PKT_STATUS_OK )
{
LogError( ( "Cellular_PacketSwitchAttach: failed, PktRet: %d", pktStatus ) );
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
}
}
return cellularStatus;
}
/*-----------------------------------------------------------*/
CellularError_t Cellular_Init( CellularHandle_t * pCellularHandle,
const CellularCommInterface_t * pCommInterface )
{
CellularTokenTable_t cellularTokenTable =
{
.pCellularUrcHandlerTable = CellularUrcHandlerTable,
.cellularPrefixToParserMapSize = CellularUrcHandlerTableSize,
.pCellularSrcTokenErrorTable = CellularSrcTokenErrorTable,
.cellularSrcTokenErrorTableSize = CellularSrcTokenErrorTableSize,
.pCellularSrcTokenSuccessTable = CellularSrcTokenSuccessTable,
.cellularSrcTokenSuccessTableSize = CellularSrcTokenSuccessTableSize,
.pCellularUrcTokenWoPrefixTable = CellularUrcTokenWoPrefixTable,
.cellularUrcTokenWoPrefixTableSize = CellularUrcTokenWoPrefixTableSize,
.pCellularSrcExtraTokenSuccessTable = NULL,
.cellularSrcExtraTokenSuccessTableSize = 0
};
return Cellular_CommonInit( pCellularHandle, pCommInterface, &cellularTokenTable );
}
/*-----------------------------------------------------------*/