blob: 8f057d8172cb26fc7544ad8aabd97e780c161508 [file] [log] [blame]
/******************************************************************************
*(C) Copyright 2021 ASR MicroElectronics Ltd.
* All Rights Reserved
******************************************************************************/
/*--------------------------------------------------------------------------------------------------------------------
* -------------------------------------------------------------------------------------------------------------------
*
* Filename: ecall_daemon.c
*
* Description: ecall_daemon
*
* History:
* June 22, 2021 - ZhouTao Creation of file
*
* Notes:
*
******************************************************************************/
#ifndef NO_AUDIO
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <libubus.h>
#include <fcntl.h>
#include "ecall_daemon.h"
#include "at_tok.h"
#include "ril.h"
#include "rilutil.h"
#include "audio_if_parameter.h"
#include "ecall_sms.h"
#define ECALL_CLCOK_ALARM CLOCK_BOOTTIME_ALARM
#define MAX_NUMBER_LEN 40
#define NG_ECALL_MT_DEFAULT_TEST_NUMBER_URL "default.virtual"
#define NG_ECALL_MO_DEFAULT_TEST_NUMBER_URL "urn:service:test.sos.ecall"
#define ECALL_SAVE_ALACK_PATH "./tmp/ecallSaveAlAck"
#define ECALL_SAVE_ALACK_COUNT_MAX (100)
char testNumber[MAX_NUMBER_LEN] = {'N','U','L','L', 0};
char reconfigureNumber[MAX_NUMBER_LEN] = {'N','U','L','L', 0};
char smsMsdNumber[MAX_NUMBER_LEN] = {'1', '1', '2', 0}; //ECALL_SMS_FALLBACK_NUMBER
char nGMtEcallTestNumUrl[MAX_NUMBER_LEN] = {0};
char nGMoEcallTestNumUrl[MAX_NUMBER_LEN] = {0};
char ecall_msd[300] = {0};
char ecall_msd_hex[150] = {0};
static char gEcallMsdPath[64] = {0};
static int gEcallMsdLen = 0;
static int gEcallMsdSavedFlag = 0;
static int gEcallCallID = 0;
static int gPushVal = 0;
static int gSmsMsd = 0;
static int gEcallNW = 0;
static int gEcallType = 0;
static int gEcallCeer = 16;
static int gEcallRedial = 0;
static int gSimEcallOnly = 0;
static int gSimEcallActive = 0;
static int gEcallOnlySim = 0;
static int gEcallOnlySimValid = 0;
static int gEcallSmsProcess = 1;
static int gEcallSaveAlAckCnt = 0;
#ifdef EU
static int gEcallMode = 0; //default ecall mode is EU
#elif defined ERA
static int gEcallMode = 1;
#endif
static int gEcallDialCnt = 0;
static int gEcallSmsMsdCnt = 0;
static int gCurrentHasCallSet = 0;
static int gEacllUserUpdatedMsd = 0;
DAEMON_ECALL_STATUS gEcallStatus = DAEMON_ECALL_IDLE;
static int gEcallTimerInitialized = 0;
struct blob_buf send_at_b;
struct blob_buf ecall_sms_b;
struct blob_buf ecall_cmgr_b;
extern struct ubus_context *ecall_ctx;
extern void ecall_sms_parse_pdu(char *smsPdu);
static int gEcallUbusRilId = 0;
/* ecall global count define */
static int ECALL_AUTO_DIAL_ATTEMPTS = 10;
//static int ECALL_MANUAL_DIAL_ATTEMPTS = 10;
static int ECALL_SMS_MSD_RETRANSMIT_ATTEMPTS = 10; //INT_MEM_TRANSMIT_ATTEMPTS
/* ecall global timer value define */
static int ECALL_PSAP_CALLBACK_TMR_EU = 60*60; //60min
static int ECALL_PSAP_CALLBACK_TMR_ERA = 20*60; //20min
static int ECALL_DIAL_SETUP_TMR_EU = 60; //60s
static int ECALL_DIAL_SETUP_TMR_ERA = 30; //30s
static int ECALL_REDIAL_TMR_ERA = 30; //30s for ecall abnormal disconnect
static int ECALL_REDIAL_HANGUP_TMR_INT = 5; //5s for ivs hangup and redial timer interval
static int ECALL_DIAL_CLEARDOWN_TMR = 60*60; //60min
static int ECALL_WAIT_HL_ACK_TMR = 5; //5s--T6
static int ECALL_SMS_SEND_MSD_TMR = 60*60; //60min
static int ECALL_WAIT_LL_ACK_TMR = 20; //20s--T7
static int ECALL_NAD_DEREGISTRATION_TMR_ERA = 2*60*60; //120min--NAD_DEREGISTRATION_TIME
static int ECALL_NAD_DEREGISTRATION_TMR_EU = 12*60*60; //720min--NAD_DEREGISTRATION_TIME
static int ECALL_WAIT_T6_T7_TMR = 25;//ECALL_WAIT_HL_ACK_TMR + ECALL_WAIT_LL_ACK_TMR; //25s--T6+T7 timer
static TIMER_t ecall_psap_callback_timer;
static TIMER_t ecall_dial_cleardown_timer;
static TIMER_t ecall_dial_setup_timer;
static TIMER_t ecall_redial_timer;
static TIMER_t ecall_wait_hl_ack_timer;
static TIMER_t ecall_sms_retransmit_timer;
static TIMER_t ecall_saved_sms_retransmit_timer;
static TIMER_t ecall_deregister_network_timer;
/* ecall timer callback function declared */
static void ecall_psap_callback_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_dial_cleardown_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_smsMsd_retransmit_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_retransmit_msd_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_saved_smsMsd_retransmit_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_deregister_network_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_setup_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_redial_setup_cb(int sigNum, siginfo_t *pInfo, void *p);
static void ecall_hang_up(void);
#define ecall_set_ecall_type(val) (gEcallType = val)
#define ecall_get_ecall_type() (gEcallType)
#define ecall_set_ecallNetwork(val) (gEcallNW = val)
#define ecall_get_ecallNetwork() (gEcallNW)
#define ecall_set_redial_flag(val) (gEcallRedial = val)
#define ecall_get_redial_flag() (gEcallRedial)
#define ecalL_daemon_set_ceerVal(val) (gEcallCeer = val)
#define ecall_daemon_get_ceerVal() (gEcallCeer)
#define ecall_set_sim_ecallOnly(val) (gSimEcallOnly = val)
#define ecall_get_sim_ecallOnly() (gSimEcallOnly)
#define ecall_set_sim_ecallActive(val) (gSimEcallActive = val)
#define ecall_get_sim_ecallActive() (gSimEcallActive)
#define ecall_set_ecallOnlySim(val) (gEcallOnlySim = val)
#define ecall_get_ecallOnlySim() (gEcallOnlySim)
#define ecall_set_ecallOnlySimValid(val) (gEcallOnlySimValid = val)
#define ecall_get_ecallOnlySimValid() (gEcallOnlySimValid)
#define ecall_daemon_set_smsProcess(val) (gEcallSmsProcess = val)
#define ecall_daemon_get_smsProcess() (gEcallSmsProcess)
#define ecall_set_ecall_hangup_redial_timer(val) (ECALL_REDIAL_HANGUP_TMR_INT = val)
#define ecall_get_ecall_hangup_redial_timer() (ECALL_REDIAL_HANGUP_TMR_INT)
#define ecall_set_smsMsd_send_count(val) (ECALL_SMS_MSD_RETRANSMIT_ATTEMPTS = val)
#define ecall_get_smsMsd_send_count() (ECALL_SMS_MSD_RETRANSMIT_ATTEMPTS)
#define ecall_set_ecalltimer_initialized(val) (gEcallTimerInitialized = val)
#define ecall_get_ecalltimer_initialized() (gEcallTimerInitialized)
#define ecall_get_ecall_redial_cnt() (gEcallDialCnt)
#define ecall_reset_ecall_redial_cnt() (gEcallDialCnt = 0)
#define ecall_get_ecall_status() (gEcallStatus)
int ecall_set_ecall_status(DAEMON_ECALL_STATUS ecallStatus)
{
gEcallStatus = ecallStatus;
return 0;
}
#define ecall_daemon_get_ecallPush() (gPushVal)
int ecall_daemon_set_ecallPush(int val)
{
gPushVal = val;
return 0;
}
int ecall_daemon_set_mode(int val)
{
gEcallMode = val;
return 0;
}
int ecall_daemon_get_mode(void)
{
return gEcallMode;
}
int ecall_current_is_ecallOnly_mode(void)
{
if (((ecall_get_sim_ecallActive() != 5) && (ecall_get_ecallOnlySim() > 0)) //ecallonlysim > 0
|| (ecall_get_sim_ecallActive() == 1) //cs ecall only
|| (ecall_get_sim_ecallActive() == 2) //ng ecall only
|| (ecall_get_sim_ecallActive() == 3)) //es and ng ecall only
{
return 1;
}
else
{
return 0;
}
}
unsigned int ecall_get_ubus_ril_id(void)
{
int ret = 0;
unsigned int id = 0;
if (gEcallUbusRilId > 0) {
return gEcallUbusRilId;
} else {
ret = ubus_lookup_id(ecall_ctx, "ril", &id);
if (ret == 0) {
gEcallUbusRilId = id;
} else {
ECALL_Log("lookup ril object failed\n");
return 0;
}
}
return id;
}
char *ecall_strsep(char **s, const char *del)
{
char *begin = *s;
char *end = NULL;
if(begin == NULL)
return NULL;
end = strpbrk(begin, del);
if(end)
*end++ = '\0';
*s = end;
return begin;
}
char* ecallStrdup(const char* str)
{
char *result = NULL;
int length = 0;
if (str) {
length = strlen(str);
result = (char *)malloc(length +1);
}
if (result) {
memcpy(result, str, length);
result[length] = 0;
}
return result;
}
int at_tok_start(char **p_cur)
{
if (*p_cur == NULL)
{
return -1;
}
// skip prefix
// consume "^[^:]:"
*p_cur = strchr(*p_cur, ':');
if (*p_cur == NULL)
{
return -1;
}
(*p_cur)++;
return 0;
}
void skipWhiteSpace(char **p_cur)
{
if (*p_cur == NULL) return;
while (**p_cur != '\0' && isspace(**p_cur))
{
(*p_cur)++;
}
}
void skipNextComma(char **p_cur)
{
if (*p_cur == NULL) return;
while (**p_cur != '\0' && **p_cur != ',')
{
(*p_cur)++;
}
if (**p_cur == ',')
{
(*p_cur)++;
}
}
char * nextTok(char **p_cur)
{
char *ret = NULL;
skipWhiteSpace(p_cur);
if (*p_cur == NULL)
{
ret = NULL;
}
else if (**p_cur == '"')
{
(*p_cur)++;
ret = ecall_strsep(p_cur, "\"");
skipNextComma(p_cur);
}
else
{
ret = ecall_strsep(p_cur, ",");
}
return ret;
}
int at_tok_nextint_base(char **p_cur, int *p_out, int base, int uns)
{
char *ret;
if (*p_cur == NULL)
{
return -1;
}
ret = nextTok(p_cur);
if (ret == NULL)
{
return -1;
}
else
{
long l;
char *end;
if (uns)
l = strtoul(ret, &end, base);
else
l = strtol(ret, &end, base);
*p_out = (int)l;
}
return 0;
}
int at_tok_nextint(char **p_cur, int *p_out)
{
return at_tok_nextint_base(p_cur, p_out, 10, 0);
}
int at_tok_nextstr(char **p_cur, char **p_out)
{
if (*p_cur == NULL)
{
return -1;
}
*p_out = nextTok(p_cur);
return 0;
}
/** returns 1 on "has more tokens" and 0 if no */
int at_tok_hasmore(char **p_cur)
{
return !(*p_cur == NULL || **p_cur == '\0');
}
int ecall_invoke_noreply(unsigned int sAtpIndex, const char *service,
const char *method, struct blob_attr *msg)
{
UNUSED(sAtpIndex);
struct ubus_context *ctx;
int rc;
uint32_t id;
struct ubus_request req;
ctx = ubus_connect(NULL);
if (!ctx)
return -1;
ubus_add_uloop(ctx);
/* Look up the target object id by the object path */
rc = ubus_lookup_id(ctx, service, &id);
if (rc != 0)
return -1;
rc = ubus_invoke_async(ctx, id, method, msg, &req);
if (rc != 0)
return -1;
/* cancel req (on client side) because noreply is needed */
ubus_abort_request(ctx, &req);
return 0;
}
static void ecall_rilrequest_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int rilid = 0;
unsigned int rilerror = 0;
void *data = NULL;
int datalen = 0;
int ret = 0;
char *respPtr = NULL;
//ENTER();
ret = rilutil_parseResponse(msg, &rilid, &rilerror, &data, &datalen);
if (ret)
goto end;
ECALL_Log("ecall_rilrequest_cb recv rilid %d, rilerror %d.\n", rilid, rilerror);
switch (rilid) {
case RIL_REQUEST_SEND_ATCMD:
{
if (rilerror) {
ECALL_Log("Get at response err %d\n", rilerror);
goto end;
}
ECALL_Log("Get at response: %s\n", data);
if (data)
{
respPtr = data;
if (strncmp(respPtr, "*ECALLONLY:", strlen("*ECALLONLY:")) == 0)
{
ecall_handle_ecallOnly_response(respPtr);
}
if (strncmp(respPtr, "*ECALLONLYSIM:", strlen("*ECALLONLYSIM:")) == 0)
{
ecall_handle_ecallOnlySim_response(respPtr);
}
else if (strncmp(respPtr, "+CEER:", strlen("+CEER:")) == 0)
{
ecall_handle_ceer_response(respPtr);
}
else if (strncmp(respPtr, "*ECALLMSDGEN:", strlen("*ECALLMSDGEN:")) == 0)
{
ecall_handle_msdGen_response(respPtr);
}
else
{
}
}
break;
}
case RIL_REQUEST_GET_SIM_STATUS:
{
if (rilerror) {
ECALL_Log("Get sim status err %d\n", rilerror);
goto end;
}
ECALL_Log("Get sim status: %s\n", data);
}
break;
case RIL_REQUEST_SEND_SMS:
{
if (rilerror) {
ECALL_Log("Get send sms status err %d\n", rilerror);
goto end;
}
/* sms send successed. */
ecallHandleSmsMsdResp();
ECALL_Log("ecall send sms status: %s\n", data);
}
break;
case RIL_REQUEST_GET_NW_DOMAIN:
if (rilerror) {
ECALL_Log("Get network status err %d\n", rilerror);
goto end;
}
/* sms send successed. */
ret = handle_ecallNetwork((char*)data);
if (ret > 0) {
ecall_set_ecallNetwork(1);
} else {
ecall_set_ecallNetwork(0);
}
ECALL_Log("ecall get network status: %d\n", ret);
break;
case RIL_REQUEST_GET_CMGR:
if (rilerror) {
ECALL_Log("Get cmgr err %d\n", rilerror);
goto end;
}
ECALL_Log("ecall get cmgr data: %s\n", (char *)data);
ecallHandleSmsReceived((const char *)data);
break;
default:
break;
}
end:
if (data)
rilutil_freeResponseData(rilid, data, datalen);
//LEAVE();
}
unsigned int ecall_ubusSendEcallCmd(unsigned int sAtpIndex, unsigned int op_id, unsigned int param1, char* MSD)
{
unsigned int length;
struct blob_buf outBlob;
unsigned int ret = 1;
unsigned int origParserId = sAtpIndex;
memset(&outBlob, 0, sizeof(outBlob));
blob_buf_init(&outBlob, 0);
if(MSD != NULL)
length = sizeof(op_id) + sizeof(param1) + 140; //ECALL_MSD_BIN_MAX_LEN 140
else
length = sizeof(op_id) + sizeof(param1);
//DBGMSG(ubusSendEcallCmd, "%s: length = %d.\n", __FUNCTION__, length);
blobmsg_add_u32(&outBlob, "length", (unsigned int)length);
blobmsg_add_u32(&outBlob, "op", (unsigned int)op_id);
blobmsg_add_u32(&outBlob, "param1", (unsigned int)param1);
if(MSD != NULL)
blobmsg_add_string(&outBlob, "data", MSD);
if (ecall_invoke_noreply(origParserId, "audio_if", AUDIO_IF_UBUS_ECALL_DATA_SET, outBlob.head) == 0) {
//ret = ATRESP( atHandle, ATCI_RESULT_CODE_OK, 0, NULL);
ret = 0;
ECALL_Log("%s: succeed in sending AUDIO_IF_UBUS_ECALL_DATA_SET\n", __FUNCTION__);
} else {
//ret = ATRESP( atHandle, ATCI_RESULT_CODE_CME_ERROR, CME_UNKNOWN, NULL);
ret = 1;
ECALL_Log("%s: fail to send AUDIO_IF_UBUS_ECALL_DATA_SET\n", __FUNCTION__);
}
blob_buf_free(&outBlob);
return(ret);
}
int ecallSendAtCmd(void *data, int sync)
{
int ret;
unsigned int id = 0;
int len = 0;
struct ubus_request *req = NULL;
len = strlen(data)+1;
blob_buf_init(&send_at_b, 0);
rilutil_makeRequestBlob(&send_at_b, RIL_REQUEST_SEND_ATCMD, data, len);
id = ecall_get_ubus_ril_id();
if (id == 0)
return -1;
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (req == NULL) {
ECALL_Log("leave ecallSendAtCmd: lack of memory\n");
return -2;
}
if (sync)
ret = ubus_invoke(ecall_ctx, id, "ril_request", send_at_b.head, ecall_rilrequest_cb, NULL, 0);
else {
ret = ubus_invoke_async(ecall_ctx, id, "ril_request", send_at_b.head, req);
req->data_cb = ecall_rilrequest_cb;
req->priv = data;
ubus_complete_request_async(ecall_ctx, req);
}
return ret;
}
static void ecall_start_auto_answer(int timeVal)
{
char arr[64] = {0};
sprintf(arr, "ATS0=1\r");
ecallSendAtCmd(arr, 1);
ecall_disable_timer(ecall_psap_callback_timer);
ecall_enable_timer(ecall_psap_callback_timer, timeVal);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
void ecall_stop_auto_answer(void)
{
char arr[64] = {0};
int ret = 0;
sprintf(arr, "ATS0=0\r");
ret = ecallSendAtCmd(arr, 1);
ECALL_Log("%s: ret=%d, leave.", __FUNCTION__, ret);
return;
}
/* ecall timer callback function define */
static void ecall_psap_callback_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
ECALL_Log("%s: enter, ecall status=%d.\n", __FUNCTION__, gEcallStatus);
ecall_stop_auto_answer();
return;
}
static void ecall_dial_cleardown_nomal(void)
{
char arr[64] = {0};
int ret = 0;
sprintf(arr, "ATH\r");
ret = ecallSendAtCmd((void*)arr, 1);
sleep(1); //sleep 1s
ECALL_Log("%s: ecall send hang up at for nomal call, ret=%d.\n", __FUNCTION__, ret);
return;
}
static void ecall_dial_cleardown_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
char arr[64] = {0};
int ret = 0;
sprintf(arr, "AT+CECALLINSIDE=5\r");
ret = ecallSendAtCmd((void*)arr, 1);
ECALL_Log("%s: ecall send hang up at ret=%d.\n", __FUNCTION__, ret);
sleep(2); //sleep 2s
return;
}
static void ecall_setup_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
ECALL_Log("%s: enter, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
if (gEcallDialCnt < ECALL_AUTO_DIAL_ATTEMPTS) {
ecall_hang_up(); //hangup ecall
}
ecall_disable_timer(ecall_redial_timer);
ecall_enable_timer(ecall_redial_timer, ecall_get_ecall_hangup_redial_timer());
return;
}
static void ecall_redial_setup_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
ECALL_Log("%s: enter, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
if (ecall_daemon_get_mode() == 1) { //ERA, redial timer=30s, 33464 spec define era redial is retry 10 times within 5mins
if (gEcallDialCnt < ECALL_AUTO_DIAL_ATTEMPTS) {
if (ecall_get_ecall_status() < DAEMON_ECALL_MO_SETUP) { //redial and send msd
ecall_redial_and_send_msd();
gEcallDialCnt++;
} else {
ECALL_Log("%s1: redial failed, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
}
} else {
//if (gEcallCallID != 0) { //has ecall dialing and alerting and 30s timeout, hang up it
// ecall_dial_cleardown_cb(NULL); //hangup ecall
//}
ECALL_Log("%s: redial attempts times has exhausted, wait PSAP answer call or network hang up call.\n", __FUNCTION__);
}
} else { //EU, redial timer=60s, when call isn't setup or call is ring always but not answer, IVS need redial witnin 2mins
if (ecall_get_ecall_status() < DAEMON_ECALL_MO_SETUP) { //redial and send msd
ecall_redial_and_send_msd();
} else {
ECALL_Log("%s2: redial failed, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
}
}
return;
}
static void ecall_retransmit_msd_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
ECALL_Log("%s: enter, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
if (ecall_daemon_get_mode() == 1) { //ERA mode, when msd send failed IVS need use SMS send msd.
if (ecall_get_ecall_status() == DAEMON_ECALL_MO_MSD || ecall_get_ecall_status() == DAEMON_ECALL_MO_SETUP) {
if (gEcallCallID != 0) //current ecall isn't hangup, so use sms send msd
ecall_sms_send_cfg_msd();
else //current ecall has hangup, ivs need redial and send msd
ecall_redial_and_send_msd();
} else {
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
}
} else { //EU mode, when msd send failed and duration timer=2min isn't expiered, IVS need redial and send msd via in-band.
if (ecall_get_ecall_status() >= DAEMON_ECALL_MO_MSD) {
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
ecall_retransmit_send_msd();
} else {
ECALL_Log("%s: redial failed, gEcallDialCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallDialCnt, gEcallStatus);
return;
}
}
return;
}
static void ecall_smsMsd_retransmit_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
int ret = 0;
ECALL_Log("%s: enter, gEcallSmsMsdCnt=%d, ecall status=%d.\n", __FUNCTION__, gEcallSmsMsdCnt, gEcallStatus);
if (ecall_daemon_get_mode() == 1 && gSmsMsd == 1) {
if (gEcallSmsMsdCnt < ECALL_SMS_MSD_RETRANSMIT_ATTEMPTS) {
if (ecall_get_ecall_status() == DAEMON_ECALL_SMS) {
ret = ecall_sms_send_cfg_msd();
if (ret == 0 || ret == -1) {
ecall_disable_timer(ecall_sms_retransmit_timer);
ecall_enable_timer(ecall_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
}
} else {
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
}
} else {
gEcallSmsMsdCnt = 0;
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
}
} else {
ecall_msd_saved("/tmp/ecall_msd_sms_send_failed", ecall_msd);
ECALL_Log("ecall_smsMsd_retransmit_cb: sms send msd failed and gEcallMode %d, gSmsMsd %d.", gEcallMode, gSmsMsd);
}
return;
}
static void ecall_saved_smsMsd_retransmit_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
ecall_get_network_status();
ECALL_Log("%s: enter, gEcallNW=%d, gEcallMode=%d, gEcallMsdSavedFlag=%d.\n", __FUNCTION__, gEcallNW, gEcallMode, gEcallMsdSavedFlag);
if (ecall_get_ecallNetwork() > 0 || (gEcallMsdSavedFlag > 0))
{
if ((ecall_daemon_get_mode() == 1) && (gEcallMsdSavedFlag > 0))
{
ecall_sms_send_saved_msd();
}
}
else
{
//ecallStopTimer(&ecall_saved_sms_retransmit_timer);
ecall_disable_timer(ecall_saved_sms_retransmit_timer);
//ecallStartTimer(&ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
ecall_enable_timer(ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
}
return;
}
static void ecall_deregister_network_cb(int sigNum, siginfo_t *pInfo, void *p)
{
UNUSED(sigNum);
UNUSED(pInfo);
UNUSED(p);
char arr[64] = {0};
sprintf(arr, "AT*ECALLREG=0\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
ecall_disable_timer(&ecall_deregister_network_timer);
return;
}
static void ecall_hang_up(void)
{
char arr[64] = {0};
int ret = 0;
//sprintf(arr, "AT+CECALLINSIDE=5\r");
sprintf(arr, "ATH\r");
ret = ecallSendAtCmd((void*)arr, 1);
ECALL_Log("%s: ecall send hang up at ret=%d.\n", __FUNCTION__, ret);
return;
}
void ecall_redial_and_send_msd(void)
{
int ecallType = 0;
int pushVal = 0;
char arr[400] = {0};
int ret = 0;
ecallType = gEcallType;
pushVal = ecall_daemon_get_ecallPush();
ECALL_Log("%s: this is %d redial.", __FUNCTION__, gEcallDialCnt);
ECALL_Log("%s: ecall type=%d, ecall push=%d.", __FUNCTION__, ecallType, pushVal);
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
if (0 != strlen(ecall_msd)) {
/* AT*ECALLMSD=MSD */
memset(arr, 0, 400);
sprintf(arr, "AT*ECALLMSD=%s\r", ecall_msd);
ret = ecallSendAtCmd((void*)arr, 0);
/* AT+CECALL=ecallType */
memset(arr, 0, 400);
sprintf(arr, "AT+CECALL=%d\r", ecallType);
ret = ecallSendAtCmd((void*)arr, 0);
/* AT*ECALLPUSH */
if (pushVal) {
memset(arr, 0, 400);
sprintf(arr, "AT*ECALLPUSH\r");
ret = ecallSendAtCmd((void*)arr, 0);
}
ECALL_Log("%s: redial success and ret=%d.", __FUNCTION__, ret);
} else {
ECALL_Log("%s: redial failed.", __FUNCTION__);
}
}
void ecall_retransmit_send_msd(void)
{
int ecallType = 0;
int pushVal = 0;
char arr[400] = {0};
int ret = 0;
ecallType = gEcallType;
pushVal = ecall_daemon_get_ecallPush();
ECALL_Log("%s: ecall type=%d, ecall push=%d.", __FUNCTION__, ecallType, pushVal);
ecall_set_ecall_status(DAEMON_ECALL_MO_SETUP);
if (0 != strlen(ecall_msd)) {
/* AT*ECALLMSD=MSD */
memset(arr, 0, 400);
sprintf(arr, "AT*ECALLMSD=%s\r", ecall_msd);
ret = ecallSendAtCmd((void*)arr, 0);
/* AT*ECALLPUSH */
if (pushVal) {
memset(arr, 0, 400);
sprintf(arr, "AT*ECALLPUSH\r");
ret = ecallSendAtCmd((void*)arr, 0);
}
ECALL_Log("%s: retransmit send msd success and ret=%d.", __FUNCTION__, ret);
} else {
ECALL_Log("%s: retransmit send msd failed.", __FUNCTION__);
}
}
void ecall_redial_only(void)
{
int ecallType = 0;
char arr[64] = {0};
int ret = 0;
ecallType = gEcallType;
//ecall_dial_cleardown_cb(NULL); //hangup ecall
sprintf(arr, "AT+CECALL=%d\r", ecallType);
ret = ecallSendAtCmd((void*)arr, 1);
ECALL_Log("ecall_redial_only: redial success and ecallType=%d, ret=%d.", ecallType, ret);
return;
}
int RildReady(void)
{
unsigned int ril_id;
ril_id = ecall_get_ubus_ril_id();
if (ril_id > 0)
return 1;
return 0;
}
int ecall_subscriber_cb(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(ctx);
UNUSED(obj);
UNUSED(req);
UNUSED(method);
unsigned int requestid = 0;
unsigned int rilerrno = 0;
void *response = NULL;
int responselen = 0;
int ret = 0;
ret = rilutil_parseResponse(msg, &requestid, &rilerrno, &response, &responselen);
if (ret)
goto end;
ECALL_Log("ecall_subscriber_cb: rcv %d", requestid);
ecall_handle_ril_ind(ctx, requestid, rilerrno, response, responselen);
end:
if (response)
rilutil_freeResponseData(requestid,response,responselen);
return 0;
}
void ecall_subscriber_remove_cb(struct ubus_context *ctx, struct ubus_subscriber *obj, uint32_t id)
{
UNUSED(ctx);
UNUSED(obj);
UNUSED(id);
ECALL_Log("ecall_subscriber_remove_cb");
}
void ecall_handle_ecallOnly_response(const char *s)
{
int err;
char *line = ecallStrdup((char *)s);
int ecallActive = 0;
int simEcall = 0;
char *pStart = NULL;
ECALL_Log("%s: %s", __FUNCTION__,s);
pStart = line;
err = at_tok_start(&line);
if(err < 0) {
goto error;
}
if (at_tok_hasmore(&line))
{
err = at_tok_nextint(&line, &ecallActive);
if(err < 0)
goto error;
}
if (at_tok_hasmore(&line))
{
err = at_tok_nextint(&line, &simEcall);
if(err < 0)
goto error;
}
ECALL_Log("%s rcv: ecallActive=%d, simEcall=%d", __FUNCTION__, ecallActive, simEcall);
ecall_set_sim_ecallActive(ecallActive);
ecall_set_sim_ecallOnly(simEcall);
error:
if(pStart) {
free(pStart);
}
return;
}
void ecall_handle_ecallOnlySim_response(const char *s)
{
int err;
char *line = ecallStrdup((char *)s);
int ecallOnlySim = 0;
char *pStart = NULL;
ECALL_Log("%s: %s", __FUNCTION__,s);
pStart = line;
err = at_tok_start(&line);
if(err < 0) {
goto error;
}
if (at_tok_hasmore(&line))
{
err = at_tok_nextint(&line, &ecallOnlySim);
if(err < 0)
goto error;
}
ECALL_Log("%s rcv: ecallOnlySim=%d", __FUNCTION__, ecallOnlySim);
ecall_set_ecallOnlySim(ecallOnlySim);
ecall_set_ecallOnlySimValid(1);
error:
if(pStart) {
free(pStart);
}
return;
}
int ecall_send_getEcallOnly_cmd(void)
{
int ret = 0;
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT*ECALLONLY?\r");
ret = ecallSendAtCmd(arr, 1);
ECALL_Log("%s: ret = %d.", __FUNCTION__, ret);
return ret;
}
int ecall_send_getEcallOnlySim_cmd(void)
{
int ret = 0;
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT*ECALLONLYSIM?\r");
ret = ecallSendAtCmd(arr, 1);
ECALL_Log("%s: ret = %d.", __FUNCTION__, ret);
return ret;
}
void ecall_set_voice_data(unsigned int cmd_id, unsigned int res_id, unsigned int param)
{
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT*ECALLVOICE=%d,%d,%d\r", cmd_id, res_id, param);
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
void ecall_reset_msd_timestamp(void)
{
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT*ECALLMSDCFG=5,1\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
int ecall_msd_saved(char *filePath, char *ecallMsd)
{
int ecallMsdFd = 0;
int ecallMsdLen = 0;
int ret = 0;
if ((strlen(filePath) > 0) && (strlen(ecallMsd) > 0)) {
ecallMsdLen = strlen(ecallMsd);
ECALL_Log("%s: ecallMsd file path is %s and length is %d.\n", __FUNCTION__, filePath, ecallMsdLen);
} else {
ECALL_Log("%s: file path or ecallMsd is NULL.\n", __FUNCTION__);
return -1;
}
ecallMsdFd = open (filePath, O_RDWR|O_CREAT|O_TRUNC, 0666);
if (ecallMsdFd < 0) {
ECALL_Log("%s: open file failed and ecallMsdFd=%d.\n", __FUNCTION__, ecallMsdFd);
return -1;
}
ret = write(ecallMsdFd, ecallMsd, ecallMsdLen);
if (ret < 0) {
ECALL_Log("%s: write ecall msd failed.\n", __FUNCTION__);
goto error;
} else if (ret < ecallMsdLen) {
ECALL_Log("%s: wrote less the buffer size and ret=%d.\n", __FUNCTION__, ret);
goto error;
} else {
ECALL_Log("%s: write ecall msd success and ret=%d.\n", __FUNCTION__, ret);
}
error:
if (ecallMsdFd) {
ret = close(ecallMsdFd);
if (ret < 0) {
ECALL_Log("%s: close ecall msd failed.\n", __FUNCTION__);
}
}
return ret;
}
int ecall_save_alAck(char *aLAckStr)
{
int ecallAlAckFd = 0;
int ecallAlAckLen = 0;
int ret = 0;
if (gEcallSaveAlAckCnt >= ECALL_SAVE_ALACK_COUNT_MAX) {
//remove save alack file
remove(ECALL_SAVE_ALACK_PATH);
gEcallSaveAlAckCnt = 0;
}
if (strlen(aLAckStr) > 0) {
ecallAlAckLen = strlen(aLAckStr);
ECALL_Log("%s: ecallMsd file path is %s and length is %d.\n", __FUNCTION__, ECALL_SAVE_ALACK_PATH, ecallAlAckLen);
} else {
ECALL_Log("%s: file path or ecallMsd is NULL.\n", __FUNCTION__);
return -1;
}
ecallAlAckFd = open (ECALL_SAVE_ALACK_PATH, O_RDWR|O_CREAT|O_APPEND, 0666);
if (ecallAlAckFd < 0) {
ECALL_Log("%s: open file failed and ecallMsdFd=%d.\n", __FUNCTION__, ecallAlAckFd);
return -1;
}
ret = write(ecallAlAckFd, aLAckStr, ecallAlAckLen);
if (ret < 0) {
ECALL_Log("%s: write ecall msd failed.\n", __FUNCTION__);
goto error;
} else if (ret < ecallAlAckLen) {
ECALL_Log("%s: wrote less the buffer size and ret=%d.\n", __FUNCTION__, ret);
goto error;
} else {
ECALL_Log("%s: write ecall msd success and ret=%d.\n", __FUNCTION__, ret);
gEcallSaveAlAckCnt++;
}
error:
if (ecallAlAckFd) {
ret = close(ecallAlAckFd);
if (ret < 0) {
ECALL_Log("%s: close ecall msd failed.\n", __FUNCTION__);
}
}
return ret;
}
char * ecall_get_timestamp(void)
{
struct timeval log_time;
char *timestr = NULL;
gettimeofday(&log_time, NULL);
timestr = ctime(&(log_time.tv_sec));
timestr[strlen(timestr) - 1] = '\0';
return timestr;
}
int ecall_ubus_sms_send(char* smsNum, char* txtData)
{
int ret = -1;
rilutilstrings param;
unsigned int id;
id = ecall_get_ubus_ril_id();
if (id == 0) {
ECALL_Log("lookup ril object failed\n");
return -1;
}
if (!txtData) return -2;
param.num = 2;
char* strs[2] = {NULL, NULL};
//strs[0] = smsNum;
strs[1] = txtData;
param.str = strs;
ecall_set_ecall_status(DAEMON_ECALL_SMS);
ECALL_Log("ecall_ubus_sms_send: smsNum %s, txtData %s.\n", smsNum, txtData);
blob_buf_init(&ecall_sms_b, 0);
ret = rilutil_makeRequestBlob(&ecall_sms_b, RIL_REQUEST_SEND_SMS, &param, sizeof(rilutilstrings));
ret = ubus_invoke(ecall_ctx, id, "ril_request", ecall_sms_b.head, ecall_rilrequest_cb, NULL, 0);
ECALL_Log("%s: ret=%d", __FUNCTION__, ret);
return ret;
}
int ecall_ubus_get_cmgr(int index)
{
int ret = -1;
int param = 0;
unsigned int id;
id = ecall_get_ubus_ril_id();
if (id == 0) {
ECALL_Log("lookup ril object failed\n");
return -1;
}
param = index;
ECALL_Log("ecall_ubus_get_cmgr: param %d.\n", param);
blob_buf_init(&ecall_cmgr_b, 0);
ret = rilutil_makeRequestBlob(&ecall_cmgr_b, RIL_REQUEST_GET_CMGR, &param, sizeof(rilutilstrings));
ret = ubus_invoke(ecall_ctx, id, "ril_request", ecall_cmgr_b.head, ecall_rilrequest_cb, NULL, 0);
ECALL_Log("%s: ret=%d", __FUNCTION__, ret);
return ret;
}
int ecall_sms_send_cfg_msd(void)
{
int ret = 0;
unsigned char *smsDataTmp = NULL;
if (ecall_daemon_get_mode() != 1) {
ECALL_Log("%s: sms send failed, ecall mode=%d.", __FUNCTION__, ecall_daemon_get_mode());
return -3;
}
//ecall_send_updateMsd_cmd();
smsDataTmp = ecall_sms_msdSMS(ecall_msd, gEcallMsdLen);
if (smsDataTmp == NULL)
{
ECALL_Log("%s: ecall_sms_msdSMS return smsData is NULL.", __FUNCTION__);
return -4;
}
/* use sms send msd */
if ((0 != strlen(smsMsdNumber)) && (0 != strlen(ecall_msd))) {
ret = ecall_ubus_sms_send(smsMsdNumber, (char *)smsDataTmp);
gEcallSmsMsdCnt++;
if (0 == ret) {
gSmsMsd = 1;
//ecallStartTimer(&ecall_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
//ecall_enable_timer(ecall_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
ECALL_Log("%s: sms send done.", __FUNCTION__);
} else {
ECALL_Log("%s: sms send fail.", __FUNCTION__);
ret = -1;
}
} else {
ECALL_Log("%s: no config sms number or msd is NULL.", __FUNCTION__);
ret = -2;
}
if (smsDataTmp) {
free(smsDataTmp);
smsDataTmp = NULL;
}
return ret;
}
int ecall_sms_send_saved_msd(void)
{
int ret = 0;
int smsMsdFd = -1;
int i = 0;
char smsMsdSavedPath[128] = {0};
char smsMsdSaved[300] = {0};
unsigned char *smsDataTmp = NULL;
ECALL_Log("%s: sms send saved msd, ecall mode=%d, gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMode, gEcallMsdSavedFlag);
if (ecall_daemon_get_mode() != 1) {
return -3;
}
if (gEcallMsdSavedFlag > 0) {
for (i = 0; i < gEcallMsdSavedFlag; i++) {
sprintf(smsMsdSavedPath, "./tmp/ecall_msd_saved_%d", i);
ECALL_Log("%s: smsMsdSavedPath=%s.", __FUNCTION__, smsMsdSavedPath);
if (access(smsMsdSavedPath, F_OK) != 0)
{
ECALL_Log("%s: %s file isn't exist.", __FUNCTION__, smsMsdSavedPath);
continue;
}
smsMsdFd = open(smsMsdSavedPath, O_RDONLY);
if (smsMsdFd < 0) {
ECALL_Log("%s: open sms msd saved file path failed.", __FUNCTION__);
ret = -1;
goto error;
} else {
memset(smsMsdSaved, 0x00, sizeof(smsMsdSaved));
ret = read(smsMsdFd, smsMsdSaved, sizeof(smsMsdSaved));
if (ret > 0) {
if (0 != strlen(smsMsdNumber)) {
smsDataTmp = ecall_sms_msdSMS(smsMsdSaved, strlen(smsMsdSaved));
if (smsDataTmp == NULL) {
ECALL_Log("%s: ecall_sms_msdSMS return smsData is NULL.", __FUNCTION__);
ret = -4;
goto error;
} else {
gSmsMsd = 1;
ecall_set_msdPath(smsMsdSavedPath);
ret = ecall_ubus_sms_send(smsMsdNumber, (char *)smsDataTmp);
//start msdSms retransmit timer
//ecallStopTimer(&ecall_saved_sms_retransmit_timer);
ecall_disable_timer(ecall_saved_sms_retransmit_timer);
//ecallStartTimer(&ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
ecall_enable_timer(ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
if (0 == ret) {
ECALL_Log("%s: sms send msd success and i=%d.", __FUNCTION__, i);
//remove(smsMsdSavedPath); //remove saved msd
ret = 0;
goto error;
} else {
ECALL_Log("%s: sms send msd failed and i=%d.", __FUNCTION__, i);
ret = -4;
goto error;
}
}
} else {
ECALL_Log("%s: sms number not config.", __FUNCTION__);
ret = -3;
goto error;
}
} else {
ECALL_Log("%s: read saved msd failed.", __FUNCTION__);
ret = -2;
goto error;
}
}
sleep(5); //sleep 1s after send sms
}
//gEcallMsdSavedFlag = 0;
}
error:
if (smsDataTmp) {
free(smsDataTmp);
smsDataTmp = NULL;
}
if (smsMsdFd > 0) {
close(smsMsdFd);
smsMsdFd = -1;
}
return ret;
}
int ecall_sms_send_smsFailed_msd(void)
{
int ret = 0;
int fd = 0;
char smsSendFailedMsd[300] = {0};
if (ecall_daemon_get_mode() != 1) {
ECALL_Log("%s: sms send failed, ecall mode=%d.", __FUNCTION__, ecall_daemon_get_mode());
return -5;
}
/* use sms send msd */
if (0 != strlen(smsMsdNumber)) {
fd = open("/tmp/ecall_msd_sms_send_failed", O_RDONLY);
if (fd < 0) {
ECALL_Log("%s: open file failed.", __FUNCTION__);
return -1;
} else {
ret = read(fd, smsSendFailedMsd, sizeof(smsSendFailedMsd));
if (ret <= 0) {
ECALL_Log("%s: read file failed.", __FUNCTION__);
return -2;
} else {
ret = ecall_ubus_sms_send(smsMsdNumber, smsSendFailedMsd);
if (0 != ret) {
ECALL_Log("%s: sms send failed.", __FUNCTION__);
ret = -3;
} else {
close(fd);
fd = -1;
remove("/ecall_msd_sms_send_failed"); //remove msd of sms send failed
}
}
}
} else {
ECALL_Log("%s: sms number not config.", __FUNCTION__);
return -4;
}
return ret;
}
void ecall_get_network_status(void)
{
unsigned int id;
id = ecall_get_ubus_ril_id();
if (id == 0) {
ECALL_Log("lookup ril object failed\n");
return;
}
blob_buf_init(&ecall_sms_b, 0);
rilutil_makeRequestBlob(&ecall_sms_b, RIL_REQUEST_GET_NW_DOMAIN, NULL, 0);
ubus_invoke(ecall_ctx, id, "ril_request", ecall_sms_b.head, ecall_rilrequest_cb, 0, 0);
ECALL_Log("%s: send ril request.", __FUNCTION__);
return;
}
void ecall_timer_init(void)
{
if (ecall_get_ecalltimer_initialized() == 0)
{
ecall_start_timer(&ecall_psap_callback_timer, SIG_ECALL_PSAP_CALLBACK, ecall_psap_callback_cb);
ecall_start_timer(&ecall_dial_cleardown_timer, SIG_ECALL_PSAP_CLEARDOWN, ecall_dial_cleardown_cb);
ecall_start_timer(&ecall_dial_setup_timer, SIG_ECALL_DIAL_SETUP, ecall_setup_cb);
ecall_start_timer(&ecall_redial_timer, SIG_ECALL_REDIAL_SETUP, ecall_redial_setup_cb);
ecall_start_timer(&ecall_wait_hl_ack_timer, SIG_ECALL_WAIT_HL_ACK, ecall_retransmit_msd_cb);
ecall_start_timer(&ecall_sms_retransmit_timer, SIG_ECALL_SMS_RETRANSMIT, ecall_smsMsd_retransmit_cb);
ecall_start_timer(&ecall_saved_sms_retransmit_timer, SIG_ECALL_SAVED_SMS_RETRANSMIT, ecall_saved_smsMsd_retransmit_cb);
ecall_start_timer(&ecall_deregister_network_timer, SIG_ECALL_DEREG_NETWORK, ecall_deregister_network_cb);
ecall_set_ecalltimer_initialized(1);
}
ECALL_Log("%s: leave", __FUNCTION__);
return;
}
int ecall_start_timer(TIMER_t *timerid, int signum, SIG_HANDLER timeout_handler)
{
struct sigevent sev;
struct sigaction sa;
int ret = 0;
memset(&sev, 0x00, sizeof(struct sigevent));
memset(&sa, 0x00, sizeof(struct sigaction));
sa.sa_flags = SA_SIGINFO;
sa.sa_sigaction = timeout_handler;
sigemptyset(&sa.sa_mask);
if(sigaction(signum, &sa, NULL) == -1)
ECALL_Log("sigaction");
sev.sigev_notify = SIGEV_SIGNAL;
sev.sigev_signo = signum;
sev.sigev_value.sival_ptr = timerid;
ret = timer_create(ECALL_CLCOK_ALARM, &sev, timerid);
ECALL_Log("ecall_start_timer return[%d], timerid[%x]", ret, *timerid);
return ret;
}
int ecall_enable_timer(TIMER_t timerid, long secs)
{
struct itimerspec its;
int ret = 0;
if (secs < 0)
return -1;
//how long to run the first time
its.it_value.tv_sec = secs;
its.it_value.tv_nsec = 0;
//after first time, how long to run next time
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
ret = timer_settime(timerid, 0, &its, NULL);
ECALL_Log("ecall_enable_timer return[%d], timerid[%x], secs[%ld]", ret, timerid, secs);
return ret;
}
int ecall_disable_timer(TIMER_t timerid)
{
struct itimerspec its;
its.it_value.tv_sec = 0;
its.it_value.tv_nsec = 0;
its.it_interval.tv_sec = 0;
its.it_interval.tv_nsec = 0;
ECALL_Log("%s: timerid[%x]", __FUNCTION__, timerid);
return timer_settime(timerid, 0, &its, NULL);
}
int ecall_delete_timer(TIMER_t timerid)
{
return timer_delete(timerid);
}
#if 0
void ecallStartTimer(struct uloop_timeout *timeout, int timeVal)
{
//UNUSED(timeout);
ECALL_Log("%s: timeVal=%lu.", __FUNCTION__, timeVal);
if (timeVal > 0)
uloop_timeout_set(timeout, timeVal);
return;
}
void ecallStopTimer(struct uloop_timeout *timeout)
{
//UNUSED(timeout);
if (timeout)
uloop_timeout_cancel(timeout);
return;
}
#endif
void ecall_sms_deReg(void)
{
char arr[64] = {0};
sprintf(arr, "AT*ECALLREG=0\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
static void ecall_get_ecalldata_t6_timer(void)
{
char arr[64] = {0};
sprintf(arr, "AT*ECALLDATA=5,2\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
static void ecall_get_ecalldata_t7_timer(void)
{
char arr[64] = {0};
sprintf(arr, "AT*ECALLDATA=5,3\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
void ecall_start_manual_ecall(void)
{
char arr[64] = {0};
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT*ECALLMSDGEN\r");
ecallSendAtCmd(arr, 1);
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT+CECALL=2\r");
ecallSendAtCmd(arr, 1);
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT*ECALLPUSH\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
void ecall_start_auto_ecall(void)
{
char arr[64] = {0};
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT*ECALLMSDGEN\r");
ecallSendAtCmd(arr, 1);
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT+CECALL=3\r");
ecallSendAtCmd(arr, 1);
memset(arr, 0, sizeof(arr));
sprintf(arr, "AT*ECALLPUSH\r");
ecallSendAtCmd(arr, 1);
ECALL_Log("%s: leave.", __FUNCTION__);
return;
}
int handle_ecallNetwork(void *data)
{
int err = 0;
rilutilstrings *resp = NULL;
if (data) {
resp = (rilutilstrings *)data;
if ((resp->num != 2) || (0 == memcmp(resp->str[0], "No Service", strlen("No Service")))) {
ECALL_Log("handle_ecallNetwork recv no service.\n");
return -1;
}
ECALL_Log("handle_ecallNetwork data->num=%d.\n", resp->num);
ECALL_Log("handle_ecallNetwork: resp->str[0]=%s.\n", resp->str[0]);
//ECALL_Log("handle_ecallNetwork: resp->str[1]=%s.\n", resp->str[1]);
if (0 == memcmp(resp->str[1], "CS_ONLY", strlen("CS_ONLY"))) {
err = 1;
} else if (0 == memcmp(resp->str[1], "PS_ONLY", strlen("PS_ONLY"))) {
err = 2;
} else if (0 == memcmp(resp->str[1], "CS_PS", strlen("CS_PS"))) {
err = 3;
} else if (0 == memcmp(resp->str[1], "CAMPED", strlen("CAMPED"))) {
err = 4;
//if (ecall_daemon_get_mode() == 0)
// err = 4;
//else if (ecall_daemon_get_mode() == 1)
// err = -2;
//else
// err = -3;
} else if (0 == memcmp(resp->str[1], "ECALLONLY", strlen("ECALLONLY"))) {
err = 5;
} else {
err = 0;
}
} else {
ECALL_Log("handle_ecallNetwork data is NULL.\n");
return -1;
}
return err;
}
int ecall_daemon_set_ecallSmsNum(char *ecallSmsNum)
{
if ((ecallSmsNum != NULL) && (strlen(ecallSmsNum) > 0))
{
memset(smsMsdNumber, '\0', sizeof(smsMsdNumber));
memcpy(smsMsdNumber, ecallSmsNum, strlen(ecallSmsNum));
ECALL_Log("%s: strlen(ecallSmsNum)=%d, ecallSmsNum=%s", __FUNCTION__, strlen(ecallSmsNum), ecallSmsNum);
return 0;
}
else
{
ECALL_Log("%s: recv ecall msd is invalid", __FUNCTION__);
return -1;
}
}
char * ecall_daemon_get_ecallSmsNum(void)
{
if (strlen(smsMsdNumber) > 0)
{
return smsMsdNumber;
}
else
{
return NULL;
}
}
int ecall_daemon_set_ecallMsd(char *ecallMsd)
{
if ((ecallMsd != NULL) && (strlen(ecallMsd) > 0))
{
gEcallMsdLen = strlen(ecallMsd);
memset(ecall_msd, '\0', sizeof(ecall_msd));
memcpy(ecall_msd, ecallMsd, gEcallMsdLen);
ECALL_Log("%s: gEcallMsdLen=%d, ecall_msd=%s", __FUNCTION__, gEcallMsdLen, ecall_msd);
if (1 == ecall_daemon_get_mode())
{
ecall_save_curMsd();
}
return 0;
}
else
{
ECALL_Log("%s: recv ecall msd is invalid", __FUNCTION__);
return -1;
}
}
char * ecall_daemon_get_ecallMsd(void)
{
if (strlen(ecall_msd) > 0)
{
return ecall_msd;
}
else
{
return NULL;
}
}
int ecall_daemon_send_ceer_cmd(void)
{
int ret = 0;
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT+CEER\r");
ret = ecallSendAtCmd(arr, 1);
ECALL_Log("%s: ret = %d.", __FUNCTION__, ret);
return ret;
}
void ecall_handle_ceer_response(const char *s)
{
int err, ceerVal = 0;
char *line = ecallStrdup((char *)s);
char *ceerStr = NULL;
char *pStart = NULL;
char data[3] = {0};
ECALL_Log("%s: %s", __FUNCTION__, s);
pStart = line;
err = at_tok_start(&line);
if(err < 0) {
goto error;
}
err = at_tok_nextstr(&line, &ceerStr);
if(err < 0) {
goto error;
}
ECALL_Log("%s: %s", __FUNCTION__, ceerStr);
data[0] = ceerStr[0];
if (data[0] >= '0' && data[0] <= '9')
ceerVal = data[0] - '0';
data[1] = ceerStr[1];
if (data[1] >= '0' && data[1] <= '9')
ceerVal = ceerVal * 10 + (data[1] - '0');
data[2] = ceerStr[2];
if (data[2] >= '0' && data[2] <= '9')
ceerVal = ceerVal * 10 + (data[2] - '0');
ECALL_Log("%s: ceerVal=%d", __FUNCTION__, ceerVal);
ecalL_daemon_set_ceerVal(ceerVal);
error:
if(pStart) {
free(pStart);
}
return;
}
int ecall_send_updateMsd_cmd(void)
{
int ret = 0;
char arr[64] = {0};
memset(arr, 0x00, sizeof(arr));
snprintf(arr, sizeof(arr), "AT*ECALLMSDGEN\r");
ret = ecallSendAtCmd(arr, 1);
ECALL_Log("%s: ret = %d.", __FUNCTION__, ret);
return ret;
}
void ecall_handle_msdGen_response(const char *s)
{
int err;
char *line = ecallStrdup((char *)s);
char *msd = NULL;
char *pStart = NULL;
ECALL_Log("%s: %s", __FUNCTION__,s);
pStart = line;
err = at_tok_start(&line);
if(err < 0) {
goto error;
}
err = at_tok_nextstr(&line, &msd);
if(err < 0) {
goto error;
}
if (msd != NULL)
{
ecall_daemon_set_ecallMsd(msd);
}
else
{
goto error;
}
ecall_daemon_str2hex(gEcallMsdLen, ecall_msd, ecall_msd_hex, sizeof(ecall_msd_hex)); // update to gMSDStr_HEX
//gEcallMsdHexLen = gEcallMsdLen/2;
//ecall_msd_saved("/tmp/ecall_msd_sms_send_failed", ecall_msd);
ECALL_Log("%s rcv: ecall msd %s, ecall msd length %d.", __FUNCTION__, ecall_msd, gEcallMsdLen);
error:
if(pStart) {
free(pStart);
}
return;
}
void ecall_daemon_get_ecallParams(char *respBuff, int buffLen)
{
int len = 0;
if (ecall_daemon_get_mode() == 1)
{
len += snprintf(respBuff + len, buffLen - len, "ERA mode, callback timer: %ds, ", ECALL_PSAP_CALLBACK_TMR_ERA);
len += snprintf(respBuff + len, buffLen - len, "dial setup timer: %ds, ", ECALL_DIAL_SETUP_TMR_ERA);
len += snprintf(respBuff + len, buffLen - len, "NAD deregister timer: %ds, ", ECALL_NAD_DEREGISTRATION_TMR_ERA);
len += snprintf(respBuff + len, buffLen - len, "cleardown timer: %ds, ", ECALL_DIAL_CLEARDOWN_TMR);
len += snprintf(respBuff + len, buffLen - len, "redial attempts count: %d, ", ECALL_AUTO_DIAL_ATTEMPTS);
len += snprintf(respBuff + len, buffLen - len, "redial wait timer: %ds, ", ECALL_REDIAL_TMR_ERA);
len += snprintf(respBuff + len, buffLen - len, "smsprocess: %d, ", ecall_daemon_get_smsProcess());
len += snprintf(respBuff + len, buffLen - len, "SMS resend timer: %ds, ", ECALL_SMS_SEND_MSD_TMR);
len += snprintf(respBuff + len, buffLen - len, "sms msd send count: %d.", ecall_get_smsMsd_send_count());
}
else
{
len += snprintf(respBuff + len, buffLen - len, "EU mode, callback timer: %ds, ", ECALL_PSAP_CALLBACK_TMR_EU);
len += snprintf(respBuff + len, buffLen - len, "dial setup timer: %ds, ", ECALL_DIAL_SETUP_TMR_EU);
len += snprintf(respBuff + len, buffLen - len, "NAD deregister timer: %ds, ", ECALL_NAD_DEREGISTRATION_TMR_EU);
len += snprintf(respBuff + len, buffLen - len, "cleardown timer: %ds.", ECALL_DIAL_CLEARDOWN_TMR);
}
return;
}
void ecallClearTimer(void)
{
//stop ecall dial setup timer
//ecallStopTimer(&ecall_dial_setup_timer);
ecall_disable_timer(ecall_dial_setup_timer);
//stop ecall clear down timer
//ecallStopTimer(&ecall_dial_cleardown_timer);
ecall_disable_timer(ecall_dial_cleardown_timer);
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
//ecallStopTimer(&ecall_psap_callback_timer);
ecall_disable_timer(ecall_psap_callback_timer);
//ecallStopTimer(&ecall_deregister_network_timer);
ecall_disable_timer(ecall_deregister_network_timer);
return;
}
void ecall_clear_status(void)
{
ecallClearTimer();
ecall_clear_allSavedMsd();
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
gEcallMsdSavedFlag = 0;
gEcallCallID = 0;
gPushVal = 0;
gSmsMsd = 0;
gEcallNW = 0;
gEcallType = 0;
gEcallCeer = 16;
gEcallRedial = 0;
gSimEcallOnly = 0;
gSimEcallActive = 0;
gEcallDialCnt = 0;
gEcallSmsMsdCnt = 0;
gCurrentHasCallSet = 0;
gEacllUserUpdatedMsd = 0;
}
int ecall_check_msd_hasMore(void)
{
int i = 0, count = 0;
char savedMsdPath[64] = {0};
for (i = 0; i < gEcallMsdSavedFlag; i++)
{
memset(savedMsdPath, 0x00, sizeof(savedMsdPath));
sprintf(savedMsdPath, "./tmp/ecall_msd_saved_%d", i);
if (access(savedMsdPath, F_OK) != 0)
{
ECALL_Log("%s: savedMsdPath=%s file isn't exist.", __FUNCTION__, savedMsdPath);
continue;
}
count++;
ECALL_Log("%s: savedMsdPath=%s file is exist, count=%d.", __FUNCTION__, savedMsdPath, count);
}
return count;
}
int ecall_set_msdPath(char *msdPath)
{
if ((msdPath != NULL) && (strlen(msdPath) > 0))
{
memset(gEcallMsdPath, 0x0, sizeof(gEcallMsdPath));
memcpy(gEcallMsdPath, msdPath, strlen(msdPath));
ECALL_Log("%s: gEcallMsdPath=%s", __FUNCTION__, gEcallMsdPath);
}
else
{
ECALL_Log("%s: msdPath=%s file is nivalid.", __FUNCTION__, msdPath);
return -1;
}
return 0;
}
char * ecall_get_msdPath(void)
{
if (strlen(gEcallMsdPath) > 0)
{
return gEcallMsdPath;
}
else
{
return NULL;
}
}
int ecall_clear_allSavedMsd(void)
{
int i = 0;
char savedMsdPath[64] = {0};
for (i = 0; i < 100; i++)
{
memset(savedMsdPath, 0x00, sizeof(savedMsdPath));
sprintf(savedMsdPath, "./tmp/ecall_msd_saved_%d", i);
if (access(savedMsdPath, F_OK) != 0)
{
//ECALL_Log("%s: savedMsdPath=%s file isn't exist.", __FUNCTION__, savedMsdPath);
continue;
}
else
{
ECALL_Log("%s: removed savedMsdPath=%s file.", __FUNCTION__, savedMsdPath);
remove(savedMsdPath);
}
}
gEcallMsdSavedFlag = 0;
return 0;
}
int ecall_clear_curMsd(void)
{
int ret = 0;
int i = 0, savedMsdFd = -1;
char savedMsd[300] = {0};
char savedMsdPath[64] = {0};
ECALL_Log("%s: gEcallMsdSavedFlag=%d, strlen(ecall_msd)=%d.", __FUNCTION__, gEcallMsdSavedFlag, strlen(ecall_msd));
if (strlen(ecall_msd) > 0)
{
if (gEcallMsdSavedFlag > 0)
{
for (i = 0; i < gEcallMsdSavedFlag; i++)
{
memset(savedMsdPath, 0x00, sizeof(savedMsdPath));
sprintf(savedMsdPath, "./tmp/ecall_msd_saved_%d", i);
if (access(savedMsdPath, F_OK) != 0)
{
ECALL_Log("%s: savedMsdPath=%s file isn't exist.", __FUNCTION__, savedMsdPath);
continue;
}
savedMsdFd = open(savedMsdPath, O_RDONLY);
if (savedMsdFd < 0)
{
ECALL_Log("%s: open sms msd saved file path failed.", __FUNCTION__);
continue;
}
else
{
memset(savedMsd, 0x00, sizeof(savedMsd));
ret = read(savedMsdFd, savedMsd, sizeof(savedMsd));
ECALL_Log("%s: read saved msd ret=%d, path=%s, msd=%s.", __FUNCTION__, ret, savedMsdPath, savedMsd);
if (ret > 0) {
if (0 == strncmp(savedMsd, ecall_msd, strlen(ecall_msd)))
{
remove(savedMsdPath);
ECALL_Log("%s: find current sent msd and remove him in file system.", __FUNCTION__);
ret = ecall_check_msd_hasMore();
if (ret == 0)
{
ECALL_Log("%s: file system not exist msd.", __FUNCTION__);
gEcallMsdSavedFlag = 0;
}
break;
}
}
else
{
ECALL_Log("%s: read saved msd failed.", __FUNCTION__);
if (savedMsdFd > 0)
{
close(savedMsdFd);
savedMsdFd = -1;
}
continue;
}
}
}
}
else
{
ECALL_Log("%s: gEcallMsdSavedFlag is invalid.", __FUNCTION__);
return -1;
}
}
else
{
ECALL_Log("%s: current msd is invalid.", __FUNCTION__);
return -2;
}
if (savedMsdFd > 0)
{
close(savedMsdFd);
savedMsdFd = -1;
}
return 0;
}
int ecall_save_curMsd(void)
{
int ret = 0;
int i = 0, savedMsdFd = -1;
char savedMsd[300] = {0};
char savedMsdPath[64] = {0};
ECALL_Log("%s: gEcallMsdSavedFlag=%d, strlen(ecall_msd)=%d.", __FUNCTION__, gEcallMsdSavedFlag, strlen(ecall_msd));
if (strlen(ecall_msd) != 0)
{
if (gEcallMsdSavedFlag > 100)
{
ECALL_Log("%s: msd saved failed and gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMsdSavedFlag);
return -2;
}
else if (gEcallMsdSavedFlag >= 0 && gEcallMsdSavedFlag <= 100)
{
for(i = 0; i < gEcallMsdSavedFlag; i++)
{
memset(savedMsdPath, 0x00, sizeof(savedMsdPath));
sprintf(savedMsdPath, "./tmp/ecall_msd_saved_%d", i);
if (access(savedMsdPath, F_OK) != 0)
{
ECALL_Log("%s: savedMsdPath=%s file isn't exist.", __FUNCTION__, savedMsdPath);
continue;
}
savedMsdFd = open(savedMsdPath, O_RDONLY);
if (savedMsdFd < 0)
{
ECALL_Log("%s: open sms msd saved file path failed.", __FUNCTION__);
continue;
}
else
{
memset(savedMsd, 0x00, sizeof(savedMsd));
ret = read(savedMsdFd, savedMsd, sizeof(savedMsd));
ECALL_Log("%s: read saved msd ret=%d, path=%s, msd=%s.", __FUNCTION__, ret, savedMsdPath, savedMsd);
if (ret > 0)
{
if (0 == strncmp(savedMsd, ecall_msd, strlen(ecall_msd)))
{
ECALL_Log("%s: find current sent msd has saved in file system.", __FUNCTION__);
goto exit;
}
else
{
ECALL_Log("%s: current sent msd isn't equal %s.", __FUNCTION__, savedMsdPath);
if (savedMsdFd > 0)
{
close(savedMsdFd);
savedMsdFd = -1;
}
continue;
}
}
else
{
ECALL_Log("%s: read saved msd failed.", __FUNCTION__);
if (savedMsdFd > 0)
{
close(savedMsdFd);
savedMsdFd = -1;
}
continue;
}
}
}
memset(savedMsdPath, 0x00, sizeof(savedMsdPath));
sprintf(savedMsdPath, "/tmp/ecall_msd_saved_%d", gEcallMsdSavedFlag);
ret = ecall_msd_saved(savedMsdPath, ecall_msd);
if (ret >= 0)
{
gEcallMsdSavedFlag++;
ECALL_Log("%s: ecall msd has saved and gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMsdSavedFlag);
}
else
{
ECALL_Log("%s: ecall msd saved failed and gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMsdSavedFlag);
return -1;
}
}
else
{
ECALL_Log("%s: %d is invalid.", __FUNCTION__, gEcallMsdSavedFlag);
return -3;
}
}
exit:
//ecall_reset_msd_timestamp();
if (savedMsdFd > 0)
{
close(savedMsdFd);
savedMsdFd = -1;
}
return 0;
}
void ecallHandleEcallType(const char *s)
{
int err;
char arr[64] = {0};
char *line = ecallStrdup((char *)s);
int ecallType = 0;
char *pStart = NULL;
ecall_get_network_status();
ecall_set_voice_data(4, 0, 1);
pStart = line;
ECALL_Log("%s: %s", __FUNCTION__,s);
err = at_tok_start(&line);
if(err < 0)
goto error;
err = at_tok_nextint(&line, &ecallType);
if(err < 0) {
goto error;
}
gEcallType = ecallType;
ECALL_Log("%s rcv: ecallType %d, ecall nw %d", __FUNCTION__, gEcallType, ecall_get_ecallNetwork());
ECALL_Log("%s: gCurrentHasCallSet %d, gEcallCallID %d.", __FUNCTION__, gCurrentHasCallSet, gEcallCallID);
if (gCurrentHasCallSet == 1) //has a call is setup,need to hangup when a new call want to setup
{
if (0 == gEcallCallID) //it is current has a normal call is processing, need hangup it.
{
ecall_dial_cleardown_nomal(); //hangup call
}
else //it is current has a ecall is processing, don't setup ecall again.
{
if (5 != ecallType)
{
if(pStart)
free(pStart);
return;
}
}
}
ecallClearTimer(); //clear ecall timer
if (gEcallType == 5) //for user hang up ecall
goto hang_up_ecall;
if (ecall_daemon_get_mode() == 1)
{
if (ecall_get_ecallNetwork() <= 0) //network not ready, msd need saved
{
#if 0
if (strlen(ecall_msd) != 0) {
if (gEcallMsdSavedFlag > 100) {
ECALL_Log("%s: msd saved failed and gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMsdSavedFlag);
} else {
char ecallMsdPath[128] = {0};
sprintf(ecallMsdPath, "/tmp/ecall_msd_saved_%d", gEcallMsdSavedFlag);
err = ecall_msd_saved(ecallMsdPath, ecall_msd);
if (err >= 0) {
gEcallMsdSavedFlag++;
ECALL_Log("%s: ecall network not ready, msd has saved and gEcallMsdSavedFlag=%d.", __FUNCTION__, gEcallMsdSavedFlag);
//ecallStopTimer(&ecall_saved_sms_retransmit_timer);
//ecallStartTimer(&ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
} else {
ECALL_Log("%s: ecall msd saved failed", __FUNCTION__);
}
}
}
ecall_reset_msd_timestamp();
#endif
ECALL_Log("%s: ecall network not ready, need saved msd and return", __FUNCTION__);
ecall_set_redial_flag(1);
return;
}
}
ecall_get_ecalldata_t6_timer(); //update T6 timer
ecall_get_ecalldata_t7_timer(); //update T7 timer
ecall_send_getEcallOnly_cmd(); // get ecallonly value
if (ecall_get_ecallOnlySimValid() == 0) { //only once get ecallonlysim value
ecall_send_getEcallOnlySim_cmd();
}
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO);
sprintf(arr, "AT+CECALLINSIDE=%d\r", ecallType);
ecallSendAtCmd((void*)arr, 1);
//stop dial setup timer
//ecallStopTimer(&ecall_dial_setup_timer);
ecall_disable_timer(ecall_dial_setup_timer);
//start dial setup timer
if (ecall_daemon_get_mode() == 0) { //EU
//ecallStartTimer(&ecall_dial_setup_timer, ECALL_DIAL_SETUP_TMR_EU);
ecall_enable_timer(ecall_dial_setup_timer, ECALL_DIAL_SETUP_TMR_EU);
} else {
//ecallStartTimer(&ecall_dial_setup_timer, ECALL_DIAL_SETUP_TMR_ERA);
ecall_enable_timer(ecall_dial_setup_timer, ECALL_DIAL_SETUP_TMR_ERA);
}
hang_up_ecall:
if (gEcallType == 5)
{
ecall_clear_status();
sprintf(arr, "AT+CECALLINSIDE=%d\r", ecallType);
ecallSendAtCmd((void*)arr, 1);
}
error:
if(pStart) {
free(pStart);
}
return;
}
int ecall_daemon_set_ecallTimer(char *timerName, int timerValue)
{
if ((timerName != NULL) && (strlen(timerName) > 0))
{
if ((0 == strncmp(timerName, "callback", strlen("callback"))) || (0 == strncmp(timerName, "CALLBACK", strlen("CALLBACK")))) {
if (0 == ecall_daemon_get_mode()) {
ECALL_PSAP_CALLBACK_TMR_EU = timerValue;
} else {
ECALL_PSAP_CALLBACK_TMR_ERA = timerValue;
}
} else if ((0 == strncmp(timerName, "cleardown", strlen("cleardown"))) || (0 == strncmp(timerName, "CLEARDOWN", strlen("CLEARDOWN")))) {
ECALL_DIAL_CLEARDOWN_TMR = timerValue;
} else if ((0 == strncmp(timerName, "dial", strlen("dial"))) || (0 == strncmp(timerName, "DIAL", strlen("DIAL")))) {
if (0 == ecall_daemon_get_mode()) {
ECALL_DIAL_SETUP_TMR_EU = timerValue;
} else {
ECALL_DIAL_SETUP_TMR_ERA = timerValue;
}
} else if ((0 == strcmp(timerName, "sms")) || (0 == strcmp(timerName, "SMS"))) {
ECALL_SMS_SEND_MSD_TMR = timerValue;
} else if ((0 == strncmp(timerName, "dereg", strlen("dereg"))) || (0 == strncmp(timerName, "DEREG", strlen("DEREG")))) {
if (ecall_daemon_get_mode() == 0) { //EU mode
ECALL_NAD_DEREGISTRATION_TMR_EU = timerValue;
}
else {
ECALL_NAD_DEREGISTRATION_TMR_ERA = timerValue;
}
} else if ((0 == strncmp(timerName, "redialcnt", strlen("redialcnt"))) || (0 == strncmp(timerName, "REDIALCNT", strlen("REDIALCNT")))) {
ECALL_AUTO_DIAL_ATTEMPTS = timerValue;
} else if ((0 == strncmp(timerName, "redialtmr", strlen("redialtmr"))) || (0 == strncmp(timerName, "REDIALTMR", strlen("REDIALTMR")))) {
if (ecall_daemon_get_mode() == 1) //ERA mode
ECALL_REDIAL_TMR_ERA = timerValue;
} else if ((0 == strcmp(timerName, "smsprocess")) || (0 == strcmp(timerName, "SMSPROCESS"))) {
ecall_daemon_set_smsProcess(timerValue);
} else if ((0 == strcmp(timerName, "smsmsdcnt")) || (0 == strcmp(timerName, "SMSMSDCNT"))) {
ecall_set_smsMsd_send_count(timerValue);
} else if ((0 == strcmp(timerName, "hangup_redial_tmr")) || (0 == strcmp(timerName, "HANGUP_REDIAL_TMR"))) {
ecall_set_ecall_hangup_redial_timer(timerValue);
} else {
ECALL_Log("%s rcv ecall timer name is invalid.", __FUNCTION__);
return -1;
}
ECALL_Log("%s: timerValue=%d, timerName=%s", __FUNCTION__, timerValue, timerName);
return 0;
}
else
{
ECALL_Log("%s: set ecall timer name is invalid", __FUNCTION__);
return -2;
}
}
int ecall_daemon_get_ecallTimerValue(char *timerName)
{
int timerValue = 0;
if ((timerName != NULL) && (strlen(timerName) > 0))
{
if ((0 == strncmp(timerName, "callback", strlen("callback"))) || (0 == strncmp(timerName, "CALLBACK", strlen("CALLBACK"))))
{
if (0 == ecall_daemon_get_mode()) {
timerValue = ECALL_PSAP_CALLBACK_TMR_EU;
} else {
timerValue = ECALL_PSAP_CALLBACK_TMR_ERA;
}
}
else if ((0 == strncmp(timerName, "cleardown", strlen("cleardown"))) || (0 == strncmp(timerName, "CLEARDOWN", strlen("CLEARDOWN"))))
{
timerValue = ECALL_DIAL_CLEARDOWN_TMR;
}
else if ((0 == strncmp(timerName, "dial", strlen("dial"))) || (0 == strncmp(timerName, "DIAL", strlen("DIAL"))))
{
if (0 == ecall_daemon_get_mode()) {
timerValue = ECALL_DIAL_SETUP_TMR_EU;
} else {
timerValue = ECALL_DIAL_SETUP_TMR_ERA;
}
}
else if ((0 == strcmp(timerName, "sms")) || (0 == strcmp(timerName, "SMS")))
{
timerValue = ECALL_SMS_SEND_MSD_TMR;
}
else if ((0 == strncmp(timerName, "dereg", strlen("dereg"))) || (0 == strncmp(timerName, "DEREG", strlen("DEREG")))) {
if (ecall_daemon_get_mode() == 0) { //EU mode
timerValue = ECALL_NAD_DEREGISTRATION_TMR_EU;
}
else {
timerValue = ECALL_NAD_DEREGISTRATION_TMR_ERA;
}
}
else if ((0 == strncmp(timerName, "redialcnt", strlen("redialcnt"))) || (0 == strncmp(timerName, "REDIALCNT", strlen("REDIALCNT"))))
{
timerValue = ECALL_AUTO_DIAL_ATTEMPTS;
}
else if ((0 == strncmp(timerName, "redialtmr", strlen("redialtmr"))) || (0 == strncmp(timerName, "REDIALTMR", strlen("REDIALTMR"))))
{
timerValue = ECALL_REDIAL_TMR_ERA;
}
else if ((0 == strcmp(timerName, "smsprocess")) || (0 == strcmp(timerName, "SMSPROCESS")))
{
timerValue = ecall_daemon_get_smsProcess();
}
else if ((0 == strcmp(timerName, "smsmsdcnt")) || (0 == strcmp(timerName, "SMSMSDCNT")))
{
timerValue = ecall_get_smsMsd_send_count();
}
else if ((0 == strcmp(timerName, "hangup_redial_tmr")) || (0 == strcmp(timerName, "HANGUP_REDIAL_TMR")))
{
timerValue = ecall_get_ecall_hangup_redial_timer();
}
else
{
ECALL_Log("%s rcv ecall timer name is invalid.", __FUNCTION__);
return -1;
}
ECALL_Log("%s get ecall timerName[%s], timerValue[%d].", __FUNCTION__, timerName, timerValue);
return timerValue;
}
else
{
ECALL_Log("%s get ecall timer value is invalid.", __FUNCTION__);
return -2;
}
}
int ecall_daemon_handle_setMode(char *ecallMode)
{
if ((ecallMode != NULL) && (strlen(ecallMode) > 0))
{
if ((0 == strncmp(ecallMode, "EU", strlen("EU"))) || (0 == strncmp(ecallMode, "eu", strlen("eu"))))
{
ecall_daemon_set_mode(0);
}
else if ((0 == strncmp(ecallMode, "ERA", strlen("ERA"))) || (0 == strncmp(ecallMode, "era", strlen("era"))))
{
ecall_daemon_set_mode(1);
}
else
{
ecall_daemon_set_mode(0);
}
return 0;
}
else
{
ECALL_Log("%s: recv ecallMode[%s] is invalid", __FUNCTION__, ecallMode);
return -1;
}
}
void ecallHandleSmsMsdResp(void)
{
char *msdPath = NULL;
int ret = 0;
ECALL_Log("%s: gEcallMode %d, gSmsMsd %d, gEcallStatus %d, gEcallDialCnt %d.", __FUNCTION__, gEcallMode, gSmsMsd, gEcallStatus, gEcallDialCnt);
if (ecall_daemon_get_mode() == 1 && gSmsMsd == 1)
{
gEcallDialCnt = 0;
ecall_set_redial_flag(0);
msdPath = ecall_get_msdPath();
if (msdPath != NULL)
{
if (access(msdPath, F_OK) == 0)
{
remove(msdPath);
ECALL_Log("%s: msdPath=%s is removed.", __FUNCTION__, msdPath);
}
else
{
ECALL_Log("%s: msdPath isn't exist.", __FUNCTION__);
}
ret = ecall_check_msd_hasMore();
if (ret == 0)
{
gEcallMsdSavedFlag = 0;
//ecallStopTimer(&ecall_saved_sms_retransmit_timer);
ecall_disable_timer(ecall_saved_sms_retransmit_timer);
}
else
{
//ecallStopTimer(&ecall_saved_sms_retransmit_timer);
ecall_disable_timer(ecall_saved_sms_retransmit_timer);
//ecallStartTimer(&ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
ecall_enable_timer(ecall_saved_sms_retransmit_timer, ECALL_SMS_SEND_MSD_TMR);
}
gSmsMsd = 0;
}
else
//if (ecall_get_ecall_status() == DAEMON_ECALL_SMS)
{
ECALL_Log("%s: config msd sms is send success.", __FUNCTION__);
ecall_clear_curMsd();
//ecallStopTimer(&ecall_sms_retransmit_timer);
ecall_disable_timer(ecall_sms_retransmit_timer);
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
gSmsMsd = 0;
gEcallSmsMsdCnt = 0;
}
}
return;
}
int ecall_daemon_send_msdSms(int smsSendMsdFlag)
{
int ret = 0;
ECALL_Log("%s: smsSendMsdFlag=%d", __FUNCTION__, smsSendMsdFlag);
if (0 == smsSendMsdFlag) {
ret = ecall_sms_send_cfg_msd();
} else if (1 == smsSendMsdFlag) {
ret = ecall_sms_send_saved_msd();
} else if (2 == smsSendMsdFlag) {
ret = ecall_sms_send_smsFailed_msd();
} else {
ECALL_Log("%s recv smsFlag is invalid.", __FUNCTION__);
ret = -1;
}
return ret;
}
int ecall_daemon_set_ecallTestNum(char *ecallTestNum, char *ecallReconfigNum)
{
if ((ecallTestNum != NULL) && (strlen(ecallTestNum) > 0))
{
memset(testNumber, '\0', sizeof(testNumber));
memcpy(testNumber, ecallTestNum, strlen(ecallTestNum));
ECALL_Log("%s: testNumber=%s", __FUNCTION__, testNumber);
}
if ((ecallReconfigNum != NULL) && (strlen(ecallReconfigNum) > 0))
{
memset(reconfigureNumber, '\0', sizeof(reconfigureNumber));
memcpy(reconfigureNumber, ecallReconfigNum, strlen(ecallReconfigNum));
ECALL_Log("%s: reconfigureNumber=%s", __FUNCTION__, reconfigureNumber);
}
return 0;
}
void ecallHandleClcc(const char *s)
{
char *callMumber;
int direction=0;
RIL_Call *ril_call_status;
RIL_CallState callStat = 0;
int callID = 0;
if (strlen(nGMtEcallTestNumUrl) == 0) {
memset(nGMtEcallTestNumUrl, 0x00, sizeof(nGMtEcallTestNumUrl));
strncpy(nGMtEcallTestNumUrl, NG_ECALL_MT_DEFAULT_TEST_NUMBER_URL, sizeof(nGMtEcallTestNumUrl)-1);
}
if (strlen(nGMoEcallTestNumUrl) == 0) {
memset(nGMoEcallTestNumUrl, 0x00, sizeof(nGMoEcallTestNumUrl));
strncpy(nGMoEcallTestNumUrl, NG_ECALL_MO_DEFAULT_TEST_NUMBER_URL, sizeof(nGMoEcallTestNumUrl)-1);
}
ril_call_status = (RIL_Call*)s;
if(ril_call_status->number == NULL)
{
ECALL_Log("%s: received call number is NULL", __FUNCTION__);
return;
}
ECALL_Log("%s: %s", __FUNCTION__,ril_call_status->number);
callMumber = ril_call_status->number;
direction = ril_call_status->isMT;
callStat = ril_call_status->state;
callID = ril_call_status->index;
ECALL_Log("%s: callStat %d, callMumber %s, direction %d, callID %d", __FUNCTION__, callStat, callMumber, direction, callID);
ECALL_Log("%s: testNumber=%s, reconfigureNumber=%s", __FUNCTION__, testNumber, reconfigureNumber);
ECALL_Log("%s: nGMtEcallTestNumUrl=%s, nGMoEcallTestNumUrl=%s", __FUNCTION__, nGMtEcallTestNumUrl, nGMoEcallTestNumUrl);
if (ecall_current_is_ecallOnly_mode() == 1)
{
ECALL_Log("%s: ecall only mode, don't care ecall number!", __FUNCTION__);
}
else if(strcmp(callMumber, "112") && strcmp(callMumber, "119") && (strstr(callMumber, testNumber) == NULL) && (strstr(callMumber, reconfigureNumber) == NULL))
{
if ((strstr(callMumber, nGMoEcallTestNumUrl) == NULL) && (strstr(callMumber, nGMtEcallTestNumUrl) == NULL)) {
if ((!direction) && (0 == callStat)) //has a normal call is answer
gCurrentHasCallSet = 1;
ECALL_Log("%s: it's not a ecall, just return", __FUNCTION__);
return;
}
}
else
{
ECALL_Log("%s: callMumber %s, testNumber %s, reconfigureNumber %s", __FUNCTION__, callMumber, testNumber, reconfigureNumber);
}
ECALL_WAIT_T6_T7_TMR = ECALL_WAIT_HL_ACK_TMR + ECALL_WAIT_LL_ACK_TMR; //update T6 + T7 timer
ECALL_Log("%s: T6 + T7 timer %d", __FUNCTION__,ECALL_WAIT_T6_T7_TMR);
if(!direction) { //MO call
//rcord current call is a ecall
gEcallCallID = callID;
if (0 == callStat) {
ecall_set_redial_flag(0);
if ((ecall_get_ecall_status() == DAEMON_ECALL_MO) || (ecall_get_ecall_status() == DAEMON_ECALL_MO_MSD_SENT)) {
//stop dial setup timer
//ecallStopTimer(&ecall_dial_setup_timer);
ecall_disable_timer(ecall_dial_setup_timer);
if (ecall_get_ecall_status() == DAEMON_ECALL_MO) {
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO_SETUP);
}
//start ecall clear down timer
//ecallStartTimer(&ecall_dial_cleardown_timer, ECALL_DIAL_CLEARDOWN_TMR);
ecall_enable_timer(ecall_dial_cleardown_timer, ECALL_DIAL_CLEARDOWN_TMR);
}
}else if (2 == callStat) {
if (ecall_get_ecall_status() == DAEMON_ECALL_MO) {
}
} else {
ECALL_Log("%s: callMumber %s, callStat %d", __FUNCTION__,callMumber, callStat);
}
} else { //MT Call
if (0 == callStat) { /* only MT call status is active to send voice data */
ECALL_Log("%s: callMumber %s, call audio API", __FUNCTION__,callMumber);
ecall_ubusSendEcallCmd(0, 1, 0, NULL); //TEL_AT_CMD_ATP_0
ecall_set_voice_data(4, 0, 1);
}
}
if (ecall_get_ecall_redial_cnt() == ECALL_AUTO_DIAL_ATTEMPTS) //ecall redial count is ECALL_AUTO_DIAL_ATTEMPTS, but new MO/MT ecall has setup successful, so redialcnt need to reset;
{
ecall_reset_ecall_redial_cnt();
}
return;
}
static char hexToNum(char ch)
{
ch = toupper(ch);
if (isdigit(ch)) {
ch -= '0';
} else if (isxdigit(ch)) {
ch -= 'A';
ch += 0x0A;
}
return ch;
}
void ecall_daemon_str2hex(int src_len, char *psrc, char *pdest, int dest_len)
{
int i = 0;
char highpart =0;
char lowpart = 0;
char result = 0;
ECALL_Log("%s: src_len %d, dest_len %d", __func__,src_len, dest_len);
if((psrc == NULL) || (pdest == NULL))
return;
if(src_len > dest_len<<1)
return;
for (i = 0; i < src_len; i++)
{
highpart = hexToNum(*psrc++);
//ECALL_Log(str_to_Hex5, "%s: result[%d]: highpart %X\n", __FUNCTION__, i>>1, highpart);
lowpart = hexToNum(*psrc++);
//ECALL_Log(str_to_Hex6, "%s: result[%d]: lowpart %X\n", __FUNCTION__, i>>1, highpart);
result = (highpart<<4) | lowpart;
*pdest++ = result;
i++;
//ECALL_Log(str_to_Hex7, "%s: result[%d]: %X, highpart %d, lowpart %d\n", __FUNCTION__, i>>1, result, highpart, lowpart);
}
return;
}
void ecallHandleSmsReceived(const char *s)
{
char *line = ecallStrdup((char *)s);
char *data = NULL;
char *pStart = NULL;
char hexData[128] = {0};
ECALL_Log("%s: %s, msg len=%d.", __FUNCTION__, s, strlen(s));
if (line)
{
data = line;
pStart = line;
}
ecall_daemon_str2hex(strlen(data), data, hexData, sizeof(hexData));
#if 0
hexDataLen = strlen(data)/2;
if ( hexDataLen > 0 )
{
for (i = 0; i < hexDataLen; i++)
{
ECALL_Log(ecallHandleSmsReceived1, "%s: hexData[%d]=%x", __FUNCTION__, i, hexData[i]);
}
}
#endif
ecall_sms_parse_pdu(hexData);
if(pStart)
free(pStart);
}
void ecallHandleSmsIdxRecvExt(void *data)
{
int err = 0;
int *resp = NULL;
int index = 0;
if (data) {
resp = (int *)data;
ECALL_Log("%s: value[0]=%d, value[1]=%d", __FUNCTION__, resp[0], resp[1]);
index = resp[1];
ECALL_Log("%s: index=%d", __FUNCTION__, index);
if (index >= 0) {
err = ecall_ubus_get_cmgr(index);
ECALL_Log("%s: err=%d", __FUNCTION__, err);
}
}
return;
}
void ecallHandleNetworkChanged(void *data)
{
UNUSED(data);
ECALL_Log("%s: enter!!!", __FUNCTION__);
ecall_get_network_status();
if (0 == ecall_get_redial_flag() || ecall_get_ecallNetwork() <= 0)
{
ECALL_Log("%s: network flag is 0 or network not ready, just return!!!", __FUNCTION__);
return;
}
ECALL_Log("%s: gEcallNW=%d, gEcallMsdSavedFlag=%d, gEcallRedial=%d.", __FUNCTION__, gEcallNW, gEcallMsdSavedFlag, gEcallRedial);
if ((ecall_daemon_get_mode() == 1))
{
if ((gEcallMsdSavedFlag > 0) && (gEcallDialCnt == ECALL_AUTO_DIAL_ATTEMPTS))
{
ecall_sms_send_saved_msd();
if (ecall_get_ecall_status() == DAEMON_ECALL_SMS)
{
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
}
}
if ((ecall_get_redial_flag()) == 1 && (gEcallDialCnt < ECALL_AUTO_DIAL_ATTEMPTS))
ecall_redial_only();
}
return;
}
void ecallHandleSmsIdxRecvONSim(void *data)
{
int err = 0;
int *resp = NULL;
int index = 0;
if (data) {
resp = (int *)data;
ECALL_Log("%s: index=%d", __FUNCTION__, *resp);
index = *resp;
ECALL_Log("%s: index=%d", __FUNCTION__, index);
if (index >= 0) {
err = ecall_ubus_get_cmgr(index);
ECALL_Log("%s: err=%d", __FUNCTION__, err);
}
}
return;
}
void ecallHandleEcalldata(const char *s)
{
int urc_id = -1, urc_data = -1, timer = 0;
int *arr_p;
arr_p = (int*)s;
urc_id = *arr_p;
urc_data = *((int *)(arr_p + 1));
timer = *((int *)(arr_p + 2));
char alAckStr[128] = {0};
char *timeStr = NULL;
ECALL_Log("%s: urc_id %d, urc_data %d, timer %d", __FUNCTION__, urc_id, urc_data, timer);
if (urc_id == 5) {
if (urc_data == 2) { //get T6 timer 1 frame = 20ms
ECALL_WAIT_HL_ACK_TMR = timer * 20;
} else if (urc_data == 3) {
ECALL_WAIT_LL_ACK_TMR = timer * 20;
} else {
ECALL_Log("%s: recv no used urc data.", __FUNCTION__);
return;
}
} else if (urc_id == 24 || urc_id == 25) { //T5 or T6 expiry
//stop ecall_wait_hl_ack_timer and send msd via sms when ecall mode is ERA
//stop wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
ecall_retransmit_msd_cb(0, NULL, NULL);
} else if (urc_id == 26) { //T7 expiry
//stop ecall_wait_hl_ack_timer and send msd via sms when ecall mode is ERA
//stop wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
if (gEacllUserUpdatedMsd == 0 || gEacllUserUpdatedMsd == 2) { //gEacllUserUpdatedMsd == 1 is user don't update msd, so send old msd via sms is not must.
ecall_retransmit_msd_cb(0, NULL, NULL);
}
gEacllUserUpdatedMsd = 0;
} else if (urc_id == 9) { //pull mode, user need update msd
gEacllUserUpdatedMsd = 1;
} else if (urc_id == 21) { //user has updated msd
if (gEacllUserUpdatedMsd == 1) //gEacllUserUpdatedMsd value update when pull mode and received urcid=9
gEacllUserUpdatedMsd = 2;
} else if(urc_id == 17) { //HL-ACK received
//stop wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO_MSD_SENT);
if (1 == ecall_daemon_get_mode())
{
//ecall_clear_curMsd();
ecall_clear_allSavedMsd();
}
gEcallDialCnt = 0;
ecall_daemon_set_ecallPush(0);
gEacllUserUpdatedMsd = 0;
}
else if(urc_id == 12) { //SEND MSD request received
//start wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
//ecallStartTimer(&ecall_wait_hl_ack_timer, ECALL_WAIT_T6_T7_TMR);
ecall_enable_timer(ecall_wait_hl_ack_timer, ECALL_WAIT_T6_T7_TMR);
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO_MSD);
} else if (urc_id == 0) {
ecall_daemon_set_ecallPush(0);
if ((urc_data & 0x02) == 0) { //receice eIM completes sending MSD
//stop wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO_MSD_SENT);
if (1 == ecall_daemon_get_mode())
{
//ecall_clear_curMsd();
ecall_clear_allSavedMsd();
}
gEcallDialCnt = 0;
gEacllUserUpdatedMsd = 0;
//save received al-ack and it's timestamp
timeStr = ecall_get_timestamp();
if (strlen(timeStr) > 0) {
memset(alAckStr, 0x00, sizeof(alAckStr));
snprintf(alAckStr, sizeof(alAckStr), "IVS received AL-ACK on %s\n", timeStr);
if (strlen(alAckStr) > 0) {
ecall_save_alAck(alAckStr);
}
} else {
ECALL_Log("%s: ecall get time string fail.", __FUNCTION__);
}
} else if ((urc_data & 0x02) == 2) { //Clear down received
if (ecall_get_ecall_status() <= DAEMON_ECALL_MO_MSD_SENT) { //normol clear down
//stop wait HL_ACK timer
//ecallStopTimer(&ecall_wait_hl_ack_timer);
ecall_disable_timer(ecall_wait_hl_ack_timer);
//stop clear down timer
//ecallStopTimer(&ecall_dial_cleardown_timer);
ecall_disable_timer(ecall_dial_cleardown_timer);
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_MO_MSD_SENT);
//hang up call
ecall_hang_up();
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
//set psap callback timer
if (ecall_daemon_get_mode() == 0) { //EU Mode
ecall_start_auto_answer(ECALL_PSAP_CALLBACK_TMR_EU);
} else {
ecall_start_auto_answer(ECALL_PSAP_CALLBACK_TMR_ERA);
}
} else {
ECALL_Log("%s: error1 urc_id %d, urc_data %0x, ecall status %d.", __FUNCTION__, urc_id, urc_data, gEcallStatus);
}
} else {
ECALL_Log("%s: error2 urc_id %d, urc_data %0x.", __FUNCTION__, urc_id, urc_data);
}
} else {
ECALL_Log("%s: urc_id %d unused.", __FUNCTION__, urc_id);
}
return;
}
void ecallHandlePsapHangUp(void)
{
ECALL_Log("%s: recv 'NO CARRIER'", __FUNCTION__);
ECALL_Log("%s: gCurrentHasCallSet[%d], gEcallCallID[%d], gEcallMode[%d], gEcallType[%d]", __FUNCTION__, gCurrentHasCallSet, gEcallCallID, gEcallMode, gEcallType);
ECALL_Log("%s: ecall_get_ecall_status[%d]", __FUNCTION__, ecall_get_ecall_status());
ECALL_Log("%s: gEcallDialCnt[%d]", __FUNCTION__, gEcallDialCnt);
if (gEcallType == 5) //for user hang up ecall
{
ecall_clear_status();
return;
}
if (ecall_daemon_send_ceer_cmd() != 0)
{
ECALL_Log("%s: get ceer falied", __FUNCTION__);
return;
}
ECALL_Log("%s: gEcallCeer[%d]", __FUNCTION__, ecall_daemon_get_ceerVal());
gCurrentHasCallSet = 0;
if(gEcallCallID != 0) //current call is ecall
{
gEcallCallID = 0;
if (ecall_daemon_get_ceerVal() != 16) //gEcallNormalHangup=0 is not user use AT+CECALL=5 or psap send clear down command
{
//when ecall hangup and ivs not received AL-ACK and msd is transmitting, ivs need redial and send msd
if (ecall_get_ecall_status() == DAEMON_ECALL_MO)
{
//clear ecall timer
ecallClearTimer();
if (ecall_daemon_get_mode() == 1)
{
if (gEcallDialCnt < ECALL_AUTO_DIAL_ATTEMPTS)
{
//ecall_redial_and_send_msd();
//gEcallDialCnt++;
//ecallStartTimer(&ecall_dial_setup_timer, ECALL_REDIAL_TMR_ERA);
ecall_enable_timer(ecall_redial_timer, ECALL_REDIAL_TMR_ERA);
}
else
{
if (gEcallMsdSavedFlag > 0)
{
ecall_sms_send_saved_msd();
}
}
}
else //EU mode, redial timers has confused
{
//to be do
}
}
else if (ecall_get_ecall_status() == DAEMON_ECALL_MO_SETUP)
{
//clear ecall timer
ecallClearTimer();
ecall_redial_and_send_msd();
ECALL_Log("%s: ecall_redial_and_send_msd", __FUNCTION__);
}
else if (ecall_get_ecall_status() == DAEMON_ECALL_MO_MSD)
{
//clear ecall timer
ecallClearTimer();
ecall_redial_and_send_msd();
ECALL_Log("%s: ecall_redial_and_send_msd", __FUNCTION__);
}
else if (ecall_get_ecall_status() == DAEMON_ECALL_MO_MSD_SENT)
{
//clear ecall timer
ecallClearTimer();
ecall_set_redial_flag(1);
ECALL_Log("%s: ecall should redial only", __FUNCTION__);
}
else
{
ECALL_Log("%s: recv normal disconnet the ivs", __FUNCTION__);
}
//return; //ecall daemon need set auto answer when abnormal call disconnect.
}
else
{
//ecallStopTimer(&ecall_dial_setup_timer);
ecall_disable_timer(ecall_dial_setup_timer);
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
}
}
else
{
ECALL_Log("%s: current call isn't a ecall.", __FUNCTION__);
return;
}
//set auto answer and start psap callback timer
if (ecall_daemon_get_mode() == 0) { //EU mode
ecall_start_auto_answer(ECALL_PSAP_CALLBACK_TMR_EU);
} else if (ecall_daemon_get_mode() == 1) {
ecall_start_auto_answer(ECALL_PSAP_CALLBACK_TMR_ERA);
} else {
ECALL_Log("%s: set psap callback timer failed, gEcallMode=%d.", __FUNCTION__, ecall_daemon_get_mode());
}
if (ecall_send_getEcallOnly_cmd() == 0)
{
if (ecall_current_is_ecallOnly_mode() == 1)
{
//ecallStopTimer(&ecall_deregister_network_timer);
ecall_disable_timer(ecall_deregister_network_timer);
if (ecall_daemon_get_mode() == 0) { //EU mode
//ecallStartTimer(&ecall_deregister_network_timer, ECALL_NAD_DEREGISTRATION_TMR_EU);
ecall_enable_timer(ecall_deregister_network_timer, ECALL_NAD_DEREGISTRATION_TMR_EU);
}
else {
//ecallStartTimer(&ecall_deregister_network_timer, ECALL_NAD_DEREGISTRATION_TMR_ERA);
ecall_enable_timer(ecall_deregister_network_timer, ECALL_NAD_DEREGISTRATION_TMR_ERA);
}
}
}
//set ecall status
ecall_set_ecall_status(DAEMON_ECALL_IDLE);
return;
}
int ecall_handle_ril_ind(struct ubus_context *ctx, unsigned int rilid, unsigned int rilerror, char *data, int data_len)
{
UNUSED(data_len);
UNUSED(ctx);
int ret = 0;
if (rilerror)
return -1;
ECALL_Log("ecall_handle_ril_ind: ecall status: %d, ecall mode: %d, ecall type: %d, ecall nw: %d", gEcallStatus, gEcallMode, gEcallType, gEcallNW);
switch(rilid)
{
case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED_EXT: //+clcc
ecallHandleClcc(data);
break;
case RIL_UNSOL_ECALLDATA: //+ecalldata
ecallHandleEcalldata(data);
break;
case RIL_UNSOL_CALL_NO_CARRIER_EXT: //PSAP hang up ecall
ecallHandlePsapHangUp();
break;
case RIL_UNSOL_ECALL_TYPE:
ecallHandleEcallType(data);
break;
case RIL_UNSOL_RESPONSE_SMS_SENT:
//ecallHandleSmsMsdResp();
break;
case RIL_UNSOL_RESPONSE_NEW_SMS: /* +CMT */
if (ecall_daemon_get_smsProcess() == 1 && ecall_daemon_get_mode() == 1)
ecallHandleSmsReceived(data);
break;
case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: /* +CMTI */
if (ecall_daemon_get_smsProcess() == 1 && ecall_daemon_get_mode() == 1)
ecallHandleSmsIdxRecvONSim(data);
break;
case RIL_UNSOL_NEW_SMS_EXT: /* +CMTI */
if (ecall_daemon_get_smsProcess() == 1 && ecall_daemon_get_mode() == 1)
ecallHandleSmsIdxRecvExt(data);
break;
case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: /* network is changed */
ecallHandleNetworkChanged(data);
break;
default:
break;
}
return ret;
}
#endif