2975 lines
107 KiB
C
2975 lines
107 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
|
|
*/
|
|
|
|
/**
|
|
* @brief FreeRTOS Cellular Library API implemenation with 3GPP AT command.
|
|
*/
|
|
|
|
/* Standard includes. */
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#include "cellular_platform.h"
|
|
|
|
#ifndef CELLULAR_DO_NOT_USE_CUSTOM_CONFIG
|
|
/* Include custom config file before other headers. */
|
|
#include "cellular_config.h"
|
|
#endif
|
|
#include "cellular_config_defaults.h"
|
|
#include "cellular_internal.h"
|
|
#include "cellular_common_internal.h"
|
|
#include "cellular_common_api.h"
|
|
#include "cellular_at_core.h"
|
|
#include "cellular_types.h"
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
#define CELLULAR_CEDRXS_POS_ACT ( 0U )
|
|
#define CELLULAR_CEDRXS_POS_VALUE ( 1U )
|
|
#define CELLULAR_CEDRXS_MAX_ENTRY ( 4U )
|
|
|
|
#define CELLULAR_AT_CMD_TYPICAL_MAX_SIZE ( 32U )
|
|
|
|
#define PDN_ACT_PACKET_REQ_TIMEOUT_MS ( 150000UL )
|
|
|
|
#define INVALID_PDN_INDEX ( 0xFFU )
|
|
|
|
/* Length of HPLMN including RAT. */
|
|
#define CRSM_HPLMN_RAT_LENGTH ( 9U )
|
|
|
|
#define PRINTF_BINARY_PATTERN_INT4 "%c%c%c%c"
|
|
#define PRINTF_BYTE_TO_BINARY_INT4( i ) \
|
|
( ( ( ( i ) & 0x08U ) != 0U ) ? '1' : '0' ), \
|
|
( ( ( ( i ) & 0x04U ) != 0U ) ? '1' : '0' ), \
|
|
( ( ( ( i ) & 0x02U ) != 0U ) ? '1' : '0' ), \
|
|
( ( ( ( i ) & 0x01U ) != 0U ) ? '1' : '0' )
|
|
|
|
#define PRINTF_BINARY_PATTERN_INT8 \
|
|
PRINTF_BINARY_PATTERN_INT4 PRINTF_BINARY_PATTERN_INT4
|
|
#define PRINTF_BYTE_TO_BINARY_INT8( i ) \
|
|
PRINTF_BYTE_TO_BINARY_INT4( ( i ) >> 4 ), PRINTF_BYTE_TO_BINARY_INT4( i )
|
|
|
|
#define CPSMS_POS_MODE ( 0U )
|
|
#define CPSMS_POS_RAU ( 1U )
|
|
#define CPSMS_POS_RDY_TIMER ( 2U )
|
|
#define CPSMS_POS_TAU ( 3U )
|
|
#define CPSMS_POS_ACTIVE_TIME ( 4U )
|
|
|
|
#define T3324_TIMER_UNIT( x ) ( ( uint32_t ) ( ( ( x ) & 0x000000E0U ) >> 5U ) ) /* Bits 6, 7, 8. */
|
|
#define T3324_TIMER_VALUE( x ) ( ( uint32_t ) ( ( x ) & 0x0000001FU ) )
|
|
#define T3324_TIMER_DEACTIVATED ( 0xFFFFFFFFU )
|
|
|
|
#define T3324_TIMER_UNIT_2SECONDS ( 0U )
|
|
#define T3324_TIMER_UNIT_1MINUTE ( 1U )
|
|
#define T3324_TIMER_UNIT_DECIHOURS ( 2U )
|
|
#define T3324_TIMER_UNIT_DEACTIVATED ( 7U )
|
|
|
|
#define T3412_TIMER_UNIT( x ) ( ( uint32_t ) ( ( ( x ) & 0x000000E0U ) >> 5U ) ) /* Bits 6, 7, 8. */
|
|
#define T3412_TIMER_VALUE( x ) ( ( uint32_t ) ( ( x ) & 0x0000001FU ) )
|
|
#define T3412_TIMER_DEACTIVATED ( 0xFFFFFFFFU )
|
|
|
|
#define T3412_TIMER_UNIT_10MINUTES ( 0U )
|
|
#define T3412_TIMER_UNIT_1HOURS ( 1U )
|
|
#define T3412_TIMER_UNIT_10HOURS ( 2U )
|
|
#define T3412_TIMER_UNIT_2SECONDS ( 3U )
|
|
#define T3412_TIMER_UNIT_30SECONDS ( 4U )
|
|
#define T3412_TIMER_UNIT_1MINUTES ( 5U )
|
|
#define T3412_TIMER_UNIT_DEACTIVATED ( 7U )
|
|
|
|
#define CELULAR_PDN_CONTEXT_TYPE_MAX_SIZE ( 7U ) /* The length of "IPV4V6" + 1. */
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/**
|
|
* @brief operator information.
|
|
*/
|
|
typedef struct cellularOperatorInfo
|
|
{
|
|
CellularPlmnInfo_t plmnInfo; /* Device registered PLMN info (MCC and MNC). */
|
|
CellularRat_t rat; /* Device registered Radio Access Technology (Cat-M, Cat-NB, GPRS etc). */
|
|
CellularNetworkRegistrationMode_t networkRegMode; /* Network Registered mode of the device (Manual, Auto etc). */
|
|
CellularOperatorNameFormat_t operatorNameFormat; /* Format of registered network operator name. */
|
|
char operatorName[ CELLULAR_NETWORK_NAME_MAX_SIZE + 1 ]; /* Registered network operator name. */
|
|
} cellularOperatorInfo_t;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _parseTimeZoneInCCLKResponse( char ** ppToken,
|
|
bool * pTimeZoneSignNegative,
|
|
const char * pTimeZoneResp,
|
|
CellularTime_t * pTimeInfo );
|
|
static CellularPktStatus_t _parseYearMonthDayInCCLKResponse( char ** ppToken,
|
|
char ** ppTimeZoneResp,
|
|
CellularTime_t * pTimeInfo );
|
|
static CellularPktStatus_t _parseTimeInCCLKResponse( char ** ppToken,
|
|
bool timeZoneSignNegative,
|
|
char ** ppTimeZoneResp,
|
|
CellularTime_t * pTimeInfo );
|
|
static CellularPktStatus_t _parseTimeZoneInfo( char * pTimeZoneResp,
|
|
CellularTime_t * pTimeInfo );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetNetworkTime( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetFirmwareVersion( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetImei( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetModelId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetManufactureId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetNetworkReg( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularError_t queryNetworkStatus( CellularContext_t * pContext,
|
|
const char * pCommand,
|
|
const char * pPrefix,
|
|
CellularNetworkRegType_t regType );
|
|
static bool _parseCopsRegModeToken( char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static bool _parseCopsNetworkNameFormatToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static bool _parseCopsNetworkNameToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static bool _parseCopsRatToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static CellularATError_t _parseCops( char * pCopsResponse,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static CellularPktStatus_t _Cellular_RecvFuncUpdateMccMnc( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncIpAddress( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
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 CellularError_t atcmdUpdateMccMnc( CellularContext_t * pContext,
|
|
cellularOperatorInfo_t * pOperatorInfo );
|
|
static CellularError_t atcmdQueryRegStatus( CellularContext_t * pContext,
|
|
CellularServiceStatus_t * pServiceStatus );
|
|
static CellularATError_t parseT3412TimerValue( char * pToken,
|
|
uint32_t * pTimerValueSeconds );
|
|
static CellularATError_t parseT3324TimerValue( char * pToken,
|
|
uint32_t * pTimerValueSeconds );
|
|
static CellularSimCardLockState_t _getSimLockState( char * pToken );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSimLockStatus( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static bool _checkCrsmMemoryStatus( const char * pToken );
|
|
static bool _checkCrsmReadStatus( const char * pToken );
|
|
static bool _parseHplmn( char * pToken,
|
|
void * pData );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetHplmn( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetIccid( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetImsi( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
static uint32_t appendBinaryPattern( char * cmdBuf,
|
|
uint32_t cmdLen,
|
|
uint32_t value,
|
|
bool endOfString );
|
|
static CellularATError_t parseCpsmsMode( char * pToken,
|
|
CellularPsmSettings_t * pPsmSettings );
|
|
static CellularATError_t parseGetPsmToken( char * pToken,
|
|
uint8_t tokenIndex,
|
|
CellularPsmSettings_t * pPsmSettings );
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetPsmSettings( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen );
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _parseTimeZoneInCCLKResponse( char ** ppToken,
|
|
bool * pTimeZoneSignNegative,
|
|
const char * pTimeZoneResp,
|
|
CellularTime_t * pTimeInfo )
|
|
{
|
|
int32_t tempValue = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_ERROR;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
|
|
/* Get Time Zone info. */
|
|
*ppToken = strstr( pTimeZoneResp, "+" );
|
|
|
|
if( *ppToken == NULL )
|
|
{
|
|
*ppToken = strstr( pTimeZoneResp, "-" );
|
|
|
|
if( *ppToken != NULL )
|
|
{
|
|
/* Setting the timeZoneNegative value to 1 for processing seconds later. */
|
|
*pTimeZoneSignNegative = true;
|
|
}
|
|
}
|
|
|
|
if( *ppToken != NULL )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
pTimeInfo->timeZone = tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing TimeZone Information. Token %s", *ppToken ) );
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _parseYearMonthDayInCCLKResponse( char ** ppToken,
|
|
char ** ppTimeZoneResp,
|
|
CellularTime_t * pTimeInfo )
|
|
{
|
|
int32_t tempValue = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT16_MAX ) )
|
|
{
|
|
pTimeInfo->year = ( uint16_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing Year. Token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Getting the next token to process month in the CCLK AT response. */
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( ppTimeZoneResp, "/", ppToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) &&
|
|
( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pTimeInfo->month = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing month. Token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Getting the next token to process date in the CCLK AT response. */
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( ppTimeZoneResp, ",", ppToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pTimeInfo->day = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing Day. token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _parseTimeInCCLKResponse( char ** ppToken,
|
|
bool timeZoneSignNegative,
|
|
char ** ppTimeZoneResp,
|
|
CellularTime_t * pTimeInfo )
|
|
{
|
|
int32_t tempValue = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pTimeInfo->hour = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing Hour. token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Getting the next Token to process Minute in the CCLK AT Response. */
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( ppTimeZoneResp, ":", ppToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pTimeInfo->minute = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing minute. Token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Getting the next token to process Second in the CCLK AT Response.
|
|
* Get the next token based on the signedness of the Timezone. */
|
|
if( !timeZoneSignNegative )
|
|
{
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( ppTimeZoneResp, "+", ppToken );
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( ppTimeZoneResp, "-", ppToken );
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( *ppToken, 10, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pTimeInfo->second = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in Processing Second. Token %s", *ppToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _parseTimeZoneInfo( char * pTimeZoneResp,
|
|
CellularTime_t * pTimeInfo )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pToken = NULL;
|
|
bool timeZoneSignNegative = false;
|
|
char * pTempTimeZoneResp = NULL;
|
|
|
|
pTempTimeZoneResp = pTimeZoneResp;
|
|
( void ) memset( pTimeInfo, 0, sizeof( CellularTime_t ) );
|
|
atCoreStatus = Cellular_ATRemoveOutermostDoubleQuote( &pTempTimeZoneResp );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
pktStatus = _parseTimeZoneInCCLKResponse( &pToken, &timeZoneSignNegative,
|
|
pTempTimeZoneResp, pTimeInfo );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* Getting the next token to process year in the CCLK AT response. */
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( &pTempTimeZoneResp, "/", &pToken );
|
|
}
|
|
|
|
if( ( atCoreStatus == CELLULAR_AT_SUCCESS ) && ( pktStatus == CELLULAR_PKT_STATUS_OK ) )
|
|
{
|
|
pktStatus = _parseYearMonthDayInCCLKResponse( &pToken,
|
|
&pTempTimeZoneResp, pTimeInfo );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* Getting the next token to process hour in the CCLK AT response. */
|
|
atCoreStatus = Cellular_ATGetSpecificNextTok( &pTempTimeZoneResp, ":", &pToken );
|
|
}
|
|
|
|
if( ( atCoreStatus == CELLULAR_AT_SUCCESS ) && ( pktStatus == CELLULAR_PKT_STATUS_OK ) )
|
|
{
|
|
pktStatus = _parseTimeInCCLKResponse( &pToken, timeZoneSignNegative,
|
|
&pTempTimeZoneResp, pTimeInfo );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogDebug( ( "\n TimeZoneInfo: Timezone %d Year %d Month %d day %d Hour %d Minute %d Second %d ",
|
|
pTimeInfo->timeZone, pTimeInfo->year,
|
|
pTimeInfo->month, pTimeInfo->day,
|
|
pTimeInfo->hour, pTimeInfo->minute,
|
|
pTimeInfo->second ) );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetNetworkTime( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetNetworkTime: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetNetworkTime: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen == 0u ) )
|
|
{
|
|
LogError( ( "GetNetworkTime: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
pktStatus = _parseTimeZoneInfo( pRespLine, ( CellularTime_t * ) pData );
|
|
}
|
|
else
|
|
{
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetFirmwareVersion( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetFirmwareVersion: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetFirmwareVersion: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_FW_VERSION_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "GetFirmwareVersion: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveTrailingWhiteSpaces( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
( void ) strncpy( ( char * ) pData, pRespLine, CELLULAR_FW_VERSION_MAX_SIZE );
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetImei( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetImei: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetImei: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_IMEI_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "GetImei: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
( void ) strncpy( ( char * ) pData, pRespLine, CELLULAR_IMEI_MAX_SIZE );
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetModelId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetModelId: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetModelId: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_MODEL_ID_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "GetModelId: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveTrailingWhiteSpaces( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
( void ) strncpy( ( char * ) pData, pRespLine, CELLULAR_MODEL_ID_MAX_SIZE );
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetManufactureId( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetManufactureId: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetManufactureId: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_MANUFACTURE_ID_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "GetManufactureId: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveTrailingWhiteSpaces( pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
( void ) strncpy( ( char * ) pData, pRespLine, CELLULAR_MANUFACTURE_ID_MAX_SIZE );
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetNetworkReg( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pPregLine = NULL;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularNetworkRegType_t regType = CELLULAR_REG_TYPE_UNKNOWN;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPsreg: response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( CellularNetworkRegType_t ) ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetPsreg: ppData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
regType = *( ( CellularNetworkRegType_t * ) pData );
|
|
pPregLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveLeadingWhiteSpaces( &pPregLine );
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
/* Assumption is that the data is null terminated so we don't need the dataLen. */
|
|
_Cellular_LockAtDataMutex( pContext );
|
|
pktStatus = _Cellular_ParseRegStatus( pContext, pPregLine, false, regType );
|
|
_Cellular_UnlockAtDataMutex( pContext );
|
|
}
|
|
|
|
LogDebug( ( "atcmd network register status %d pktStatus:%d", regType, pktStatus ) );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t queryNetworkStatus( CellularContext_t * pContext,
|
|
const char * pCommand,
|
|
const char * pPrefix,
|
|
CellularNetworkRegType_t regType )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularNetworkRegType_t recvRegType = regType;
|
|
CellularAtReq_t atReqGetResult = { 0 };
|
|
|
|
configASSERT( pContext != NULL );
|
|
atReqGetResult.pAtCmd = pCommand;
|
|
atReqGetResult.atCmdType = CELLULAR_AT_MULTI_WITH_PREFIX;
|
|
atReqGetResult.pAtRspPrefix = pPrefix;
|
|
atReqGetResult.respCallback = _Cellular_RecvFuncGetNetworkReg;
|
|
atReqGetResult.pData = &recvRegType;
|
|
atReqGetResult.dataLen = ( uint16_t ) sizeof( CellularNetworkRegType_t );
|
|
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetResult );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseCopsRegModeToken( char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
bool parseStatus = true;
|
|
int32_t var = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "_parseCopsRegMode: Input Parameter NULL" ) );
|
|
parseStatus = false;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &var );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( var >= 0 ) && ( var < ( int32_t ) REGISTRATION_MODE_MAX ) )
|
|
{
|
|
/* Variable "var" is ensured that it is valid and within
|
|
* a valid range. Hence, assigning the value of the variable to
|
|
* networkRegMode with a enum cast. */
|
|
/* coverity[misra_c_2012_rule_10_5_violation] */
|
|
pOperatorInfo->networkRegMode = ( CellularNetworkRegistrationMode_t ) var;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseCopsRegMode: Error in processing Network Registration mode. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseCopsNetworkNameFormatToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
bool parseStatus = true;
|
|
int32_t var = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "_parseCopsNetworkNameFormat: Input Parameter NULL" ) );
|
|
parseStatus = false;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &var );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( var >= 0 ) &&
|
|
( var < ( int32_t ) OPERATOR_NAME_FORMAT_MAX ) )
|
|
{
|
|
/* Variable "var" is ensured that it is valid and within
|
|
* a valid range. Hence, assigning the value of the variable to
|
|
* operatorNameFormat with a enum cast. */
|
|
/* coverity[misra_c_2012_rule_10_5_violation] */
|
|
pOperatorInfo->operatorNameFormat = ( CellularOperatorNameFormat_t ) var;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseCopsNetworkNameFormat: Error in processing Network Registration mode. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseCopsNetworkNameToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
bool parseStatus = true;
|
|
uint32_t mccMncLen = 0U;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "_parseCopsNetworkName: Input Parameter NULL" ) );
|
|
parseStatus = false;
|
|
}
|
|
else
|
|
{
|
|
if( ( pOperatorInfo->operatorNameFormat == OPERATOR_NAME_FORMAT_LONG ) ||
|
|
( pOperatorInfo->operatorNameFormat == OPERATOR_NAME_FORMAT_SHORT ) )
|
|
{
|
|
( void ) strncpy( pOperatorInfo->operatorName, pToken, CELLULAR_NETWORK_NAME_MAX_SIZE );
|
|
}
|
|
else if( pOperatorInfo->operatorNameFormat == OPERATOR_NAME_FORMAT_NUMERIC )
|
|
{
|
|
mccMncLen = ( uint32_t ) strlen( pToken );
|
|
|
|
if( ( mccMncLen == ( CELLULAR_MCC_MAX_SIZE + CELLULAR_MNC_MAX_SIZE ) ) ||
|
|
( mccMncLen == ( CELLULAR_MCC_MAX_SIZE + CELLULAR_MNC_MAX_SIZE - 1U ) ) )
|
|
{
|
|
( void ) strncpy( pOperatorInfo->plmnInfo.mcc, pToken, CELLULAR_MCC_MAX_SIZE );
|
|
pOperatorInfo->plmnInfo.mcc[ CELLULAR_MCC_MAX_SIZE ] = '\0';
|
|
( void ) strncpy( pOperatorInfo->plmnInfo.mnc, &pToken[ CELLULAR_MCC_MAX_SIZE ],
|
|
( uint32_t ) ( mccMncLen - CELLULAR_MCC_MAX_SIZE + 1u ) );
|
|
pOperatorInfo->plmnInfo.mnc[ CELLULAR_MNC_MAX_SIZE ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseCopsNetworkName: Error in processing Network MCC MNC: Length not Valid" ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in processing Operator Name: Format Unknown" ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseCopsRatToken( const char * pToken,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
bool parseStatus = true;
|
|
int32_t var = 0;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "_parseCopsNetworkName: Input Parameter NULL" ) );
|
|
parseStatus = false;
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 10, &var );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( var < ( int32_t ) CELLULAR_RAT_MAX ) && ( var >= 0 ) )
|
|
{
|
|
/* Variable "var" is ensured that it is valid and within
|
|
* a valid range. Hence, assigning the value of the variable to
|
|
* rat with a enum cast. */
|
|
/* coverity[misra_c_2012_rule_10_5_violation] */
|
|
pOperatorInfo->rat = ( CellularRat_t ) var;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "_parseCopsNetworkName: Error in processing RAT. Token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t _parseCops( char * pCopsResponse,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
char * pToken = NULL;
|
|
char * pTempCopsResponse = pCopsResponse;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
bool parseStatus = false;
|
|
|
|
/* Getting next token from COPS response. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTempCopsResponse, &pToken );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _parseCopsRegModeToken( pToken, pOperatorInfo );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTempCopsResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _parseCopsNetworkNameFormatToken( pToken, pOperatorInfo );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTempCopsResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _parseCopsNetworkNameToken( pToken, pOperatorInfo );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pTempCopsResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _parseCopsRatToken( pToken, pOperatorInfo );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncUpdateMccMnc( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pCopsResponse = NULL;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
cellularOperatorInfo_t * pOperatorInfo = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "UpdateMccMnc: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( cellularOperatorInfo_t ) ) )
|
|
{
|
|
LogError( ( "UpdateMccMnc: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else
|
|
{
|
|
pCopsResponse = pAtResp->pItm->pLine;
|
|
pOperatorInfo = ( cellularOperatorInfo_t * ) pData;
|
|
|
|
/* Remove COPS Prefix. */
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pCopsResponse );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Removing all the Quotes from the COPS response. */
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pCopsResponse );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Removing all Space from the COPS response. */
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pCopsResponse );
|
|
}
|
|
|
|
/* parse all the data from cops. */
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = _parseCops( pCopsResponse, pOperatorInfo );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_ERROR )
|
|
{
|
|
LogError( ( "ERROR: COPS %s", pCopsResponse ) );
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncIpAddress( 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;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "Recv IP address: Invalid context" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "Recv IP address: response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen == 0U ) )
|
|
{
|
|
LogError( ( "Recv IP address: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
LogDebug( ( "Recv IP address: Context id: %s", pToken ) );
|
|
|
|
if( pInputLine[ 0 ] != '\0' )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
}
|
|
else
|
|
{
|
|
/* This is the case "+CGPADDR: 1". Return "0.0.0.0" in this case.*/
|
|
( void ) strncpy( pData, "0,0,0,0", dataLen );
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
LogDebug( ( "Recv IP address: Ip Addr: %s", pToken ) );
|
|
( void ) strncpy( pData, pToken, dataLen );
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
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 ].rat = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in processing RAT value. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
break;
|
|
|
|
case CELLULAR_CEDRXS_POS_VALUE:
|
|
atCoreStatus = Cellular_ATStrtoi( pToken, 2, &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;
|
|
|
|
default:
|
|
LogError( ( "Unknown Parameter Position in AT+CEDRXS Response" ) );
|
|
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;
|
|
}
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
LogDebug( ( "GetEidrx setting[%d]: RAT: %d, Value: 0x%x",
|
|
count, pEidrxSettingsList->eidrxList[ count ].rat,
|
|
pEidrxSettingsList->eidrxList[ count ].requestedEdrxVaue ) );
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "GetEidrx: Parsing Error encountered, atCoreStatus: %d", atCoreStatus ) );
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
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 ) )
|
|
{
|
|
LogError( ( "GetEidrxSettings: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != CELLULAR_EDRX_LIST_MAX_SIZE ) )
|
|
{
|
|
LogError( ( "GetEidrxSettings: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pEidrxSettingsList = ( CellularEidrxSettingsList_t * ) pData;
|
|
pCommnadItem = pAtResp->pItm;
|
|
|
|
while( ( pCommnadItem != NULL ) && ( pktStatus == CELLULAR_PKT_STATUS_OK ) )
|
|
{
|
|
pInputLine = pCommnadItem->pLine;
|
|
|
|
if( ( strcmp( "+CEDRXS: 0", pInputLine ) == 0 ) ||
|
|
( strcmp( "+CEDRXS:", pInputLine ) == 0 ) )
|
|
{
|
|
LogDebug( ( "GetEidrx: empty EDRXS setting %s", pInputLine ) );
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = parseEidrxLine( pInputLine, count, pEidrxSettingsList );
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
count++;
|
|
}
|
|
}
|
|
|
|
pCommnadItem = pCommnadItem->pNext;
|
|
pEidrxSettingsList->count = count;
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t atcmdUpdateMccMnc( CellularContext_t * pContext,
|
|
cellularOperatorInfo_t * pOperatorInfo )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus;
|
|
CellularAtReq_t atReqGetMccMnc = { 0 };
|
|
|
|
atReqGetMccMnc.pAtCmd = "AT+COPS?";
|
|
atReqGetMccMnc.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetMccMnc.pAtRspPrefix = "+COPS";
|
|
atReqGetMccMnc.respCallback = _Cellular_RecvFuncUpdateMccMnc;
|
|
atReqGetMccMnc.pData = pOperatorInfo;
|
|
atReqGetMccMnc.dataLen = ( uint16_t ) sizeof( cellularOperatorInfo_t );
|
|
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetMccMnc );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularError_t atcmdQueryRegStatus( CellularContext_t * pContext,
|
|
CellularServiceStatus_t * pServiceStatus )
|
|
{
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
const cellularAtData_t * pLibAtData = NULL;
|
|
CellularNetworkRegistrationStatus_t psRegStatus = REGISTRATION_STATUS_UNKNOWN;
|
|
|
|
configASSERT( pContext != NULL );
|
|
|
|
cellularStatus = queryNetworkStatus( pContext, "AT+CREG?", "+CREG", CELLULAR_REG_TYPE_CREG );
|
|
|
|
#ifndef CELLULAR_MODEM_NO_GSM_NETWORK
|
|
/* Added below +CGREG support as some modems also support GSM/EDGE network. */
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
/* Ignore the network status query return value with CGREG. Some modem
|
|
* may not support EDGE or GSM. In this case, psRegStatus is not stored
|
|
* in libAtData. CEREG will be used to query the ps network status. */
|
|
( void ) queryNetworkStatus( pContext, "AT+CGREG?", "+CGREG", CELLULAR_REG_TYPE_CGREG );
|
|
}
|
|
|
|
/* Check if modem acquired GPRS Registration. */
|
|
/* Query CEREG only if the modem did not already acquire PS registration. */
|
|
_Cellular_LockAtDataMutex( pContext );
|
|
psRegStatus = pContext->libAtData.psRegStatus;
|
|
_Cellular_UnlockAtDataMutex( pContext );
|
|
#endif /* ifndef CELLULAR_MODEM_NO_GSM_NETWORK */
|
|
|
|
if( ( cellularStatus == CELLULAR_SUCCESS ) &&
|
|
( psRegStatus != REGISTRATION_STATUS_REGISTERED_HOME ) &&
|
|
( psRegStatus != REGISTRATION_STATUS_ROAMING_REGISTERED ) )
|
|
{
|
|
cellularStatus = queryNetworkStatus( pContext, "AT+CEREG?", "+CEREG", CELLULAR_REG_TYPE_CEREG );
|
|
}
|
|
|
|
/* Get the service status from lib AT data. */
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
pLibAtData = &pContext->libAtData;
|
|
_Cellular_LockAtDataMutex( pContext );
|
|
pServiceStatus->rat = pLibAtData->rat;
|
|
pServiceStatus->csRegistrationStatus = pLibAtData->csRegStatus;
|
|
pServiceStatus->psRegistrationStatus = pLibAtData->psRegStatus;
|
|
pServiceStatus->csRejectionCause = pLibAtData->csRejCause;
|
|
pServiceStatus->csRejectionType = pLibAtData->csRejectType;
|
|
pServiceStatus->psRejectionCause = pLibAtData->psRejCause;
|
|
pServiceStatus->psRejectionType = pLibAtData->psRejectType;
|
|
_Cellular_UnlockAtDataMutex( pContext );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t parseT3412TimerValue( char * pToken,
|
|
uint32_t * pTimerValueSeconds )
|
|
{
|
|
int32_t tempValue = 0;
|
|
uint32_t tokenValue = 0;
|
|
uint32_t timerUnitIndex = 0;
|
|
uint32_t timerValue = 0;
|
|
CellularATError_t atCoreStatus = Cellular_ATStrtoi( pToken, 2, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( tempValue < 0 )
|
|
{
|
|
LogError( ( "Error in processing Periodic Processing Active time value. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
else
|
|
{
|
|
tokenValue = ( uint32_t ) tempValue;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
timerUnitIndex = T3412_TIMER_UNIT( tokenValue );
|
|
timerValue = T3412_TIMER_VALUE( tokenValue );
|
|
|
|
/* Parse the time unit. */
|
|
switch( timerUnitIndex )
|
|
{
|
|
case T3412_TIMER_UNIT_10MINUTES:
|
|
*pTimerValueSeconds = timerValue * ( 10U * 60U );
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_1HOURS:
|
|
*pTimerValueSeconds = timerValue * ( 1U * 60U * 60U );
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_10HOURS:
|
|
*pTimerValueSeconds = timerValue * ( 10U * 60U * 60U );
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_2SECONDS:
|
|
*pTimerValueSeconds = timerValue * 2U;
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_30SECONDS:
|
|
*pTimerValueSeconds = timerValue * 30U;
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_1MINUTES:
|
|
*pTimerValueSeconds = timerValue * 60U;
|
|
break;
|
|
|
|
case T3412_TIMER_UNIT_DEACTIVATED:
|
|
*pTimerValueSeconds = T3412_TIMER_DEACTIVATED;
|
|
break;
|
|
|
|
default:
|
|
LogError( ( "Invalid T3412 timer unit index" ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t parseT3324TimerValue( char * pToken,
|
|
uint32_t * pTimerValueSeconds )
|
|
{
|
|
int32_t tempValue = 0;
|
|
uint32_t tokenValue = 0;
|
|
uint32_t timerUnitIndex = 0;
|
|
uint32_t timerValue = 0;
|
|
CellularATError_t atCoreStatus = Cellular_ATStrtoi( pToken, 2, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( tempValue < 0 )
|
|
{
|
|
LogError( ( "Error in processing Periodic Processing Active time value. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
else
|
|
{
|
|
tokenValue = ( uint32_t ) tempValue;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
timerUnitIndex = T3324_TIMER_UNIT( tokenValue );
|
|
timerValue = T3324_TIMER_VALUE( tokenValue );
|
|
|
|
/* Parse the time unit. */
|
|
switch( timerUnitIndex )
|
|
{
|
|
case T3324_TIMER_UNIT_2SECONDS:
|
|
*pTimerValueSeconds = timerValue * 2u;
|
|
break;
|
|
|
|
case T3324_TIMER_UNIT_1MINUTE:
|
|
*pTimerValueSeconds = timerValue * 60U;
|
|
break;
|
|
|
|
case T3324_TIMER_UNIT_DECIHOURS:
|
|
*pTimerValueSeconds = timerValue * ( 15U * 60U );
|
|
break;
|
|
|
|
case T3324_TIMER_UNIT_DEACTIVATED:
|
|
*pTimerValueSeconds = T3324_TIMER_DEACTIVATED;
|
|
break;
|
|
|
|
default:
|
|
LogError( ( "Invalid T3324 timer unit index" ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
break;
|
|
}
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetEidrxSettings( 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 = { 0 };
|
|
|
|
atReqGetEidrx.pAtCmd = "AT+CEDRXS?";
|
|
atReqGetEidrx.atCmdType = CELLULAR_AT_MULTI_WITH_PREFIX;
|
|
atReqGetEidrx.pAtRspPrefix = "+CEDRXS";
|
|
atReqGetEidrx.respCallback = _Cellular_RecvFuncGetEidrxSettings;
|
|
atReqGetEidrx.pData = pEidrxSettingsList;
|
|
atReqGetEidrx.dataLen = CELLULAR_EDRX_LIST_MAX_SIZE;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pEidrxSettingsList == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetEidrxSettings : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
( void ) memset( pEidrxSettingsList, 0, sizeof( CellularEidrxSettingsList_t ) );
|
|
/* Query the pEidrxSettings from the network. */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetEidrx );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_GetEidrxSettings: couldn't retrieve Eidrx settings" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonSetEidrxSettings( 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 = { 0 };
|
|
|
|
atReqSetEidrx.pAtCmd = cmdBuf;
|
|
atReqSetEidrx.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReqSetEidrx.pAtRspPrefix = NULL;
|
|
atReqSetEidrx.respCallback = NULL;
|
|
atReqSetEidrx.pData = NULL;
|
|
atReqSetEidrx.dataLen = 0;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pEidrxSettings == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonSetEidrxSettings : 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%d,%d,\"" PRINTF_BINARY_PATTERN_INT4 "\"",
|
|
"AT+CEDRXS=",
|
|
pEidrxSettings->mode,
|
|
pEidrxSettings->rat,
|
|
PRINTF_BYTE_TO_BINARY_INT4( pEidrxSettings->requestedEdrxVaue ) );
|
|
LogDebug( ( "Eidrx setting: %s ", cmdBuf ) );
|
|
/* Query the PSMsettings from the network. */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetEidrx );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_SetEidrxSettings: couldn't set Eidrx settings" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonRfOn( CellularHandle_t cellularHandle )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus;
|
|
CellularPktStatus_t pktStatus;
|
|
CellularAtReq_t atReq = { 0 };
|
|
|
|
atReq.pAtCmd = "AT+CFUN=1";
|
|
atReq.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReq.pAtRspPrefix = NULL;
|
|
atReq.respCallback = NULL;
|
|
atReq.pData = NULL;
|
|
atReq.dataLen = 0;
|
|
|
|
/* Make sure library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReq );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonRfOff( CellularHandle_t cellularHandle )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus;
|
|
CellularPktStatus_t pktStatus;
|
|
CellularAtReq_t atReq = { 0 };
|
|
|
|
atReq.pAtCmd = "AT+CFUN=4";
|
|
atReq.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReq.pAtRspPrefix = NULL;
|
|
atReq.respCallback = NULL;
|
|
atReq.pData = NULL;
|
|
atReq.dataLen = 0;
|
|
|
|
/* Make sure library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReq );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetRegisteredNetwork( CellularHandle_t cellularHandle,
|
|
CellularPlmnInfo_t * pNetworkInfo )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
cellularOperatorInfo_t * pOperatorInfo = ( cellularOperatorInfo_t * ) Platform_Malloc( sizeof( cellularOperatorInfo_t ) );
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pNetworkInfo == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetRegisteredNetwork : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else if( pOperatorInfo == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetRegisteredNetwork : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_NO_MEMORY;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = atcmdUpdateMccMnc( pContext, pOperatorInfo );
|
|
}
|
|
|
|
if( cellularStatus == CELLULAR_SUCCESS )
|
|
{
|
|
if( pOperatorInfo->rat != CELLULAR_RAT_INVALID )
|
|
{
|
|
( void ) memcpy( pNetworkInfo->mcc, pOperatorInfo->plmnInfo.mcc, CELLULAR_MCC_MAX_SIZE );
|
|
pNetworkInfo->mcc[ CELLULAR_MCC_MAX_SIZE ] = '\0';
|
|
( void ) memcpy( pNetworkInfo->mnc, pOperatorInfo->plmnInfo.mnc, CELLULAR_MNC_MAX_SIZE );
|
|
pNetworkInfo->mnc[ CELLULAR_MNC_MAX_SIZE ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = CELLULAR_UNKNOWN;
|
|
}
|
|
}
|
|
|
|
Platform_Free( pOperatorInfo );
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetServiceStatus( CellularHandle_t cellularHandle,
|
|
CellularServiceStatus_t * pServiceStatus )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
cellularOperatorInfo_t operatorInfo;
|
|
|
|
( void ) memset( &operatorInfo, 0, sizeof( cellularOperatorInfo_t ) );
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pServiceStatus == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetServiceStatus : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* Always query and update the cellular Lib AT data. */
|
|
( void ) atcmdQueryRegStatus( pContext, pServiceStatus );
|
|
( void ) atcmdUpdateMccMnc( pContext, &operatorInfo );
|
|
|
|
/* Service status data from operator info. */
|
|
pServiceStatus->networkRegistrationMode = operatorInfo.networkRegMode;
|
|
pServiceStatus->plmnInfo = operatorInfo.plmnInfo;
|
|
( void ) strncpy( pServiceStatus->operatorName, operatorInfo.operatorName, CELLULAR_NETWORK_NAME_MAX_SIZE );
|
|
pServiceStatus->operatorNameFormat = operatorInfo.operatorNameFormat;
|
|
|
|
LogDebug( ( "SrvStatus: rat %d cs %d, ps %d, mode %d, csRejType %d, csRej %d, psRejType %d, psRej %d, plmn %s%s",
|
|
pServiceStatus->rat,
|
|
pServiceStatus->csRegistrationStatus, pServiceStatus->psRegistrationStatus,
|
|
pServiceStatus->networkRegistrationMode,
|
|
pServiceStatus->csRejectionType, pServiceStatus->csRejectionCause,
|
|
pServiceStatus->psRejectionType, pServiceStatus->psRejectionCause,
|
|
pServiceStatus->plmnInfo.mcc, pServiceStatus->plmnInfo.mnc ) );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetNetworkTime( CellularHandle_t cellularHandle,
|
|
CellularTime_t * pNetworkTime )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqGetNetworkTime = { 0 };
|
|
|
|
atReqGetNetworkTime.pAtCmd = "AT+CCLK?";
|
|
atReqGetNetworkTime.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetNetworkTime.pAtRspPrefix = "+CCLK";
|
|
atReqGetNetworkTime.respCallback = _Cellular_RecvFuncGetNetworkTime;
|
|
atReqGetNetworkTime.pData = pNetworkTime;
|
|
atReqGetNetworkTime.dataLen = ( uint16_t ) sizeof( CellularTime_t );
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pNetworkTime == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetNetworkTime : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetNetworkTime );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_GetNetworkTime: couldn't retrieve Network Time" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetModemInfo( CellularHandle_t cellularHandle,
|
|
CellularModemInfo_t * pModemInfo )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqGetFirmwareVersion = { 0 };
|
|
CellularAtReq_t atReqGetImei = { 0 };
|
|
CellularAtReq_t atReqGetModelId = { 0 };
|
|
CellularAtReq_t atReqGetManufactureId = { 0 };
|
|
|
|
atReqGetFirmwareVersion.pAtCmd = "AT+CGMR";
|
|
atReqGetFirmwareVersion.atCmdType = CELLULAR_AT_WO_PREFIX;
|
|
atReqGetFirmwareVersion.pAtRspPrefix = NULL;
|
|
atReqGetFirmwareVersion.respCallback = _Cellular_RecvFuncGetFirmwareVersion;
|
|
atReqGetFirmwareVersion.pData = pModemInfo->firmwareVersion;
|
|
atReqGetFirmwareVersion.dataLen = CELLULAR_FW_VERSION_MAX_SIZE + 1U;
|
|
|
|
atReqGetImei.pAtCmd = "AT+CGSN";
|
|
atReqGetImei.atCmdType = CELLULAR_AT_WO_PREFIX;
|
|
atReqGetImei.pAtRspPrefix = NULL;
|
|
atReqGetImei.respCallback = _Cellular_RecvFuncGetImei;
|
|
atReqGetImei.pData = pModemInfo->imei;
|
|
atReqGetImei.dataLen = CELLULAR_IMEI_MAX_SIZE + 1U;
|
|
|
|
atReqGetModelId.pAtCmd = "AT+CGMM";
|
|
atReqGetModelId.atCmdType = CELLULAR_AT_WO_PREFIX;
|
|
atReqGetModelId.pAtRspPrefix = NULL;
|
|
atReqGetModelId.respCallback = _Cellular_RecvFuncGetModelId;
|
|
atReqGetModelId.pData = pModemInfo->modelId;
|
|
atReqGetModelId.dataLen = CELLULAR_MODEL_ID_MAX_SIZE + 1U;
|
|
|
|
atReqGetManufactureId.pAtCmd = "AT+CGMI";
|
|
atReqGetManufactureId.atCmdType = CELLULAR_AT_WO_PREFIX;
|
|
atReqGetManufactureId.pAtRspPrefix = NULL;
|
|
atReqGetManufactureId.respCallback = _Cellular_RecvFuncGetManufactureId;
|
|
atReqGetManufactureId.pData = pModemInfo->manufactureId;
|
|
atReqGetManufactureId.dataLen = CELLULAR_MANUFACTURE_ID_MAX_SIZE + 1U;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pModemInfo == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetModemInfo : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
( void ) memset( pModemInfo, 0, sizeof( CellularModemInfo_t ) );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetFirmwareVersion );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetImei );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetModelId );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetManufactureId );
|
|
}
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "ModemInfo: hwVer:%s, fwVer:%s, serialNum:%s, IMEI:%s, manufactureId:%s, modelId:%s ",
|
|
pModemInfo->hardwareVersion, pModemInfo->firmwareVersion, pModemInfo->serialNumber, pModemInfo->imei,
|
|
pModemInfo->manufactureId, pModemInfo->modelId ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetIPAddress( CellularHandle_t cellularHandle,
|
|
uint8_t contextId,
|
|
char * pBuffer,
|
|
uint32_t bufferLength )
|
|
{
|
|
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 atReqGetIp = { 0 };
|
|
|
|
atReqGetIp.pAtCmd = cmdBuf;
|
|
atReqGetIp.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetIp.pAtRspPrefix = "+CGPADDR";
|
|
atReqGetIp.respCallback = _Cellular_RecvFuncIpAddress;
|
|
atReqGetIp.pData = pBuffer;
|
|
atReqGetIp.dataLen = ( uint16_t ) bufferLength;
|
|
|
|
/* Make sure the library is open. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( ( pBuffer == NULL ) || ( bufferLength == 0U ) )
|
|
{
|
|
LogError( ( "_Cellular_GetIPAddress: pBuffer is invalid or bufferLength is wrong" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
cellularStatus = _Cellular_IsValidPdn( contextId );
|
|
}
|
|
|
|
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]. */
|
|
( void ) snprintf( cmdBuf, CELLULAR_AT_CMD_TYPICAL_MAX_SIZE, "%s%d", "AT+CGPADDR=", contextId );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetIp );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "_Cellular_GetIPAddress: couldn't retrieve the IP, cmdBuf:%s, pktStatus: %d", cmdBuf, pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void _Cellular_DestroyAtDataMutex( CellularContext_t * pContext )
|
|
{
|
|
configASSERT( pContext != NULL );
|
|
|
|
PlatformMutex_Destroy( &pContext->libAtDataMutex );
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
bool _Cellular_CreateAtDataMutex( CellularContext_t * pContext )
|
|
{
|
|
bool status = false;
|
|
|
|
configASSERT( pContext != NULL );
|
|
|
|
status = PlatformMutex_Create( &pContext->libAtDataMutex, false );
|
|
|
|
return status;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void _Cellular_LockAtDataMutex( CellularContext_t * pContext )
|
|
{
|
|
configASSERT( pContext != NULL );
|
|
|
|
PlatformMutex_Lock( &pContext->libAtDataMutex );
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void _Cellular_UnlockAtDataMutex( CellularContext_t * pContext )
|
|
{
|
|
configASSERT( pContext != NULL );
|
|
|
|
PlatformMutex_Unlock( &pContext->libAtDataMutex );
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* mode 0: Clean everything.
|
|
* mode 1: Only clean the fields for creg/cgreg=0 URC. */
|
|
void _Cellular_InitAtData( CellularContext_t * pContext,
|
|
uint32_t mode )
|
|
{
|
|
cellularAtData_t * pLibAtData = NULL;
|
|
|
|
configASSERT( pContext != NULL );
|
|
|
|
pLibAtData = &pContext->libAtData;
|
|
|
|
if( mode == 0u )
|
|
{
|
|
( void ) memset( pLibAtData, 0, sizeof( cellularAtData_t ) );
|
|
pLibAtData->csRegStatus = REGISTRATION_STATUS_NOT_REGISTERED_SEARCHING;
|
|
pLibAtData->psRegStatus = REGISTRATION_STATUS_NOT_REGISTERED_SEARCHING;
|
|
}
|
|
|
|
pLibAtData->lac = 0xFFFFU;
|
|
pLibAtData->cellId = 0xFFFFFFFFU;
|
|
pLibAtData->rat = CELLULAR_RAT_INVALID;
|
|
pLibAtData->rac = 0xFF;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonSetPdnConfig( 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' };
|
|
CellularAtReq_t atReqSetPdn = { 0 };
|
|
|
|
atReqSetPdn.pAtCmd = cmdBuf;
|
|
atReqSetPdn.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReqSetPdn.pAtRspPrefix = NULL;
|
|
atReqSetPdn.respCallback = NULL;
|
|
atReqSetPdn.pData = NULL;
|
|
atReqSetPdn.dataLen = 0;
|
|
|
|
if( pPdnConfig == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonSetPdnConfig: 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:
|
|
LogError( ( "Cellular_CommonSetPdnConfig: 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 )
|
|
{
|
|
/* 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%d,\"%s\",\"%s\"",
|
|
"AT+CGDCONT=",
|
|
contextId,
|
|
pPdpTypeStr,
|
|
pPdnConfig->apnName );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetPdn );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_CommonSetPdnConfig: can't set PDN, cmdBuf:%s, PktRet: %d", cmdBuf, pktStatus ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularSimCardLockState_t _getSimLockState( char * pToken )
|
|
{
|
|
CellularSimCardLockState_t tempState = CELLULAR_SIM_CARD_LOCK_UNKNOWN;
|
|
|
|
if( pToken != NULL )
|
|
{
|
|
if( strcmp( pToken, "READY" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_READY;
|
|
}
|
|
else if( strcmp( pToken, "SIM PIN" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PIN;
|
|
}
|
|
else if( strcmp( pToken, "SIM PUK" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PUK;
|
|
}
|
|
else if( strcmp( pToken, "SIM PIN2" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PIN2;
|
|
}
|
|
else if( strcmp( pToken, "SIM PUK2" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PUK2;
|
|
}
|
|
else if( strcmp( pToken, "PH-NET PIN" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PH_NET_PIN;
|
|
}
|
|
else if( strcmp( pToken, "PH-NET PUK" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PH_NET_PUK;
|
|
}
|
|
else if( strcmp( pToken, "PH-NETSUB PIN" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PH_NETSUB_PIN;
|
|
}
|
|
else if( strcmp( pToken, "PH-NETSUB PUK" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_PH_NETSUB_PUK;
|
|
}
|
|
else if( strcmp( pToken, "PH-SP PIN" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_SP_PIN;
|
|
}
|
|
else if( strcmp( pToken, "PH-SP PUK" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_SP_PUK;
|
|
}
|
|
else if( strcmp( pToken, "PH-CORP PIN" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_CORP_PIN;
|
|
}
|
|
else if( strcmp( pToken, "PH-CORP PUK" ) == 0 )
|
|
{
|
|
tempState = CELLULAR_SIM_CARD_CORP_PUK;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Unknown SIM Lock State %s", pToken ) );
|
|
}
|
|
}
|
|
|
|
return tempState;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetSimLockStatus( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pToken = NULL, * pInputStr = NULL;
|
|
CellularSimCardLockState_t * pSimLockState = NULL;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetSimLockStatus: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetSimLockStatus: Response pData is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( CellularSimCardLockState_t ) ) )
|
|
{
|
|
LogError( ( "_Cellular_RecvFuncGetSimLockStatus: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pInputStr = pAtResp->pItm->pLine;
|
|
pSimLockState = ( CellularSimCardLockState_t * ) pData;
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pInputStr );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputStr );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputStr, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
LogDebug( ( "SIM Lock State: %s", pToken ) );
|
|
*pSimLockState = _getSimLockState( pToken );
|
|
}
|
|
|
|
if( atCoreStatus != CELLULAR_AT_SUCCESS )
|
|
{
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _checkCrsmMemoryStatus( const char * pToken )
|
|
{
|
|
bool memoryStatus = true;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "Input Parameter NULL" ) );
|
|
memoryStatus = false;
|
|
}
|
|
|
|
if( memoryStatus == true )
|
|
{
|
|
/* Checking the value sw2 in AT command response for memory problem during CRSM read.
|
|
* Refer 3GPP Spec TS 51.011 Section 9.4. */
|
|
if( strcmp( pToken, "64" ) == 0 ) /* '40' memory problem. */
|
|
{
|
|
LogError( ( "_checkCrsmMemoryStatus: Error in Processing HPLMN: CRSM Memory Error" ) );
|
|
memoryStatus = false;
|
|
}
|
|
}
|
|
|
|
return memoryStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _checkCrsmReadStatus( const char * pToken )
|
|
{
|
|
bool readStatus = true;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "Input Parameter NULL" ) );
|
|
readStatus = false;
|
|
}
|
|
|
|
if( readStatus == true )
|
|
{
|
|
/* Checking the parameter sw1 in AT command response for successful CRSM read.
|
|
* Refer 3GPP Spec TS 51.011 Section 9.4. */
|
|
if( ( strcmp( pToken, "144" ) != 0 ) && /* '90' normal ending of the command. */
|
|
( strcmp( pToken, "145" ) != 0 ) && /* '91' normal ending of the command, with extra information. */
|
|
( strcmp( pToken, "146" ) != 0 ) ) /* '92' command successful but after using an internal update retry routine 'X' times. */
|
|
{
|
|
LogError( ( "_checkCrsmReadStatus: Error in Processing HPLMN: CRSM Read Error" ) );
|
|
readStatus = false;
|
|
}
|
|
}
|
|
|
|
return readStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static bool _parseHplmn( char * pToken,
|
|
void * pData )
|
|
{
|
|
bool parseStatus = true;
|
|
CellularPlmnInfo_t * plmn = ( CellularPlmnInfo_t * ) pData;
|
|
|
|
if( pToken == NULL )
|
|
{
|
|
LogError( ( "_parseHplmn: pToken is NULL or pData is NULL" ) );
|
|
parseStatus = false;
|
|
}
|
|
else if( ( strlen( pToken ) < ( CRSM_HPLMN_RAT_LENGTH ) ) || ( strncmp( pToken, "FFFFFF", 6 ) == 0 ) )
|
|
{
|
|
LogError( ( "_parseHplmn: Error in processing HPLMN invalid token %s", pToken ) );
|
|
parseStatus = false;
|
|
}
|
|
else
|
|
{
|
|
/* Returning only the very first HPLMN present in EFHPLMNwACT in SIM.
|
|
* EF-HPLMNwACT can contain a maximum of 10 HPLMN entries in decreasing order of priority.
|
|
* In this implementation, returning the very first HPLMN is the PLMN priority list. */
|
|
/* Refer TS 51.011 Section 10.3.37 for encoding. */
|
|
plmn->mcc[ 0 ] = pToken[ 1 ];
|
|
plmn->mcc[ 1 ] = pToken[ 0 ];
|
|
plmn->mcc[ 2 ] = pToken[ 3 ];
|
|
plmn->mnc[ 0 ] = pToken[ 5 ];
|
|
plmn->mnc[ 1 ] = pToken[ 4 ];
|
|
|
|
if( pToken[ 2 ] != 'F' )
|
|
{
|
|
plmn->mnc[ 2 ] = pToken[ 2 ];
|
|
plmn->mnc[ 3 ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
plmn->mnc[ 2 ] = '\0';
|
|
}
|
|
}
|
|
|
|
return parseStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetHplmn( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
bool parseStatus = true;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pCrsmResponse = NULL, * pToken = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetHplmn: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetHplmn: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( CellularPlmnInfo_t ) ) )
|
|
{
|
|
LogError( ( "GetHplmn: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pCrsmResponse = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pCrsmResponse );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Removing the CRSM prefix in AT Response. */
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pCrsmResponse );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Removing All quotes in the AT Response. */
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pCrsmResponse );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Getting the next token separated by comma in At Response. */
|
|
atCoreStatus = Cellular_ATGetNextTok( &pCrsmResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _checkCrsmReadStatus( pToken );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pCrsmResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _checkCrsmMemoryStatus( pToken );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pCrsmResponse, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
parseStatus = _parseHplmn( pToken, pData );
|
|
|
|
if( parseStatus == false )
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetIccid( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "getIccid: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) ||
|
|
( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "getIccid: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_ICCID_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "getIccid: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Removing QCCID Prefix in AT Response. */
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pRespLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
/* Storing the ICCID value in the AT Response. */
|
|
if( strlen( pRespLine ) < ( ( size_t ) CELLULAR_ICCID_MAX_SIZE + 1U ) )
|
|
{
|
|
( void ) strncpy( pData, pRespLine, dataLen );
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = CELLULAR_AT_BAD_PARAMETER;
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetImsi( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
char * pRespLine = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "getImsi: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_INVALID_HANDLE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "getImsi: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != ( CELLULAR_IMSI_MAX_SIZE + 1U ) ) )
|
|
{
|
|
LogError( ( "getImsi: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pRespLine = pAtResp->pItm->pLine;
|
|
|
|
/* Removing all the Spaces in the AT Response. */
|
|
atCoreStatus = Cellular_ATRemoveAllWhiteSpaces( pRespLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( strlen( pRespLine ) < ( CELLULAR_IMSI_MAX_SIZE + 1U ) )
|
|
{
|
|
( void ) strncpy( ( char * ) pData, pRespLine, dataLen );
|
|
}
|
|
else
|
|
{
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetSimCardLockStatus( CellularHandle_t cellularHandle,
|
|
CellularSimCardStatus_t * pSimCardStatus )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqGetSimLockStatus = { 0 };
|
|
|
|
atReqGetSimLockStatus.pAtCmd = "AT+CPIN?";
|
|
atReqGetSimLockStatus.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetSimLockStatus.pAtRspPrefix = "+CPIN";
|
|
atReqGetSimLockStatus.respCallback = _Cellular_RecvFuncGetSimLockStatus;
|
|
atReqGetSimLockStatus.pData = NULL;
|
|
atReqGetSimLockStatus.dataLen = 0;
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pSimCardStatus == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetSimCardLockStatus : Bad paremeter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* Initialize the sim state and the sim lock state. */
|
|
pSimCardStatus->simCardLockState = CELLULAR_SIM_CARD_LOCK_UNKNOWN;
|
|
|
|
atReqGetSimLockStatus.pData = &pSimCardStatus->simCardLockState;
|
|
atReqGetSimLockStatus.dataLen = ( uint16_t ) sizeof( CellularSimCardLockState_t );
|
|
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetSimLockStatus );
|
|
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
LogDebug( ( "_Cellular_GetSimStatus, Sim Insert State[%d], Lock State[%d]",
|
|
pSimCardStatus->simCardState, pSimCardStatus->simCardLockState ) );
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetSimCardInfo( CellularHandle_t cellularHandle,
|
|
CellularSimCardInfo_t * pSimCardInfo )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqGetIccid = { 0 };
|
|
CellularAtReq_t atReqGetImsi = { 0 };
|
|
CellularAtReq_t atReqGetHplmn = { 0 };
|
|
|
|
atReqGetIccid.pAtCmd = "AT+CCID";
|
|
atReqGetIccid.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetIccid.pAtRspPrefix = "+CCID";
|
|
atReqGetIccid.respCallback = _Cellular_RecvFuncGetIccid;
|
|
atReqGetIccid.pData = pSimCardInfo->iccid;
|
|
atReqGetIccid.dataLen = CELLULAR_ICCID_MAX_SIZE + 1U;
|
|
|
|
atReqGetImsi.pAtCmd = "AT+CIMI";
|
|
atReqGetImsi.atCmdType = CELLULAR_AT_WO_PREFIX;
|
|
atReqGetImsi.pAtRspPrefix = NULL;
|
|
atReqGetImsi.respCallback = _Cellular_RecvFuncGetImsi;
|
|
atReqGetImsi.pData = pSimCardInfo->imsi;
|
|
atReqGetImsi.dataLen = CELLULAR_IMSI_MAX_SIZE + 1U;
|
|
|
|
atReqGetHplmn.pAtCmd = "AT+CRSM=176,28514,0,0,0"; /* READ BINARY commmand. HPLMN Selector with Access Technology( 6F62 ). */
|
|
atReqGetHplmn.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetHplmn.pAtRspPrefix = "+CRSM";
|
|
atReqGetHplmn.respCallback = _Cellular_RecvFuncGetHplmn;
|
|
atReqGetHplmn.pData = &pSimCardInfo->plmn;
|
|
atReqGetHplmn.dataLen = ( uint16_t ) sizeof( CellularPlmnInfo_t );
|
|
|
|
/* pContext is checked in _Cellular_CheckLibraryStatus function. */
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pSimCardInfo == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetSimCardInfo : Bad paremeter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
( void ) memset( pSimCardInfo, 0, sizeof( CellularSimCardInfo_t ) );
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetImsi );
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetHplmn );
|
|
}
|
|
|
|
if( pktStatus == CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetIccid );
|
|
}
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
else
|
|
{
|
|
LogDebug( ( "SimInfo updated: IMSI:%s, Hplmn:%s%s, ICCID:%s",
|
|
pSimCardInfo->imsi, pSimCardInfo->plmn.mcc, pSimCardInfo->plmn.mnc,
|
|
pSimCardInfo->iccid ) );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static uint32_t appendBinaryPattern( char * cmdBuf,
|
|
uint32_t cmdLen,
|
|
uint32_t value,
|
|
bool endOfString )
|
|
{
|
|
uint32_t retLen = 0;
|
|
|
|
if( value != 0U )
|
|
{
|
|
/* 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, cmdLen, "\"" PRINTF_BINARY_PATTERN_INT8 "\"%c",
|
|
( uint32_t ) PRINTF_BYTE_TO_BINARY_INT8( value ), endOfString ? '\0' : ',' );
|
|
}
|
|
else
|
|
{
|
|
/* 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, cmdLen, "%c", endOfString ? '\0' : ',' );
|
|
}
|
|
|
|
retLen = ( uint32_t ) strlen( cmdBuf );
|
|
|
|
return retLen;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonSetPsmSettings( 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' };
|
|
uint32_t cmdBufLen = 0;
|
|
CellularAtReq_t atReqSetPsm = { 0 };
|
|
|
|
atReqSetPsm.pAtCmd = cmdBuf;
|
|
atReqSetPsm.atCmdType = CELLULAR_AT_NO_RESULT;
|
|
atReqSetPsm.pAtRspPrefix = NULL;
|
|
atReqSetPsm.respCallback = NULL;
|
|
atReqSetPsm.pData = NULL;
|
|
atReqSetPsm.dataLen = 0;
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pPsmSettings == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonSetPsmSettings : 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, "AT+CPSMS=%d,", pPsmSettings->mode );
|
|
cmdBufLen = ( uint32_t ) strlen( cmdBuf );
|
|
cmdBufLen = cmdBufLen + appendBinaryPattern( &cmdBuf[ cmdBufLen ], ( CELLULAR_AT_CMD_MAX_SIZE - cmdBufLen ),
|
|
pPsmSettings->periodicRauValue, false );
|
|
cmdBufLen = cmdBufLen + appendBinaryPattern( &cmdBuf[ cmdBufLen ], ( CELLULAR_AT_CMD_MAX_SIZE - cmdBufLen ),
|
|
pPsmSettings->gprsReadyTimer, false );
|
|
cmdBufLen = cmdBufLen + appendBinaryPattern( &cmdBuf[ cmdBufLen ], ( CELLULAR_AT_CMD_MAX_SIZE - cmdBufLen ),
|
|
pPsmSettings->periodicTauValue, false );
|
|
( void ) appendBinaryPattern( &cmdBuf[ cmdBufLen ], ( CELLULAR_AT_CMD_MAX_SIZE - cmdBufLen ),
|
|
pPsmSettings->activeTimeValue, true );
|
|
|
|
LogDebug( ( "PSM setting: %s ", cmdBuf ) );
|
|
|
|
/* Query the PSMsettings from the network. */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqSetPsm );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_SetPsmSettings: couldn't set PSM settings" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t parseCpsmsMode( char * pToken,
|
|
CellularPsmSettings_t * pPsmSettings )
|
|
{
|
|
int32_t tempValue = 0;
|
|
CellularATError_t atCoreStatus = Cellular_ATStrtoi( pToken, 2, &tempValue );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
if( ( tempValue >= 0 ) && ( tempValue <= ( int32_t ) UINT8_MAX ) )
|
|
{
|
|
pPsmSettings->mode = ( uint8_t ) tempValue;
|
|
}
|
|
else
|
|
{
|
|
LogError( ( "Error in processing mode. Token %s", pToken ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
}
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularATError_t parseGetPsmToken( char * pToken,
|
|
uint8_t tokenIndex,
|
|
CellularPsmSettings_t * pPsmSettings )
|
|
{
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
|
|
switch( tokenIndex )
|
|
{
|
|
case CPSMS_POS_MODE:
|
|
atCoreStatus = parseCpsmsMode( pToken, pPsmSettings );
|
|
break;
|
|
|
|
case CPSMS_POS_RAU:
|
|
atCoreStatus = parseT3412TimerValue( pToken, &pPsmSettings->periodicRauValue );
|
|
break;
|
|
|
|
case CPSMS_POS_RDY_TIMER:
|
|
atCoreStatus = parseT3324TimerValue( pToken, &pPsmSettings->gprsReadyTimer );
|
|
break;
|
|
|
|
case CPSMS_POS_TAU:
|
|
atCoreStatus = parseT3412TimerValue( pToken, &pPsmSettings->periodicTauValue );
|
|
break;
|
|
|
|
case CPSMS_POS_ACTIVE_TIME:
|
|
atCoreStatus = parseT3324TimerValue( pToken, &pPsmSettings->activeTimeValue );
|
|
break;
|
|
|
|
default:
|
|
LogError( ( "Unknown Parameter Position in AT+QPSMS Response" ) );
|
|
atCoreStatus = CELLULAR_AT_ERROR;
|
|
break;
|
|
}
|
|
|
|
return atCoreStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static CellularPktStatus_t _Cellular_RecvFuncGetPsmSettings( CellularContext_t * pContext,
|
|
const CellularATCommandResponse_t * pAtResp,
|
|
void * pData,
|
|
uint16_t dataLen )
|
|
{
|
|
char * pInputLine = NULL, * pToken = NULL;
|
|
uint8_t tokenIndex = 0;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularATError_t atCoreStatus = CELLULAR_AT_SUCCESS;
|
|
CellularPsmSettings_t * pPsmSettings = NULL;
|
|
|
|
if( pContext == NULL )
|
|
{
|
|
LogError( ( "GetPsmSettings: pContext is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_FAILURE;
|
|
}
|
|
else if( ( pAtResp == NULL ) || ( pAtResp->pItm == NULL ) || ( pAtResp->pItm->pLine == NULL ) )
|
|
{
|
|
LogError( ( "GetPsmSettings: Response is invalid" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else if( ( pData == NULL ) || ( dataLen != sizeof( CellularPsmSettings_t ) ) )
|
|
{
|
|
LogError( ( "GetPsmSettings: pData is invalid or dataLen is wrong" ) );
|
|
pktStatus = CELLULAR_PKT_STATUS_BAD_PARAM;
|
|
}
|
|
else
|
|
{
|
|
pInputLine = pAtResp->pItm->pLine;
|
|
pPsmSettings = ( CellularPsmSettings_t * ) pData;
|
|
atCoreStatus = Cellular_ATRemovePrefix( &pInputLine );
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATRemoveAllDoubleQuote( pInputLine );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
atCoreStatus = Cellular_ATGetNextTok( &pInputLine, &pToken );
|
|
}
|
|
|
|
if( atCoreStatus == CELLULAR_AT_SUCCESS )
|
|
{
|
|
tokenIndex = 0;
|
|
|
|
while( pToken != NULL )
|
|
{
|
|
atCoreStatus = parseGetPsmToken( pToken, tokenIndex, pPsmSettings );
|
|
|
|
if( atCoreStatus != CELLULAR_AT_SUCCESS )
|
|
{
|
|
LogInfo( ( "parseGetPsmToken %s index %d failed", pToken, tokenIndex ) );
|
|
}
|
|
|
|
tokenIndex++;
|
|
|
|
if( Cellular_ATGetNextTok( &pInputLine, &pToken ) != CELLULAR_AT_SUCCESS )
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
pktStatus = _Cellular_TranslateAtCoreStatus( atCoreStatus );
|
|
}
|
|
|
|
return pktStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
CellularError_t Cellular_CommonGetPsmSettings( CellularHandle_t cellularHandle,
|
|
CellularPsmSettings_t * pPsmSettings )
|
|
{
|
|
CellularContext_t * pContext = ( CellularContext_t * ) cellularHandle;
|
|
CellularError_t cellularStatus = CELLULAR_SUCCESS;
|
|
CellularPktStatus_t pktStatus = CELLULAR_PKT_STATUS_OK;
|
|
CellularAtReq_t atReqGetPsm = { 0 };
|
|
|
|
atReqGetPsm.pAtCmd = "AT+CPSMS?";
|
|
atReqGetPsm.atCmdType = CELLULAR_AT_WITH_PREFIX;
|
|
atReqGetPsm.pAtRspPrefix = "+CPSMS";
|
|
atReqGetPsm.respCallback = _Cellular_RecvFuncGetPsmSettings;
|
|
atReqGetPsm.pData = pPsmSettings;
|
|
atReqGetPsm.dataLen = ( uint16_t ) sizeof( CellularPsmSettings_t );
|
|
|
|
cellularStatus = _Cellular_CheckLibraryStatus( pContext );
|
|
|
|
if( cellularStatus != CELLULAR_SUCCESS )
|
|
{
|
|
LogError( ( "_Cellular_CheckLibraryStatus failed" ) );
|
|
}
|
|
else if( pPsmSettings == NULL )
|
|
{
|
|
LogError( ( "Cellular_CommonGetPsmSettings : Bad parameter" ) );
|
|
cellularStatus = CELLULAR_BAD_PARAMETER;
|
|
}
|
|
else
|
|
{
|
|
/* Initialize the data. */
|
|
( void ) memset( pPsmSettings, 0, sizeof( CellularPsmSettings_t ) );
|
|
pPsmSettings->mode = 0xFF;
|
|
|
|
/* Query the PSMsettings from the network. */
|
|
pktStatus = _Cellular_AtcmdRequestWithCallback( pContext, atReqGetPsm );
|
|
|
|
if( pktStatus != CELLULAR_PKT_STATUS_OK )
|
|
{
|
|
LogError( ( "Cellular_GetPsmSettings: couldn't retrieve PSM settings" ) );
|
|
cellularStatus = _Cellular_TranslatePktStatus( pktStatus );
|
|
}
|
|
}
|
|
|
|
return cellularStatus;
|
|
}
|
|
|
|
/*-----------------------------------------------------------*/
|