blob: 3273f3cb08a5e8c24723b339a688d37f41f2f1f6 [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2008 Marvell International Ltd.
* All Rights Reserved
******************************************************************************/
/*--------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------
*
* Filename: teldat.c
*
* Description: Telephony Implementation for AT Command for CI_SG_ID_DEV.
*
* History:
* Jan 17, 2008 - Creation of file
*
* Notes:
*
******************************************************************************/
/******************************************************************************
* Include files
******************************************************************************/
#include "ci_api.h"
#include "teldat.h"
#include "telps.h"
#include "teldev.h"
#include "utlMalloc.h"
#include "telconfig.h"
#include "telatparamdef.h"
#include "telatci.h"
#include "telutl.h"
#include "telcontroller.h"
#include "ci_dat.h"
#include <sys/ioctl.h>
#include <net/if.h>
#include <fcntl.h>
#include "common_datastub_macro.h"
#include <netinet/in.h>
#if defined (BIONIC)
#include <netutils/ifc.h>
#endif
#include <cutils/properties.h>
#include <inttypes.h> /* for PRIu64 */
#include <netinet/ip.h>
#define _GNU_SOURCE
#include <netinet/udp.h>
#include "set_mbms_cnf.h"
#include <inttypes.h> /* for PRIu64 */
#define PSDATASTUB_NAME "/dev/psdatastub"
#define PSDATASTUB_IOC_MAGIC 'P'
#define PSDATASTUB_GCFDATA _IOW(PSDATASTUB_IOC_MAGIC, 1, int)
#define PSDATASTUB_TOGGLE_DATA_ENABLE_DISABLE _IOW(PSDATASTUB_IOC_MAGIC, 2, int)
#define CI_DAT_MBMS_CMD_DEVICE_INFO (CI_DAT_MBMS_CMD_GET_CURRENT_SAIS+1)
/* Globals */
int g_CGSENDSwitch = 1;
int g_TGSINKSwitch = 1;
/* Local variabls */
static INT32 gSinkCid;
static INT32 gSinkPacketSize;
static INT16 gSinkPduSize;
static INT32 gSinkPort;
static CHAR gSinkAddress[ATCI_PS_ADDRESS_SIZE + ATCI_NULL_TERMINATOR_LENGTH];
static UINT8 gSinkIpDataBuf[ATCI_IP_MTU];
static INT32 sinkRemainingPacketSize = 0;
static INT32 gSinkIncludeHdr = FALSE;
INT32 gSinkCount = 0;
BOOL gNewSinkPacket = FALSE;
BOOL gFinishOnePacket = FALSE;
int gMbmsAreaCnt = 0;
int gMbmsAreaNum = 0;
INT32 gSinkRemaingHdr = 0;
#define TIOPPPON _IOW('T', 208, int)
#define TIOPPPOFF _IOW('T', 209, int)
#define TIOPPPONCSD _IOW('T', 211, int)
extern CiServiceHandle gAtciSvgHandle[CI_SG_NUMIDS + 1];
extern AtciCurrentPsCntxList gCIDList;
extern AtciCurrentCall gCurrCall[ NUM_OF_TEL_ATP ];
extern AtciCurrentCallsList gCurrentCallsList;
extern AtciCurrentCallsList gCurrentCallsList_1;
extern int libConvertHexToNum(char *inData, int inLen, char *outData);
int cidata_fd = 0;
static int atDonofState = TRUE;
int cctdatafd = 0;
BOOL giUseUlDlOpt = FALSE;
void createSinkIpFrame( UINT32 atHandle );
void sendSinkData( UINT32 atHandle, UINT8 connType );
void createUDPPacket( UINT8 * pDatabuf, UINT32 len );
#define MAX_RESPBUFFER_SIZE (2048 - 4)
typedef enum{
MBMS_ACTIVATE_NONE,
MBMS_ACTIVATE_ENABLE,
MBMS_ACTIVATE_DISABLE
}actMbmsStatus;
static int bActMbms = MBMS_ACTIVATE_NONE;
typedef struct mbmsReqType{
CiDatMbmsCmd nCmdType;
CHAR pInputName[30];
}mbmsReqType;
static mbmsReqType mbmsCmd_params[] =
{
{CI_DAT_MBMS_CMD_ACT, "ACTIVATE"},
{CI_DAT_MBMS_CMD_DEACT, "DEACTIVATE"},
{CI_DAT_MBMS_CMD_DEACT_ALL, "DEACTIVATE_ALL"},
{CI_DAT_MBMS_CMD_SET_PREFER, "MBMS_PREFERENCE"},
{CI_DAT_MBMS_CMD_GET_NW_TIME, "SIB16_GET_NETWORK_TIME"},
{CI_DAT_MBMS_CMD_GET_SIGNAL_LEVEL, "BSSI_SIGNAL_LEVEL"},
{CI_DAT_MBMS_CMD_GET_NW_INFO, "NETWORK INFORMATION"},
{CI_DAT_MBMS_CMD_GET_MODEM_STATUS, "MODEM_STATUS"},
{CI_DAT_MBMS_CMD_SET_HYSTERESIS, "HYSTERESIS"},
{CI_DAT_MBMS_CMD_SET_AVAILABILITY_INFO, "AVAILABILITY_INFO"},
{CI_DAT_MBMS_CMD_GET_CURRENT_SAIS, "GET_SAIS_LIST"},
{CI_DAT_MBMS_CMD_DEVICE_INFO, "DEVICE INFO"}
};
/************************************************************************************
* F@: ciCGSend - GLOBAL API for GCF AT+CGSEND -command
*
*/
RETURNCODE_T ciCGSend( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
CiReturnCode ret = CIRC_FAIL;
RETURNCODE_T rc = INITIAL_RETURN_CODE;
INT32 datalen = 0, cid;
static GCFDATA gcfdata;
/*
* Put parser index into the variable
*/
CiRequestHandle reqHandle;
TelAtParserID sAtpIndex = *(TelAtParserID *)arg_p;
AtciCurrentSetCntx *p_cInfo;
reqHandle = MAKE_AT_HANDLE( sAtpIndex );
*xid_p = reqHandle;
//DBGMSG(ciCGSend0, "[ciCGSend] Line(%d): reqHandle(%d),op(%d) \n", __LINE__, reqHandle, op);
F_ENTER(ciCGSend);
if (!GET_SIM1_FLAG(reqHandle)) {
p_cInfo = gCIDList.cInfo;
} else {
p_cInfo = gCIDList.cInfo_1;
}
/*
** Check the format of the request.
*/
switch (op)
{
case TEL_EXT_GET_CMD: /* AT+CGSEND? */
{
//coverity[string_null:SUPPRESS]
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, (char *)"+CGSEND: (0-20000)\r\n");
break;
}
case TEL_EXT_TEST_CMD: /* AT+CGSEND=? */
{
//coverity[string_null:SUPPRESS]
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, (char *)"+CGSEND: (0-20000)\r\n");
break;
}
case TEL_EXT_SET_CMD: /* AT+CGSEND= */
{
if ( getExtValue(parameter_values_p, 0, &datalen, 0, 20000, 0) == TRUE )
{
//DBGMSG(ciCGSend1, "[ciCGSend] Line(%d): datalen(%d) \n", __LINE__, datalen);
for(cid = 0; cid < CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM; cid++)
{
if((p_cInfo[cid].reqHandle != INVALID_REQ_HANDLE) && (GET_ATP_INDEX(p_cInfo[cid].reqHandle) == sAtpIndex))
break;
}
gcfdata.cid = cid;
if (gcfdata.cid >= CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM)
{
WARNMSG(ciCGSend2, "[ciCGSend]no appropriate active cid\n");
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
break;
}
int psdatastub = open(PSDATASTUB_NAME, O_RDWR);
if (psdatastub < 0) {
WARNMSG(ciCGSend3, "[ciCGSend]failed to open %s\n", PSDATASTUB_NAME);
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL );
break;
}
int ret_ioctl = 0;
while (datalen > 0 && ret_ioctl >= 0)
{
gcfdata.len = (datalen > ATCI_IP_MTU) ? ATCI_IP_MTU : datalen;
gcfdata.databuf = (UINT8 *)gSinkIpDataBuf;
ret_ioctl = ioctl(psdatastub, PSDATASTUB_GCFDATA, &gcfdata);
datalen = datalen - gcfdata.len;
}
if (ret_ioctl < 0 )
ret = ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
else
ret = ATRESP(reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
close(psdatastub);
}
else
{
WARNMSG(ciCGSend4, "[ciCGSend] Line(%d): error to get size of +CGSEND \n", __LINE__);
/* ** There was a problem extracting the functionality. */
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
}
break;
}
case TEL_EXT_ACTION_CMD: /* AT+CGSEND */
default:
{
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
}
/* handle the return value */
rc = HANDLE_RETURN_VALUE(ret);
F_LEAVE(ciCGSend5);
return(rc);
}
/* version 2: use IOCTL to cistub, instead of through CIREQUEST. */
/* NEW IMPLEMENTATION FOR AT*TGSINK */
/************************************************************************************
* F@: ciGpTGSINK - GLOBAL API for GCF AT*TGSINK -command
*
*/
RETURNCODE_T ciGpTGSINK( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
CiReturnCode ret = CIRC_FAIL;
RETURNCODE_T rc = INITIAL_RETURN_CODE;
INT32 cid;
INT32 packetSize;
INT32 pduCount;
char tgsinkBuf[200];
static GCFDATA gcfdata;
F_ENTER(ciGpTGSINK0);
/*
* Put parser index into the variable
*/
CiRequestHandle reqHandle;
TelAtParserID sAtpIndex = *(TelAtParserID *)arg_p;
AtciCurrentSetCntx *p_cInfo;
reqHandle = MAKE_AT_HANDLE( sAtpIndex );
*xid_p = reqHandle;
//DBGMSG(ciGpTGSINK, "ciGpTGSINK: reqHandle = %d.\n", reqHandle);
if (!GET_SIM1_FLAG(reqHandle)) {
p_cInfo = gCIDList.cInfo;
} else {
p_cInfo = gCIDList.cInfo_1;
}
switch (op)
{
case TEL_EXT_TEST_CMD: /* AT*TGSINK=? */
{
sprintf(tgsinkBuf, "*TGSINK: (1-8),(0-%d),(1-20)\r\n", ATCI_MAX_PACKET_SIZE);
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, tgsinkBuf);
break;
}
case TEL_EXT_SET_CMD: /* AT*TGSINK=XX,XX,XX */
{
BOOL cmdValid = FALSE;
/* ** Extract the arguments starting with the CID. */
if (getExtValue(parameter_values_p, 0, &cid, 1, TEL_AT_PS_CID_VAL_MAX, TEL_AT_PS_CID_VAL_DEFAULT))
{
//DBGMSG(ciGpTGSINK1, "[ciGpTGSINK] Line(%d): cid(%d) \n", __LINE__, cid);
if (( getExtValue(parameter_values_p, 1, &packetSize, ATCI_IP_LEN + ATCI_UDP_LEN, ATCI_MAX_PACKET_SIZE, ATCI_MAX_PDU_SIZE) == TRUE ) &&
( packetSize <= ATCI_MAX_PACKET_SIZE ) ) /* Check the PacketSize */
{
//DBGMSG(ciGpTGSINK2, "[ciGpTGSINK] Line(%d): packetSize(%d) \n", __LINE__, packetSize);
if (( getExtValue(parameter_values_p, 2, &pduCount, 1, ATCI_DEFAULT_PDU_COUNT, 1) == TRUE ) &&
( pduCount <= ATCI_DEFAULT_PDU_COUNT ) ) /* Check the PacketCount */
{
cmdValid = TRUE;
//DBGMSG(ciGpTGSINK3, "[ciGpTGSINK] Line(%d): pduCount(%d) \n", __LINE__, pduCount);
gSinkCid = cid - 1;
gSinkPacketSize = packetSize;
gSinkCount = pduCount;
gcfdata.cid = gSinkCid;
int psdatastub = open(PSDATASTUB_NAME, O_RDWR);
if (psdatastub >= 0) {
int ret_ioctl = 0;
gSinkIncludeHdr = TRUE;
while(gSinkCount){
gFinishOnePacket = FALSE;
gSinkPacketSize = packetSize;
while(!gFinishOnePacket){
createSinkIpFrame(reqHandle);
gcfdata.len = gSinkPduSize;
gcfdata.databuf = (UINT8 *)gSinkIpDataBuf;
//DBGMSG(ciGpTGSINK4, "[ciGpTGSINK] ioctl");
if ((ret_ioctl = ioctl(psdatastub, PSDATASTUB_GCFDATA, &gcfdata)) < 0)
break;
}
//DBGMSG(ciGpTGSINK5, "[ciGpTGSINK] gSinkCount:%d,ret_ioctl:%d", gSinkCount,ret_ioctl);
if (ret_ioctl < 0)
break;
}
gSinkIncludeHdr = FALSE;
//DBGMSG(ciGpTGSINK6, "[ciGpTGSINK] ret_ioctl:%d", ret_ioctl);
if (ret_ioctl < 0 )
ret = ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
else
ret = ATRESP(reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
close(psdatastub);
} else {
WARNMSG(ciGpTGSINK4, "[ciGpTGSINK]failed to open %s\n", PSDATASTUB_NAME);
ret = ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
}
}
}
}
if(!cmdValid)
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
break;
}
case TEL_EXT_GET_CMD: /* AT*TGSINK? */
case TEL_EXT_ACTION_CMD:
default:
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
/* handle the return value */
rc = HANDLE_RETURN_VALUE(ret);
F_LEAVE(ciGpTGSINK5);
return(rc);
}
/************************************************************************************
* F@: ciGpCGSink - GLOBAL API for GCF AT+CGSINK -command
*
*/
RETURNCODE_T ciGpCGSink( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
CiReturnCode ret = CIRC_FAIL;
RETURNCODE_T rc = INITIAL_RETURN_CODE;
BOOL cmdValid = FALSE;
INT32 cid;
INT32 packetSize;
INT32 pduCount;
INT16 addrStrLen;
char cgsinkBuf[200];
/*
* Put parser index into the variable
*/
CiRequestHandle reqHandle;
TelAtParserID sAtpIndex = *(TelAtParserID *)arg_p;
reqHandle = MAKE_AT_HANDLE( sAtpIndex );
*xid_p = reqHandle;
//DBGMSG(ciGpCGSink, "ciGpCGSink: reqHandle = %d.\n", reqHandle);
switch (op)
{
case TEL_EXT_TEST_CMD: /* AT+CGSINK=? */
{
sprintf(cgsinkBuf, "CGSINK = [CID 0-%d],[packetSize 0-%d],[PacketCount 1-20],[Address],[UDPPort]\r\n",
CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM, ATCI_MAX_PDU_SIZE);
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, cgsinkBuf);
break;
}
case TEL_EXT_SET_CMD: /* AT+CGSINK=XX,XX,XX */
{
/*
** Extract the arguments starting with the CID.
*/
if (( getExtValue(parameter_values_p, 0, &cid, 0, 255, ATCI_DEFAULT_CID) == TRUE ) &&
( cid > 0 ) && ( cid <= CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM ))
{
if (( getExtValue(parameter_values_p, 1, &packetSize, 0, 200, ATCI_DEFAULT_PDU_SIZE) == TRUE ) &&
( packetSize <= ATCI_MAX_PACKET_SIZE ) ) /* Check the PacketSize */
{
if (( getExtValue(parameter_values_p, 2, &pduCount, 1, 200, ATCI_DEFAULT_PDU_COUNT) == TRUE ) &&
( pduCount <= ATCI_DEFAULT_PDU_COUNT ) ) /* Check the PacketCount */
{
/* Pdp destination address ("255.255.255.255") */
if ( getExtString(parameter_values_p, 3, gSinkAddress, ATCI_PS_ADDRESS_SIZE, &addrStrLen, NULL) == TRUE )
{
/* UDP port */
if ( getExtValue(parameter_values_p, 4, &gSinkPort, 0, 255, ATCI_DEFAULT_UDP_PORT) == TRUE )
{
/*
** Set the connection information for CI.
*/
gSinkCid = cid - 1;
gSinkPacketSize = packetSize;
gSinkCount = pduCount;
gNewSinkPacket = TRUE;
/* check if ready for data transfer */
if ( gAtpCtrl[sAtpIndex].psCurrCid == gSinkCid )
{
/* start sending data */
sendSinkData(reqHandle, CI_DAT_CONNTYPE_PS);
cmdValid = TRUE;
}
} /* if ( getExtString ((CommandLine_t*)parameter_values_p, X, gSinkPort */
} /* if ( getExtString ((CommandLine_t*)parameter_values_p, X, (CHAR*)address */
} /* if (( getExtValue(parameter_values_p, X, &pduCount, */
} /* if (( getExtValue(parameter_values_p, X, &packetSize, */
} /* if (( getExtValue(parameter_values_p, X, &cid, */
if(!cmdValid)
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
break;
}
case TEL_EXT_GET_CMD: /* AT+CGSINK? */
case TEL_EXT_ACTION_CMD:
default:
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
/* handle the return value */
rc = HANDLE_RETURN_VALUE(ret);
return(rc);
}
/************************************************************************************
* F@: sendSinkData
*
*/
void sendSinkData( UINT32 atHandle, UINT8 connType )
{
CiReturnCode ret = CIRC_FAIL;
static CiDatPrimSendDataOptReq sinkDataSendReq;
//static CiDatPdu sinkSendPdu;
static UINT16 sinkSeqNo = 0;
static UINT16 sinkCurrentBufPosition = 0;
char sendDataBuf[500];
/* create the IP packet if new packet to send (i.e. not new packet segment) */
if ( gNewSinkPacket == TRUE )
{
createSinkIpFrame(atHandle);
gNewSinkPacket = FALSE;
}
/*
** Set the PDU information for the CI.
*/
if (connType == CI_DAT_CONNTYPE_PS)
{
sinkDataSendReq.connInfo.id = gSinkCid;
sinkDataSendReq.connInfo.type = CI_DAT_CONNTYPE_PS;
}
else
{
sinkDataSendReq.connInfo.id = gCurrCall[GET_ATP_INDEX(atHandle)].currCallId;
sinkDataSendReq.connInfo.type = CI_DAT_CONNTYPE_CS;
}
#if 0
sinkDataSendReq.sendPdu = &sinkSendPdu;
sinkSendPdu.seqNo = sinkSeqNo;
sinkSendPdu.type = CI_DAT_TYPE_IP;
sinkSendPdu.data = &gSinkIpDataBuf[sinkCurrentBufPosition];
#endif
sinkDataSendReq.sendPdu.seqNo = sinkSeqNo;
sinkDataSendReq.sendPdu.type = CI_DAT_TYPE_IP;
sinkDataSendReq.sendPdu.data = (UINT8 *)&gSinkIpDataBuf[sinkCurrentBufPosition];
/* check size of data to send */
if ( gSinkPduSize <= CI_MAX_CI_DATA_PDU_SIZE )
{
sprintf(sendDataBuf, "Send IP Data: packet #%d, segment size=%d\r\n", gSinkCount + 1, gSinkPduSize );
/* set size of data to be sent in this request */
//sinkSendPdu.len = gSinkPduSize;
sinkDataSendReq.sendPdu.len = gSinkPduSize;
/* all can be sent in one request */
gSinkPduSize = 0;
/* update position for data to be sent next time */
sinkCurrentBufPosition = 0;
/* this is last segment of the IP packet */
//sinkSendPdu.isLast = TRUE;
sinkDataSendReq.sendPdu.isLast = TRUE;
/* reset the segment number in the IP data */
sinkSeqNo = 0;
/* if more packets to send, new IP packet will be created for next CI request */
gNewSinkPacket = TRUE;
}
else
{
sprintf(sendDataBuf, "Send IP Data: packet #%d, segment size=%d\r\n", gSinkCount, CI_MAX_CI_DATA_PDU_SIZE );
/* set size of data to be sent in this request */
//sinkSendPdu.len = CI_MAX_CI_DATA_PDU_SIZE;
sinkDataSendReq.sendPdu.len = CI_MAX_CI_DATA_PDU_SIZE;
/* more to be sent next time */
gSinkPduSize = gSinkPduSize - CI_MAX_CI_DATA_PDU_SIZE;
/* update position for data to be sent next time */
sinkCurrentBufPosition = sinkCurrentBufPosition + CI_MAX_CI_DATA_PDU_SIZE;
/* update the segment number in the IP data */
sinkSeqNo++;
/* this is not the last segment of the IP packet */
//sinkSendPdu.isLast = FALSE;
sinkDataSendReq.sendPdu.isLast = FALSE;
}
/*
** Send the CI request.
*/
ret = ciRequest( gAtciSvgHandle[CI_SG_ID_DAT], CI_PS_PRIM_SEND_DATA_REQ,
MAKE_CI_REQ_HANDLE(atHandle, CI_PS_PRIM_SEND_DATA_REQ), (void *)&sinkDataSendReq );
}
/****************************************************************
* F@: processSetFuncConf - Process CI cnf msg of AT%MBMS?
*/
static void processGetMBMSConf(UINT32 reqHandle, const void *paras)
{
CiDatPrimGetMbmsCmdCnf* pCiDatPrimGetMbmsCnf = (CiDatPrimGetMbmsCmdCnf *)paras;
if (pCiDatPrimGetMbmsCnf->rc != CIRC_DAT_SUCCESS) {
//DBGMSG(processGetMBMSConf, "processGetMBMSConf: CiDatPrimGetMbmsCmdCnf->rc=%d\n", pCiDatPrimGetMbmsCnf->rc);
ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, CME_UNKNOWN, NULL);
return;
}
gMbmsAreaNum = pCiDatPrimGetMbmsCnf->numOfArea;
//DBGMSG(processGetMBMSConf1, "processGetMBMSConf: CiDatPrimGetMbmsCmdCnf->numOfArea=%d\n", gMbmsAreaNum);
if (gMbmsAreaNum == 0) {
ATRESP(reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
return;
}
UINT8 i;
for (i = 0; i < pCiDatPrimGetMbmsCnf->numOfArea; i++) {
//DBGMSG(processGetMBMSConf2, "processGetMBMSConf: CiDatPrimGetMbmsCmdCnf->areaId[%u]=%d\n", i, pCiDatPrimGetMbmsCnf->areaId[i] );
CiDatPrimGetMbmsCmdAreaInfoReq *pGetMbmsAreaReq = utlCalloc(1, sizeof(CiDatPrimGetMbmsCmdAreaInfoReq));
if (pGetMbmsAreaReq == NULL) {
ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, CME_MEMORY_FAILURE, NULL);
break;
}
pGetMbmsAreaReq->areaId = pCiDatPrimGetMbmsCnf->areaId[i];
CiReturnCode ret = ciRequest(gAtciSvgHandle[CI_SG_ID_DAT],
CI_DAT_PRIM_GET_MBMS_CMD_AREA_INFO_REQ,
MAKE_CI_REQ_HANDLE(reqHandle, CI_DAT_PRIM_GET_MBMS_CMD_AREA_INFO_REQ),
(void *)pGetMbmsAreaReq );
if (ret != CIRC_SUCCESS) {
ATRESP(reqHandle, ATCI_RESULT_CODE_ERROR, CME_UNKNOWN, NULL);
break;
}
}
}
/****************************************************************
* F@: processSetFuncConf - Process CI cnf msg of AT%MBMSEV?
*/
static void processSetMBMSEnvConf(UINT32 reqHandle, const void *paras)
{
CiDatPrimSetMbmsEvCnf* pCiDatPrimSetMbmsEvCnf = (CiDatPrimSetMbmsEvCnf *)paras;
INT8 i;
if (CIRC_DAT_SUCCESS == pCiDatPrimSetMbmsEvCnf->rc)
{
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
}
else if(CIRC_DAT_FAILURE == pCiDatPrimSetMbmsEvCnf->rc)
{
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, CME_UNKNOWN, NULL);
}
else
{
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, CMS_UNKNOWN_ERROR, NULL);
}
return;
}
/*0 - service change event
1 - No service(No LTE coverage)
2 - Only unicast service available
3 - LTE unicast and eMBMS service available
4 - 99 REserved*/
static void processMbmsEnvInd(CiIndicationHandle indHandle, const void *pParam)
{
char respBuffer[50];
CiDatPrimMbmsEvInd* pCiDatMbmsEnvInd = (CiDatPrimMbmsEvInd *)pParam;
/*0:service change, 1: no service, 2:only unicast, 3: both available*/
snprintf(respBuffer, utlNumberOf(respBuffer), "%%MBMSEV: %d\r\n" , pCiDatMbmsEnvInd->ev);
if (!GET_SIM1_FLAG(indHandle)) {
ATRESP(IND_REQ_HANDLE, 0, 0, respBuffer);
}else {
ATRESP(IND_REQ_HANDLE_1, 0, 0, respBuffer);
}
return;
}
/*eMBMS add end*/
static unsigned short ipHeaderChecksum(unsigned char *ipHeader, unsigned int size)
{
if (size & 1)
return 0;
unsigned int i;
unsigned int cksum = 0;
for (i = 0; i < size; i += 2) {
cksum += (ipHeader[i] << 8) | ipHeader[i + 1];
}
while (cksum > 0xFFFF) {
cksum = (cksum & 0xFFFF) + (cksum >> 16);
}
return ~cksum;
}
/************************************************************************************
* F@: createSinkIPMtu
*
* insert the IP header
*/
void createSinkIpFrame( UINT32 atHandle )
{
INT32 sinkPacketNum = 0;
static unsigned short sinkPacketId = 0;
INT32 sinkHeaderSize = ATCI_IP_LEN;
/* fill the data buffer with NULL value */
memset( gSinkIpDataBuf, 0x00, ATCI_IP_MTU );
struct iphdr *iph = (struct iphdr*)gSinkIpDataBuf;
unsigned int udp_datagram_len = ATCI_UDP_LEN + gSinkPacketSize;
unsigned int offset = 0;
/* first segment of the IP packet */
if ( sinkRemainingPacketSize == 0 )
{
if ( gSinkIncludeHdr == TRUE )
{
/* get the number of expected packets */
sinkPacketNum = (gSinkPacketSize / ATCI_IP_MTU) + ((gSinkPacketSize % ATCI_IP_MTU == 0) ? 0 : 1);
gSinkRemaingHdr = sinkPacketNum * ATCI_IP_LEN + ATCI_UDP_LEN;
gSinkPacketSize -= gSinkRemaingHdr;
}
/* init size left to be transmited from the IP packet */
sinkRemainingPacketSize = gSinkPacketSize;
/* new IP , new ID */
sinkPacketId++;
/* header contains UDP info */
sinkHeaderSize += ATCI_UDP_LEN;
/* fill in UDP header*/
struct udphdr *udph = (struct udphdr*)(iph + 1);
udph->dest = htons(gSinkPort);
udph->len = htons(udp_datagram_len);
} else {
offset = udp_datagram_len - sinkRemainingPacketSize;
}
/* decrease total headers size*/
gSinkRemaingHdr -= sinkHeaderSize;
/* get size of current IP packet, relative to the size to be still transmitted
* and maximum transmit unit size */
if ( sinkRemainingPacketSize <= (ATCI_IP_MTU - sinkHeaderSize) )
{
/* if we planned to send another packet, dont finish yet*/
if ( gSinkIncludeHdr && gSinkRemaingHdr != 0 )
{
gSinkPduSize = sinkRemainingPacketSize + sinkHeaderSize;
sinkRemainingPacketSize = gSinkRemaingHdr - ATCI_IP_LEN;
}
else
{
gSinkPduSize = sinkRemainingPacketSize + sinkHeaderSize;
/* a whole packet has been transmitted */
sinkRemainingPacketSize = 0;
/* update number of packets still to be sent */
gFinishOnePacket = TRUE;
gSinkCount--;
}
}
else
{
gSinkPduSize = ATCI_IP_MTU;
sinkRemainingPacketSize = sinkRemainingPacketSize - (ATCI_IP_MTU - sinkHeaderSize);
}
iph->version = 4; /* IP + Version=4 */
iph->ihl = 5;
iph->tot_len = htons(gSinkPduSize);
iph->id = htons(sinkPacketId);
iph->frag_off = htons(offset >> 3);
if (sinkRemainingPacketSize )
iph->frag_off |= htons(IP_MF);
iph->ttl = 15;
iph->protocol = IPPROTO_UDP;
/* Source address; ex: 018.052.086.120 | 12 34 56 78 */
if ( gAtpCtrl[GET_ATP_INDEX(atHandle)].psCurrCid == gSinkCid ) {
AtciCurrentSetCntx *p_cInfo;
if (!GET_SIM1_FLAG(atHandle)) {
p_cInfo = gCIDList.cInfo;
} else {
p_cInfo = gCIDList.cInfo_1;
}
char *pAddr = (char *)p_cInfo[gSinkCid].pdpAddress;
inet_pton(AF_INET, pAddr, &iph->saddr);
} else {
iph->saddr = 0xC0A80165; /* Source address: 192.168.1.101 */
}
/* Destination address */
if (strlen( (char *)gSinkAddress ) < strlen( "x.x.x.x" )) {
/* Destination = Source */
iph->daddr = iph->saddr;
} else {
/* Destination address: ex: 192.168.010.010 | C0 A8 0A 0A */
inet_pton(AF_INET, (char *)gSinkAddress, &iph->daddr);
}
iph->check = htons(ipHeaderChecksum(gSinkIpDataBuf, ATCI_IP_LEN));
}
/************************************************************************************
* F@: createUDPPacket
*
* Create one UDP packet.
*/
void createUDPPacket( UINT8 * pDatabuf, UINT32 len )
{
static unsigned short sinkPacketId = 0;
if (len >= ATCI_IP_MTU)
len = ATCI_IP_MTU;
/* fill the data buffer with NULL value */
memset( pDatabuf, 0x00, len);
struct iphdr *iph = (struct iphdr*)pDatabuf;
/* fill in UDP header */
struct udphdr *udph = (struct udphdr*)(iph + 1);
udph->len = htons(len - ATCI_IP_LEN);
/* fill in IP header */
iph->version = 4; /* IP + Version=4 */
iph->ihl = 5;
iph->tot_len = htons(len);
iph->id = htons(sinkPacketId++);
iph->ttl = 15;
iph->protocol = IPPROTO_UDP;
iph->saddr = 0xC0A80202; /* Source address: 192.168.2.2 */
iph->daddr = INADDR_BROADCAST; /* Destination address: 255.255.255.255 */
iph->check = htons(ipHeaderChecksum(pDatabuf, ATCI_IP_LEN));
}
/************************************************************************************
* F@: ciCsDataSink - GLOBAL API for GCF AT*ICSSINK -command
*
*/
RETURNCODE_T ciCsDataSink( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
/*
** Set the result code to INITIAL_RETURN_CODE. This allows
** the indications to display the correct return code after the
** AT Command is issued.
*/
CiReturnCode ret = CIRC_FAIL;
RETURNCODE_T rc = INITIAL_RETURN_CODE;
INT32 packetSize;
INT32 pduCount;
char csDataBuf[500];
static GCFDATA gcfdata;
/*
* Put parser index into the variable
*/
CiRequestHandle reqHandle;
TelAtParserID sAtpIndex = *(TelAtParserID *)arg_p;
reqHandle = MAKE_AT_HANDLE( sAtpIndex );
*xid_p = reqHandle;
//DBGMSG(ciCsDataSink, "ciCsDataSink: reqHandle = %d.\n", reqHandle);
switch (op)
{
case TEL_EXT_TEST_CMD: /* AT*ICSSINK=? */
{
sprintf(csDataBuf, "*ICSSINK: (0-%d),(1-20)\r\n", ATCI_MAX_PDU_SIZE);
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, csDataBuf);
break;
}
case TEL_EXT_SET_CMD: /* AT*ICSSINK=XX,XX */
{
BOOL cmdValid = FALSE;
if (bLocalTest == FALSE)
{
WARNMSG(ciCsDataSink1, "[ciCsDataSink] only supported in Test Mode!\n");
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_ALLOWED, NULL );
break;
}
if (( getExtValue(parameter_values_p, 0, &packetSize, 0, ATCI_DEFAULT_PDU_SIZE, ATCI_DEFAULT_PDU_SIZE) == TRUE ) &&
( packetSize <= ATCI_MAX_PDU_SIZE ) ) /* Check the PacketSize */
{
if (( getExtValue(parameter_values_p, 1, &pduCount, 1, ATCI_DEFAULT_PDU_COUNT, ATCI_DEFAULT_PDU_COUNT) == TRUE ) &&
( pduCount <= ATCI_DEFAULT_PDU_COUNT ) ) /* Check the PacketCount */
{
if (gCurrCall[sAtpIndex].currCallId != 0)
{
cmdValid = TRUE;
gcfdata.cid = gCurrCall[sAtpIndex].currCallId;
gcfdata.len = packetSize * pduCount;
gcfdata.databuf = (UINT8 *)utlMalloc(gcfdata.len + ATCI_IP_LEN + ATCI_UDP_LEN);
createUDPPacket( gcfdata.databuf, gcfdata.len );
int ret_ioctl;
int psdatastub = open(PSDATASTUB_NAME, O_RDWR);
if (psdatastub >= 0) {
ret_ioctl = ioctl(psdatastub, PSDATASTUB_GCFDATA, &gcfdata);
close(psdatastub);
} else {
WARNMSG(ciCsDataSink2, "[ciCsDataSink]failed to open %s\n", PSDATASTUB_NAME);
ret_ioctl = -1;
}
utlFree(gcfdata.databuf);
if (ret_ioctl < 0)
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
else
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
}
} /* if (( getExtValue(parameter_values_p, X, &pduCount, */
} /* if (( getExtValue(parameter_values_p, X, &packetSize, */
if(!cmdValid)
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
break;
}
default:
ret = ATRESP( reqHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
rc = HANDLE_RETURN_VALUE(ret);
return(rc);
}
/*******************************************************************
* FUNCTION: vPDUS
*
* DESCRIPTION: Get Max PDU Size
*
* PARAMETERS:
*
* RETURNS:
*
*******************************************************************/
utlReturnCode_T vPDUS( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(op)
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(parameter_values_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
RETURNCODE_T rc = INITIAL_RETURN_CODE;
CiReturnCode ret = CIRC_FAIL;
/*
* Put parser index into the variable
*/
UINT32 atHandle = MAKE_AT_HANDLE(*(TelAtParserID *)arg_p);
*xid_p = atHandle;
switch (op)
{
case TEL_EXT_SET_CMD: /* AT+VPDUS= */
{
int optimizedData;
if (( getExtValue(parameter_values_p, 0, &optimizedData, 0, 1, 0) == TRUE ))
{
CiDatPrimGetMaxPduSizeReq *getPduSizeReq = NULL;
getPduSizeReq = utlCalloc(1, sizeof(*getPduSizeReq));
if (getPduSizeReq == NULL)
break;
getPduSizeReq->optimizedData = (CiBoolean)optimizedData;
ret = ciRequest(gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_GET_MAX_PDU_SIZE_REQ, atHandle, (void *)getPduSizeReq);
}
else
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
break;
}
default:
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
}
rc = HANDLE_RETURN_VALUE(ret);
return(rc);
}
/*******************************************************************
* FUNCTION: atdb
*
* DESCRIPTION: Used to debug setting
*
* PARAMETERS:
*
* RETURNS:
*
*******************************************************************/
utlReturnCode_T atdb( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(op)
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
UNUSEDPARAM(xid_p)
TelAtParserID * sAtpIndex;
sAtpIndex = arg_p;
int fun = 1, value = 1;
if ( getExtValue(parameter_values_p, 0, &fun, TEL_AT_CFUN_0_FUN_VAL_MIN, TEL_AT_CFUN_0_FUN_VAL_MAX, TEL_AT_CFUN_0_FUN_VAL_DEFAULT) == TRUE )
{
if ( getExtValue(parameter_values_p, 0, &value, TEL_AT_CFUN_0_FUN_VAL_MIN, TEL_AT_CFUN_0_FUN_VAL_MAX, TEL_AT_CFUN_0_FUN_VAL_DEFAULT) == TRUE )
{
switch (fun)
{
case 1:
g_CGSENDSwitch = value;
break;
case 2:
g_TGSINKSwitch = value;
break;
default:
break;
}
}
}
return utlSUCCESS;
}
#ifdef OPERATOR_VERIZON
/************************************************************************************
* F@: ciVZWTESTAPP - GLOBAL API for GCF AT*VZWTESTAPP -command
*
*/
RETURNCODE_T ciVZWTESTAPP( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
RETURNCODE_T rc = INITIAL_RETURN_CODE;
CiReturnCode ret = CIRC_FAIL;
CHAR tmpStr[TEL_AT_VZWTESTAPP_APN_STR_MAX_LEN + 1] = "";
INT16 tmpStrLen = 0;
int state; // 0-application disconnected; 1-application idle; 2-application transmitting
int msPeriod; // period in milli-second
UINT32 atHandle = MAKE_AT_HANDLE( * (TelAtParserID *) arg_p );
*xid_p = atHandle;
//DBGMSG(ciVZWTESTAPP, "ciVZWTESTAPP: atHandle = %d.", atHandle);
switch (op)
{
case TEL_EXT_SET_CMD: /* AT*VZWTESTAPP=XX,XX,XX */
{
if ( getExtString(parameter_values_p, 0, tmpStr, TEL_AT_VZWTESTAPP_APN_STR_MAX_LEN, &tmpStrLen, TEL_AT_VZWTESTAPP_APN_STR_DEFAULT) == TRUE )
{
if ( getExtValue(parameter_values_p, 1, &state, TEL_AT_VZWTESTAPP_STATE_MIN, TEL_AT_VZWTESTAPP_STATE_MAX, TEL_AT_VZWTESTAPP_STATE_DEFAULT) == TRUE )
{
if ( getExtValue(parameter_values_p, 2, &msPeriod, TEL_AT_VZWTESTAPP_MSPERIOD_MIN, TEL_AT_VZWTESTAPP_MSPERIOD_MAX, TEL_AT_VZWTESTAPP_MSPERIOD_DEFAULT) == TRUE )
{
CiDatPrimTestAppReq *pReqParam;
pReqParam = (CiDatPrimTestAppReq *)utlCalloc(1,sizeof(CiDatPrimTestAppReq));
if(pReqParam==NULL)
{
ret = CIRC_FAIL;
break;
}
pReqParam->apn.len = tmpStrLen;
memcpy(pReqParam->apn.valStr, tmpStr, tmpStrLen);
pReqParam->state = state;
pReqParam->msPeriod = msPeriod;
ret = ciRequest(gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_TEST_APP_REQ,
MAKE_CI_REQ_HANDLE(atHandle,CI_DAT_PRIM_TEST_APP_REQ), (void *)pReqParam);
break;
}
else
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
}
else
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
}
else
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_INVALID_PARAM, NULL );
}
case TEL_EXT_TEST_CMD: /* AT*VZWTESTAPP=? */
case TEL_EXT_GET_CMD: /* AT*VZWTESTAPP? */
case TEL_EXT_ACTION_CMD: /* AT*VZWTESTAPP */
default:
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
rc = HANDLE_RETURN_VALUE(ret);
return(rc);
}
#endif
void initDataPPP()
{
char name[20];
WARNMSG(initDataPPP, "initDataPPP\n");
// cctdatadev0 is reserved for VT CSD; cctdatadev1 is for internal Data PPP
sprintf(name, "/dev/cctdatadev1");
if ((cctdatafd = open(name, O_RDWR)) == -1)
{
ERRMSG(initDataPPP1, "Error open name %s\n", name);
exit(-1);
}
}
static void initCSD(int cid)
{
int cctdatafd = -1;
WARNMSG(initCSD, "[initCSD]:Enable CSD data on cid %d\n", cid);
if ((cctdatafd = open("/dev/cctdatadev0", O_RDWR)) == -1)
{
ERRMSG(initCSD1, "Error open name %s, %s\n", "/dev/cctdatadev0", strerror(errno));
return;
}
ioctl(cctdatafd, TIOPPPON, cid);
close(cctdatafd);
return;
}
static void deinitCSD(int cid)
{
int cctdatafd = -1;
WARNMSG(deinitCSD, "[deinitCSD]:Disbale CSD data on cid:%d\n", cid);
if ((cctdatafd = open("/dev/cctdatadev0", O_RDWR)) == -1)
{
ERRMSG(deinitCSD1, "Error open name %s, %s\n", "/dev/cctdatadev0", strerror(errno));
return;
}
ioctl(cctdatafd, TIOPPPOFF, cid);
close(cctdatafd);
return;
}
/************************************************************************************
*
* DAT CI confirmations
*
*************************************************************************************/
void datCnf(CiSgOpaqueHandle opSgCnfHandle,
CiServiceGroupID svgId,
CiPrimitiveID primId,
CiRequestHandle reqHandle,
void* paras)
{
UNUSEDPARAM(opSgCnfHandle)
UNUSEDPARAM(svgId)
CiPsPrimSendDataCnf * pSendDataCnf;
CiDatPrimSetUlTpIndCnf *pSetU1TpIndCnf;
CiDatPrimGetMaxPduSizeCnf *pGetMaxPduSizeCnf;
CiDatPrimTestAppCnf *pTestAppCnf;
struct datahandle_obj dataHandle;
char tmpBuf[32];
UINT8 TimeInfoHigh;
UINT32 TimeInfoLow;
int ret;
F_ENTER(datCnf0);
/*
** Determine the primitive being confirmed.
*/
ERRMSG(datCnf, "datCnf: svgId: %d, primId: %d, reqHanlde: %d\n", svgId, primId, reqHandle);
switch (primId)
{
case CI_DAT_PRIM_SEND_CNF:
{
VDBGMSG(datCnf1, "datCnf: CI_DAT_PRIM_SEND_CNF is received!\n");
break;
}
case CI_DAT_PRIM_SEND_DATA_OPT_CNF:
{
VDBGMSG(datCnf2, "datCnf: CI_DAT_PRIM_SEND_DATA_OPT_CNF is received!\n");
break;
}
case CI_PS_PRIM_SEND_DATA_CNF:
//It seems that there is memory leak for CI_PS_PRIM_SEND_DATA_CNF
pSendDataCnf = (CiPsPrimSendDataCnf*)paras;
switch (pSendDataCnf->rc)
{
case CIRC_PS_SUCCESS:
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
break;
default:
WARNMSG(datCnf3, "[datCnf] Line(%d): pSendDataCnf->rc(%d) \n", __LINE__, pSendDataCnf->rc);
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
break;
}
break;
case CI_DAT_PRIM_SET_UL_TP_IND_CNF:
pSetU1TpIndCnf = (CiDatPrimSetUlTpIndCnf *)paras;
switch (pSetU1TpIndCnf->result)
{
case CIRC_PS_SUCCESS:
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
break;
default:
WARNMSG(datCnf4, "[datCnf] Line(%d): pSetU1TpIndCnf->rc(%d) \n", __LINE__, pSetU1TpIndCnf->result);
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
break;
}
break;
case CI_DAT_PRIM_GET_MAX_PDU_SIZE_CNF:
pGetMaxPduSizeCnf = (CiDatPrimGetMaxPduSizeCnf *)paras;
switch (pGetMaxPduSizeCnf->rc){
case CIRC_PS_SUCCESS:
memset(tmpBuf, 0x00, sizeof(tmpBuf));
snprintf(tmpBuf, sizeof(tmpBuf)-1, "+VPDUS: %d", pGetMaxPduSizeCnf->size);
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, tmpBuf);
break;
default:
WARNMSG(datCnf5, "[datCnf] Line(%d): pGetMaxPduSizeCnf->rc(%d) \n", __LINE__, pGetMaxPduSizeCnf->rc);
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
break;
}
break;
#ifdef OPERATOR_VERIZON
case CI_DAT_PRIM_TEST_APP_CNF:
pTestAppCnf = (CiDatPrimTestAppCnf *)paras;
switch (pTestAppCnf->rc)
{
case CIRC_DAT_SUCCESS:
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
break;
default:
WARNMSG(datCnf6, "[datCnf] Line(%d): pTestAppCnf->rc(%d) \n", __LINE__, pTestAppCnf->rc);
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
break;
}
break;
#endif
/*eMBMS function*/
case CI_DAT_PRIM_SET_MBMS_CMD_CNF:
processSetMbmsCmdCnf(reqHandle, paras);
break;
case CI_DAT_PRIM_GET_MBMS_CMD_CNF:
processGetMBMSConf(reqHandle, paras);
break;
case CI_DAT_PRIM_GET_MBMS_CMD_AREA_INFO_CNF:
{
CiDatPrimGetMbmsCmdAreaInfoCnf* pGetMbmsAreaCnf = (CiDatPrimGetMbmsCmdAreaInfoCnf *)paras;
INT8 j = 0;
char respBuffer[1024];
char mnc_str[5];
gMbmsAreaCnt++;
if (pGetMbmsAreaCnf->rc == CIRC_DAT_SUCCESS){
for (j = 0; j < pGetMbmsAreaCnf->numOfSession; j++){
memset(mnc_str, '\0', sizeof(mnc_str));
if (pGetMbmsAreaCnf->sessionInfo[j].tmgi.mncDigit == CIMM_NETOP_TWO_DIGIT_MNC)
sprintf(mnc_str,"%02x",pGetMbmsAreaCnf->sessionInfo[j].tmgi.mnc);
else if (pGetMbmsAreaCnf->sessionInfo[j].tmgi.mncDigit == CIMM_NETOP_THREE_DIGIT_MNC)
sprintf(mnc_str,"%03x",pGetMbmsAreaCnf->sessionInfo[j].tmgi.mnc);
//DBGMSG(datCnf7, "[datCnf] Line(%d):MBMSCMD:%d,\"0x%lx 0x%lx %s\"\n", __LINE__, pGetMbmsAreaCnf->areaId, pGetMbmsAreaCnf->sessionInfo[j].tmgi.serviceId, pGetMbmsAreaCnf->sessionInfo[j].tmgi.mcc, mnc_str);
sprintf(respBuffer, "%%MBMSCMD:\"%06x%03x%s\"", pGetMbmsAreaCnf->sessionInfo[j].tmgi.serviceId, pGetMbmsAreaCnf->sessionInfo[j].tmgi.mcc, mnc_str);
if (pGetMbmsAreaCnf->sessionInfo[j].sessionIdPresent)
sprintf(respBuffer, "%s,%d\n",respBuffer, pGetMbmsAreaCnf->sessionInfo[j].sessionId);
ATRESP( reqHandle, 0, 0, respBuffer);
}
if (gMbmsAreaCnt >= gMbmsAreaNum){
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
}
}
else
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, pGetMbmsAreaCnf->rc, NULL);
break;
}
case CI_DAT_PRIM_SET_MBMS_EV_CNF:
{
CiDatPrimSetMbmsEvCnf* pCiDatPrimSetMbmsEvCnf = (CiDatPrimSetMbmsEvCnf *)paras;
switch (pCiDatPrimSetMbmsEvCnf->rc)
{
case CIRC_DAT_SUCCESS:
ATRESP( reqHandle, ATCI_RESULT_CODE_OK, 0, NULL);
break;
default:
WARNMSG(datCnf8, "[datCnf] Line(%d): pCiDatPrimSetMbmsEvCnf->rc(%d) \n", __LINE__, pCiDatPrimSetMbmsEvCnf->rc);
ATRESP( reqHandle, ATCI_RESULT_CODE_ERROR, CME_UNKNOWN, NULL);
break;
}
break;
}
default:
break;
}
F_LEAVE(datCnf9);
return;
}
/************************************************************************************
*
* DAT CI notifications
*
*************************************************************************************/
void datInd(CiSgOpaqueHandle opSgIndHandle,
CiServiceGroupID svgId,
CiPrimitiveID primId,
CiIndicationHandle indHandle,
void* pParam)
{
UNUSEDPARAM(opSgIndHandle)
UNUSEDPARAM(svgId)
F_ENTER(datInd0);
struct datahandle_obj dataHandle;
UINT32 i, reqHandle = INVALID_REQ_HANDLE;
UINT32 atpIdx;
AtciCurrentSetCntx *p_cInfo;
CiDatPrimOkInd *datPrimOkInd;
AtciCurrentCallsList *pCurrentCallsList;
if (!GET_SIM1_FLAG(indHandle)) {
pCurrentCallsList = &gCurrentCallsList;
p_cInfo = gCIDList.cInfo;
} else {
pCurrentCallsList = &gCurrentCallsList_1;
p_cInfo = gCIDList.cInfo_1;
}
switch (primId)
{
case CI_DAT_PRIM_RECV_IND:
{
/* Now data info should not be received in user space */
VDBGMSG(datInd, "datInd: CI_DAT_PRIM_RECV_IND is received!\n");
break;
}
/*eMBMS function*///%MBMSSEV(unsolicited)
case CI_DAT_PRIM_MBMS_EV_IND:
{
processMbmsEnvInd(indHandle, pParam);
break;
}
/*eMBMS add end*/
case CI_DAT_PRIM_RECV_DATA_OPT_IND:
{
/* Now data info should not be received in user space */
VDBGMSG(datInd1, "datInd: CI_DAT_PRIM_RECV_DATA_OPT_IND is received!\n");
break;
}
case CI_DAT_PRIM_OK_IND:
{
datPrimOkInd = (CiDatPrimOkInd *)pParam;
dataHandle.m_connType = datPrimOkInd->connInfo.type;
dataHandle.m_maxPduSize = datPrimOkInd->maxPduSize;
dataHandle.m_cid = datPrimOkInd->connInfo.id;
dataHandle.m_datConnInfo.id = dataHandle.m_cid;
dataHandle.m_datConnInfo.type = dataHandle.m_connType;
dataHandle.chanState = DATA_CHAN_READY_STATE;
if (datPrimOkInd->connInfo.id >= CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM)
{
ERRMSG(datInd01, "datPrimOkInd->connInfo.id=%d is invalid", datPrimOkInd->connInfo.id);
break;
}
if (dataHandle.m_connType == CI_DAT_CONNTYPE_CS)
{
dataHandle.pdptype = CI_PS_PDP_TYPE_PPP;
dataHandle.connectionType = ATCI_LOCAL;
for (i = 0; i < pCurrentCallsList->NumCalls; i++)
{
if (dataHandle.m_cid == pCurrentCallsList->callInfo[i].CallId)
{
reqHandle = pCurrentCallsList->callInfo[i].reqHandle;
break;
}
}
}
else
{
reqHandle = p_cInfo[dataHandle.m_cid].reqHandle;
dataHandle.pdptype = p_cInfo[dataHandle.m_cid].pdpType;
}
atpIdx = GET_ATP_INDEX(reqHandle);
ioctl(cidata_fd, CCIDATASTUB_DATAHANDLE, &dataHandle);
if (giUseUlDlOpt)
{
CiDatPrimSetUlTpIndReq *setUlTpIndReq;
setUlTpIndReq = utlCalloc(1, sizeof(CiDatPrimSetUlTpIndReq));
if (setUlTpIndReq == NULL) {
ERRMSG(datInd2, "datInd: CI_DAT_PRIM_OK_IND handling failed in calloc!\n");
break;
}
//DBGMSG(datInd3, "datInd: *** sending TP request\r\n");
setUlTpIndReq->reportInterval = 75;
/*
** Send the CI request.
*/
ciRequest( gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_SET_UL_TP_IND_REQ,
MAKE_CI_REQ_HANDLE(reqHandle, CI_DAT_PRIM_SET_UL_TP_IND_REQ), (void *)setUlTpIndReq );
}
/* update the connection state */
switch ( dataHandle.m_connType )
{
case CI_DAT_CONNTYPE_CS:
{
initCSD(datPrimOkInd->connInfo.id);
ATRESP( reqHandle, ATCI_RESULT_CODE_SUPPRESS, 0, (char *)"CONNECT\r\n");
break;
}
case CI_DAT_CONNTYPE_PS:
{
ATRESP( reqHandle, ATCI_RESULT_CODE_SUPPRESS, 0, (char *)"CONNECT\r\n");
/* if PPP connection requested -> enable PPP frame transfer */
if ( (_CiPsPdpType)(dataHandle.pdptype) == CI_PS_PDP_TYPE_PPP )
{
if (bLocalTest)
{
initDataPPP();
ioctl(cctdatafd, TIOPPPON, datPrimOkInd->connInfo.id);
}
}
break;
}
default:
{
break;
}
}
break;
}
case CI_DAT_PRIM_NOK_IND:
{
/*vcy fix */
CiDatPrimNokInd *datPrimNOkInd = (CiDatPrimNokInd *)pParam;
switch ( datPrimNOkInd->connInfo.type )
{
case CI_DAT_CONNTYPE_CS:
{
for (i = 0; i < pCurrentCallsList->NumCalls; i++)
{
if (datPrimNOkInd->connInfo.id == pCurrentCallsList->callInfo[i].CallId)
{
reqHandle = pCurrentCallsList->callInfo[i].reqHandle;
break;
}
}
atpIdx = GET_ATP_INDEX(reqHandle);
usleep(200*1000);//maybe there is still CSD data after NOK, wait for 200 ms
/* update the connection state */
ioctl(cidata_fd, CCIDATASTUB_CS_CHNOK, datPrimNOkInd->connInfo.id);
if (!GET_SIM1_FLAG(indHandle)) {
ATRESP(IND_REQ_HANDLE, 0, 0, (char*)"NO CARRIER");
} else {
ATRESP(IND_REQ_HANDLE_1, 0, 0, (char*)"NO CARRIER");
}
deinitCSD(datPrimNOkInd->connInfo.id);
break;
}
case CI_DAT_CONNTYPE_PS:
{
//DBGMSG(datInd4, "I am NOK,datPrimNOkInd->connInfo.type:%d,connInfo.id:%d\n",datPrimNOkInd->connInfo.type, datPrimNOkInd->connInfo.id);
if (datPrimNOkInd->connInfo.id < CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM)
{
reqHandle = gCIDList.cInfo[datPrimNOkInd->connInfo.id].reqHandle;
if (bLocalTest)
{
if (cctdatafd > 0)
ioctl(cctdatafd, TIOPPPOFF, datPrimNOkInd->connInfo.id);
}
/* update the connection state */
if (p_cInfo[datPrimNOkInd->connInfo.id].pdpType == CI_PS_PDP_TYPE_PPP) //only PPP need wait
sleep(1);//Fix me: maybe there is still PPP data over Modem
/*Reset CID information */
if (datPrimNOkInd->connInfo.id < CI_PS_MAX_MO_AND_MT_PDP_CTX_NUM)
p_cInfo[datPrimNOkInd->connInfo.id].reqHandle = INVALID_REQ_HANDLE;
}
else
{
ERRMSG(datInd4, "I am NOK,datPrimNOkInd->connInfo.type:%d,connInfo.id:%d\n",datPrimNOkInd->connInfo.type, datPrimNOkInd->connInfo.id);
}
/* Delete PDP context */
//PS_DeleteGPRSContext(IND_REQ_HANDLE, datPrimNOkInd->connInfo.id);
if (!GET_SIM1_FLAG(indHandle)) {
ATRESP(IND_REQ_HANDLE, 0, 0, (char*)"NO CARRIER PS");
} else {
ATRESP(IND_REQ_HANDLE_1, 0, 0, (char*)"NO CARRIER PS");
}
#if 0 //vcy testing
/* Delete PDP context */
deletePdpCtxReq.cid = gCurrentPdpSetCtx.cid;
DBGMSG("%s: at line %d.\n", __FUNCTION__, __LINE__);
sleep( WAIT_TIME_BEFORE_PDP_CTX_DELETE );
ciRequest( gAtciSvgHandle[CI_SG_ID_PS], CI_PS_PRIM_DELETE_PDP_CTX_REQ,
gAtciSvgReqHandle[CI_SG_ID_PS]++, (void *)&deletePdpCtxReq );
// sleep( WAIT_TIME_BEFORE_PDP_CTX_DELETE);
sleep(1);
#endif
break;
}
default:
{
break;
}
}
break;
}
case CI_DAT_PRIM_UL_TP_IND:
{
char respBuffer[255];
CiDatPrimUlTpInd *pDatPrimU1TpInd = (CiDatPrimUlTpInd *)pParam;
//how to handle this????????
sprintf(respBuffer, "CI_DAT_PRIM_UL_TP_IND:(minLimitBytes)%d\r\n",
pDatPrimU1TpInd->minLimitBytes);
if (!GET_SIM1_FLAG(indHandle)) {
ATRESP(IND_REQ_HANDLE, 0, 0, respBuffer);
} else {
ATRESP(IND_REQ_HANDLE_1, 0, 0, respBuffer);
}
break;
}
default:
break;
}
F_LEAVE(datInd5);
}
static inline BOOL isValidMbmsTime(int val)
{
return val >= TEL_AT_MBMS_SET_VAL_MIN && val <= TEL_AT_MBMS_SET_VAL_TIME_MAX;
}
static BOOL HexToTmgi (CiDatMbmsTmgi* tmgi, const char *hex, int len)
{
if (len < 11)
return FALSE;
int serviceId, mcc, mnc, mncDigit;
mncDigit = len == 11 ? 2 : 3;
HexToBin(hex, &serviceId, 6);
HexToBin(hex + 6, &mcc, 3);
HexToBin(hex + 9, &mnc, mncDigit);
tmgi->serviceId = serviceId;
tmgi->mcc = mcc;
tmgi->mnc = mnc;
tmgi->mncDigit = mncDigit;
return TRUE;
}
static BOOL getSaiValue( const utlAtParameterValue_P2c param_value_p,
int index,
int *value_p)
{
if (index == 3) {
CHAR param3[16];
INT16 param3Len;
if (getExtString(param_value_p, 3, param3, sizeof(param3) -1, &param3Len, NULL)) {
int val = atoi((char*)param3);
if (val >= TEL_AT_MBMS_SET_VAL_MIN && val <= TEL_AT_MBMS_SET_SAI_VAL_MAX) {
*value_p = val;
return TRUE;
}
}
return FALSE;
}
return getExtValue(param_value_p, index, value_p,
TEL_AT_MBMS_SET_VAL_MIN,
TEL_AT_MBMS_SET_SAI_VAL_MAX,
TEL_AT_MBMS_SET_VAL_DEFAULT);
}
static BOOL getSaiInfo(CiDatPrimSaiInfo *saiInfo, const utlAtParameterValue_P2c parameter_values_p, int offset)
{
int frequency_count = 0, sai = 0;
if (!getSaiValue(parameter_values_p, offset, &sai)) {
ERRMSG(getSaiInfo, "getSaiInfo(offset=%d): fail to get sai\n", offset);
return FALSE;
}
if (!getExtValue(parameter_values_p, offset+1, &frequency_count,
TEL_AT_MBMS_SET_VAL_MIN, CI_DAT_MBMS_MAX_FREQ, TEL_AT_MBMS_SET_VAL_DEFAULT)) {
ERRMSG(getSaiInfo1, "getSaiInfo(offset=%d): fail to get frequency_count\n", offset);
return FALSE;
}
if (frequency_count > CI_DAT_MBMS_MAX_FREQ) {
ERRMSG(getSaiInfo2, "getSaiInfo(offset=%d): invalid frequency_count: %d\n", offset, frequency_count);
return FALSE;
}
saiInfo->sai = sai;
saiInfo->numOfFreq = frequency_count;
int cnt1;
for (cnt1 = 0; cnt1 < frequency_count; cnt1++) {
int freq;
if (!getExtValue(parameter_values_p, offset + 2 + cnt1, &freq,
TEL_AT_MBMS_SET_VAL_MIN, TEL_AT_MBMS_SET_FREQ_VAL_MAX, TEL_AT_MBMS_SET_VAL_DEFAULT)) {
ERRMSG(getSaiInfo3, "getSaiInfo(offset=%d): fail to get freq[%d]\n", offset, cnt1);
return FALSE;
}
saiInfo->freq[cnt1] = freq;
}
return TRUE;
}
/************************************************************************************
* F@: ciMBMS - GLOBAL API for AT%MBMSCMD -command
*
*/
RETURNCODE_T ciMBMS( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p);
UNUSEDPARAM(num_parameters);
UNUSEDPARAM(info_text_p);
RETURNCODE_T rc = INITIAL_RETURN_CODE;
CiReturnCode ret = CIRC_FAIL;
F_ENTER(ciMBMS0);
UINT32 atHandle = MAKE_AT_HANDLE(*(TelAtParserID *)arg_p);
/*
* Put parser index into the variable
*/
*xid_p = atHandle;
//INFOMSG(ciMBMS, "ciMBMS: atHandle = %d.\n", atHandle);
/*
* process operation
*/
switch ( op )
{
case TEL_EXT_SET_CMD: /* AT%MBMSCMD */
{
INT16 cmdlen;
CHAR cmdstr[30] = "";
if((getExtString(parameter_values_p, 0, cmdstr, TEL_AT_MBMS_SET_VAL_MAX, &cmdlen, NULL) == TRUE))
{
BOOL cmdValid = FALSE;
int ncmd = 127 , count = 0;
for(count = 0; count < (int)(sizeof(mbmsCmd_params) / sizeof(mbmsCmd_params[0])); count++)
{
if(strcmp( (char *)cmdstr, (const char *)mbmsCmd_params[count].pInputName) == 0)
{
ncmd = mbmsCmd_params[count].nCmdType;
//DBGMSG(ciMBMS1, "ciMBMS: nCmd[%d], cmdstr[%s]\n", ncmd, cmdstr);
break;
}
}
if (CI_DAT_MBMS_CMD_DEVICE_INFO == ncmd){
//coverity[string_null:SUPPRESS]
ATRESP( atHandle, ATCI_RESULT_CODE_OK, 0, "%MBMSCMD: 255\r\n");
break;
}
CiDatPrimSetMbmsCmdReq *pSetMbmsReq = utlCalloc(1, sizeof(CiDatPrimSetMbmsCmdReq));
if (pSetMbmsReq == NULL){
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_MEMORY_FAILURE, NULL);
break;
}
if( ncmd == CI_DAT_MBMS_CMD_ACT || ncmd == CI_DAT_MBMS_CMD_DEACT )
{
CHAR tmgiString[TEL_AT_MBMS_SET_VAL_TMGI_LENGTH + ATCI_NULL_TERMINATOR_LENGTH];
INT16 addrStrLen;
int sessionID = 0;
CHAR mip[64];
INT16 mipLen;
if((TRUE == getExtString(parameter_values_p, 1, tmgiString, TEL_AT_MBMS_SET_VAL_TMGI_LENGTH, &addrStrLen, NULL))
&& (TRUE == getExtValue(parameter_values_p, 2, &sessionID, TEL_AT_MBMS_SET_VAL_MIN, TEL_AT_MBMS_SET_VAL_COM_MAX, TEL_AT_MBMS_SET_VAL_DEFAULT))
&& TRUE == getExtString(parameter_values_p, 3, mip, sizeof(mip) -1, &mipLen, NULL))
{
//DBGMSG(ciMBMS2, "ciMBMS: tmgi[%d]=%s, sessionID = %d, multi-ip = %s\n",
// addrStrLen, tmgiString, sessionID, mip);
cmdValid = HexToTmgi(&pSetMbmsReq->tmgi, (const char*)tmgiString, addrStrLen);
}
}
else if ( ncmd == CI_DAT_MBMS_CMD_SET_PREFER ){
CHAR preferStr[3];
INT16 vallen;
if ( getExtString(parameter_values_p, 1, preferStr, 1, &vallen, NULL) == TRUE){
if(strcmp((const char*)preferStr, "0")==0 || strcmp((const char*)preferStr, "1") == 0)
{
//remap the preference value between ril and CCI. CCI interface starts from a "NONE" value
pSetMbmsReq->prefer = atoi((const char*)preferStr) + 1;
cmdValid = TRUE;
}
}
}
else if ( (CI_DAT_MBMS_CMD_GET_NW_TIME == ncmd) || (CI_DAT_MBMS_CMD_GET_SIGNAL_LEVEL == ncmd)
||(CI_DAT_MBMS_CMD_GET_NW_INFO == ncmd) ||(CI_DAT_MBMS_CMD_GET_MODEM_STATUS== ncmd)
|| (CI_DAT_MBMS_CMD_DEACT_ALL == ncmd) || (CI_DAT_MBMS_CMD_GET_CURRENT_SAIS == ncmd) )
{
cmdValid = TRUE;
}
else if ( CI_DAT_MBMS_CMD_SET_HYSTERESIS == ncmd ){
int session_out_delay_ms = 0, mbms_out_delay_ms = 0;
CHAR param1[16], param3[16];
INT16 param1Len, param3Len;
if ( getExtString(parameter_values_p, 1, param1, 2, &param1Len, NULL) == TRUE
&& getExtValue(parameter_values_p, 2, &session_out_delay_ms, TEL_AT_MBMS_SET_VAL_MIN, TEL_AT_MBMS_SET_VAL_TIME_MAX, TEL_AT_MBMS_SET_VAL_DEFAULT) == TRUE
&& getExtString(parameter_values_p, 3, param3, sizeof(param3) -1, &param3Len, NULL) == TRUE
&& getExtValue(parameter_values_p, 4, &mbms_out_delay_ms, TEL_AT_MBMS_SET_VAL_MIN, TEL_AT_MBMS_SET_VAL_TIME_MAX, TEL_AT_MBMS_SET_VAL_DEFAULT) == TRUE )
{
int session_in_delay_ms = atoi((const char *)param1);
int mbms_in_delay_ms = atoi((const char *)param3);
if (isValidMbmsTime(session_in_delay_ms)&& isValidMbmsTime(mbms_in_delay_ms)) {
pSetMbmsReq->inSessionHysteresis = session_in_delay_ms;
pSetMbmsReq->outSessionHysteresis = session_out_delay_ms;
pSetMbmsReq->inMbmsHysteresis = mbms_in_delay_ms;
pSetMbmsReq->inMbmsHysteresis = mbms_out_delay_ms;
cmdValid = TRUE;
}
}
}
else if ( CI_DAT_MBMS_CMD_SET_AVAILABILITY_INFO == ncmd ){
CHAR tmgiString[TEL_AT_MBMS_SET_VAL_TMGI_LENGTH + ATCI_NULL_TERMINATOR_LENGTH];
INT16 addrStrLen;
int sai_count = 0;
if ( (getExtString(parameter_values_p, 1, tmgiString, TEL_AT_MBMS_SET_VAL_TMGI_LENGTH, &addrStrLen, NULL) == TRUE)
&& (TRUE == getExtValue(parameter_values_p, 2, &sai_count, TEL_AT_MBMS_SET_VAL_MIN, CI_DAT_MBMS_MAX_SAI, TEL_AT_MBMS_SET_VAL_DEFAULT))
)
{
//DBGMSG(ciMBMS3, "ciMBMS: tmgi[%d]=%s\n", addrStrLen, tmgiString);
cmdValid = HexToTmgi(&pSetMbmsReq->tmgi, (const char*)tmgiString, addrStrLen);
if (cmdValid) {
pSetMbmsReq->numOfSai = sai_count;
if (sai_count>0) {
int offset = 3;
int cnt;
for (cnt = 0; cnt < sai_count; cnt++) {
if (!getSaiInfo(&pSetMbmsReq->saiInfo[cnt], parameter_values_p, offset)) {
cmdValid = FALSE;
break;
}
offset = offset + 2 + pSetMbmsReq->saiInfo[cnt].numOfFreq;
}
}
}
}
}
if( !cmdValid )
{
utlFree(pSetMbmsReq);
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_INVALID_PARAM, NULL);
}
else
{
pSetMbmsReq->cmd= ncmd;
//DBGMSG(ciMBMS4, "ciMBMS: MBMSCMD set: cmd[%d],enabler[%d],serviceId[%d],mcc[%d],mnc[%d], preference[%d].\n", pSetMbmsReq->cmd ,pSetMbmsReq->enabler, pSetMbmsReq->tmgi.serviceId, pSetMbmsReq->tmgi.mcc, pSetMbmsReq->tmgi.mnc, pSetMbmsReq->prefer);
/* Send the CI Request. */
ret = ciRequest( gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_SET_MBMS_CMD_REQ, MAKE_CI_REQ_HANDLE(atHandle, CI_DAT_PRIM_SET_MBMS_CMD_REQ), (void *)pSetMbmsReq );
}
}
else
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_INVALID_PARAM, NULL);
}
break;
}
case TEL_EXT_GET_CMD: /*AT%MBMSCMD?*/
{
/*reset global Mbms Area Info Counter and total Number*/
gMbmsAreaCnt = 0;
gMbmsAreaNum = 0;
ret = ciRequest( gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_GET_MBMS_CMD_REQ, MAKE_CI_REQ_HANDLE(atHandle, CI_DAT_PRIM_GET_MBMS_CMD_REQ),
NULL );
break;
}
case TEL_EXT_TEST_CMD:
{
size_t i = 0;
char mbmsBuf[350];
sprintf(mbmsBuf, "%%MBMSCMD: (");
for (i = 0; i < sizeof(mbmsCmd_params)/sizeof(mbmsCmd_params[0]); i++)
{
sprintf(mbmsBuf, "%s\"%s\",", mbmsBuf,mbmsCmd_params[i].pInputName);
}
mbmsBuf[strlen(mbmsBuf)-1] = '\0';
strcat(mbmsBuf, ")\r\n");
ret = ATRESP( atHandle, ATCI_RESULT_CODE_OK, 0, mbmsBuf);
}
break;
default:
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL);
break;
}
}
/* handle the return value */
rc = HANDLE_RETURN_VALUE(ret);
F_LEAVE(ciMBMS5);
return(rc);
}
/************************************************************************************
* F@: ciMBMSEv - GLOBAL API for AT%MBMSEV -command
*
*/
RETURNCODE_T ciMBMSEv( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p);
UNUSEDPARAM(num_parameters);
UNUSEDPARAM(info_text_p);
F_ENTER(ciMBMSEv0);
RETURNCODE_T rc = INITIAL_RETURN_CODE;
CiReturnCode ret = CIRC_FAIL;
UINT32 atHandle = MAKE_AT_HANDLE(*(TelAtParserID *)arg_p);
/*
* Put parser index into the variable
*/
*xid_p = atHandle;
//DBGMSG(ciMBMSEv, "ciMBMSEv: atHandle = %d.\n", atHandle);
/*
* process operation
*/
switch ( op )
{
case TEL_EXT_SET_CMD: /* AT%MBMSEV */
{
int ncmd = 0;
if((TRUE == getExtValue(parameter_values_p, 0, &ncmd, TEL_AT_MBMS_SET_VAL_MIN, TEL_AT_MBMS_SET_VAL_EV_MAX, TEL_AT_MBMS_SET_VAL_DEFAULT)))
{
CiDatPrimSetMbmsEvReq *pSetMbmsEvReq = utlCalloc(1, sizeof(CiDatPrimSetMbmsEvReq));
if (NULL == pSetMbmsEvReq)
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
}
else
{
pSetMbmsEvReq->cmd = (ncmd == 0)? FALSE : TRUE;
//DBGMSG(ciMBMSEv1, "ciMBMSEv: AT MBMSEV=%d\n", pSetMbmsEvReq->cmd);
/* Send the CI Request. */
ret = ciRequest( gAtciSvgHandle[CI_SG_ID_DAT], CI_DAT_PRIM_SET_MBMS_EV_REQ, MAKE_CI_REQ_HANDLE(atHandle, CI_DAT_PRIM_SET_MBMS_EV_REQ), (void *)pSetMbmsEvReq );
}
}
else
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_INVALID_PARAM, NULL);
}
break;
}
/*AT%MBMSEV?*/
case TEL_EXT_GET_CMD:
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL);
}
break;
case TEL_EXT_TEST_CMD:
{
//coverity[string_null:SUPPRESS]
ret = ATRESP( atHandle, ATCI_RESULT_CODE_OK, 0, (char *)"%%MBMSEV: (0,1)");
break;
}
default:
{
ret = ATRESP( atHandle, ATCI_RESULT_CODE_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL);
break;
}
}
/* handle the return value */
rc = HANDLE_RETURN_VALUE(ret);
F_LEAVE(ciMBMSEv2);
return(rc);
}
/*eMBMS function*/
/************************************************************************************
* F@: ciStarDONOF - GLOBAL API for GCF AT*DONOF -command
*
*/
RETURNCODE_T ciStarDONOF( const utlAtParameterOp_T op,
const char *command_name_p,
const utlAtParameterValue_P2c parameter_values_p,
const size_t num_parameters,
const char *info_text_p,
unsigned int *xid_p,
void *arg_p)
{
UNUSEDPARAM(command_name_p)
UNUSEDPARAM(num_parameters)
UNUSEDPARAM(info_text_p)
UNUSEDPARAM(parameter_values_p)
RETURNCODE_T rc = INITIAL_RETURN_CODE;
CiReturnCode ret = CIRC_FAIL;
int ret_ioctl = 0;
char respBuffer[255];
UINT32 atHandle = MAKE_AT_HANDLE( * (TelAtParserID *) arg_p );
*xid_p = atHandle;
//DBGMSG(ciStarDONOF, "ciStarDONOF: atHandle = %d.", atHandle);
int psdatastub;
switch (op)
{
case TEL_EXT_SET_CMD: /* AT*DONOF = */
case TEL_EXT_ACTION_CMD: /* AT*DONOF */
psdatastub = open(PSDATASTUB_NAME, O_RDWR);
if (psdatastub >= 0)
{
ret_ioctl = ioctl(psdatastub, PSDATASTUB_TOGGLE_DATA_ENABLE_DISABLE,
NULL);
if (ret_ioctl < 0 )
ret = ATRESP(atHandle, ATCI_RESULT_CODE_ERROR, 0, NULL);
else
{
atDonofState = ((atDonofState == TRUE)?FALSE:TRUE); //Toggle Flag in case of success
ret = ATRESP(atHandle, ATCI_RESULT_CODE_OK, 0, NULL);
}
close(psdatastub);
}
else
{
WARNMSG(ciStarDONOF1, "[ciStarDONOF]failed to open %s\n", PSDATASTUB_NAME);
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
}
break;
case TEL_EXT_GET_CMD: /* AT*DONOF? */
sprintf(respBuffer, "*DONOF=%d",((atDonofState==TRUE)?1:0));
ret = ATRESP(atHandle, ATCI_RESULT_CODE_OK, 0, respBuffer);
break;
case TEL_EXT_TEST_CMD: /* AT*DONOF=? */
default:
ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_OPERATION_NOT_SUPPORTED, NULL );
break;
}
rc = HANDLE_RETURN_VALUE(ret);
return(rc);
}