/****************************************************************************** | |
*(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, ¶m, 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, ¶m, 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 |