blob: cc85beef5750524399f17554f49d5b0a6ec5c3f5 [file] [log] [blame]
//////////////////////////////////////////////////////////////////////
// INCLUDE FILES FOR MODULE
//////////////////////////////////////////////////////////////////////
#include "cm_service.h"
#include "dialer_task.h"
#include "ml_utils.h"
#include <time.h>
#ifdef CONFIG_CM_URSP
#include "ursp.h"
#endif
#include "cm_tft.h"
#include <math.h>
#include <fcntl.h>
//////////////////////////////////////////////////////////////////////
// local Prototypes
//////////////////////////////////////////////////////////////////////
#if 0
static void tftinfo_parse(struct blob_attr *msg, PacketFilterInfo * tftinfo);
#endif
int CreatePdp_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
static int GetLinkContext_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
static int SetImageType_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
static int GetImageType_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
static int get_wan_configs(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int connection_reload(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int get_apn_info(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int configs_handler(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int connection_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int set_auto_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int get_auto_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg);
int cm_start_thread();
int is_pdp_auto_mode(Mnc_Apn * work_apn, char *apn_type);
void cm_log_test(void);
void *redial_task(void *argv);
void complete_create_pdp_async_cb(struct ubus_request *req, int ret);
void complete_destroy_pdp_async_cb(struct ubus_request *req, int ret);
void accept_cl_receive_cb(struct uloop_fd *u, unsigned int events);
void cm_query_enginfo_timeout_cb(struct uloop_timeout *timeout);
void cm_process_cgdcont_msg(fifo_msg_cgdcont_s *msg);
void cm_process_auth_msg(fifo_msg_auth_s *msg);
void cm_process_act_msg(fifo_msg_act_s *msg);
void cm_process_confex_msg(fifo_msg_confex_s *msg);
void fifo_read_cb(struct uloop_fd *u, unsigned int events);
int cm_fifo_init(void);
#ifdef CONFIG_CM_P701
static int cm_get_imsi_mccmnc(char *mccmnc);
static int cm_get_zroam_list_ril();
#endif
void send_zgdcont_info_2atcmd(Apn_Info *apn_info);
void cm_toe_tuple_send(void);
static int cm_imsi_special_handle();
//////////////////////////////////////////////////////////////////////
// Macros
//////////////////////////////////////////////////////////////////////
#define IMSI_FILE "tmp/imsi_file"
//////////////////////////////////////////////////////////////////////
// Global Variables
//////////////////////////////////////////////////////////////////////
s_cellular_info g_cell_basic_info;
#if 0
static const struct blobmsg_policy cm_tftinfo_policy[] = {
[TFT1] = {.name = "direction",.type = BLOBMSG_TYPE_STRING},
[TFT2] = {.name = "directionPresent",.type = BLOBMSG_TYPE_STRING},
[TFT3_MIN] = {.name = "localPortRangeMin",.type = BLOBMSG_TYPE_STRING},
[TFT3_MAX] = {.name = "localPortRangeMax",.type = BLOBMSG_TYPE_STRING},
[TFT4_MIN] = {.name = "RemotePortRangeMin",.type = BLOBMSG_TYPE_STRING},
[TFT4_MAX] = {.name = "RemotePortRangeMax",.type = BLOBMSG_TYPE_STRING},
[TFT5] = {.name = "localPortRangePresent",.type = BLOBMSG_TYPE_STRING},
[TFT6] = {.name = "RemotelPortRangePresent",.type = BLOBMSG_TYPE_STRING},
[TFT7] = {.name = "SecondaryCID",.type = BLOBMSG_TYPE_STRING},
[TFT8] = {.name = "PfIdx",.type = BLOBMSG_TYPE_STRING},
[TFT9] = {.name = "EpIdx",.type = BLOBMSG_TYPE_STRING},
};
#endif
//destroyConnection
static const struct blobmsg_policy destroy_connection_policy[] = {
[CM_ID] = {.name = "id",.type = BLOBMSG_TYPE_INT32},
[CM_MSG1] = {.name = "connectionNum",.type = BLOBMSG_TYPE_INT32},
[CM_MSG2] = {.name = "deleteall",.type = BLOBMSG_TYPE_INT32},
};
//getLinkcontext
static const struct blobmsg_policy get_link_context_policy[] = {
[CM_ID] = {.name = "id",.type = BLOBMSG_TYPE_INT32},
//[CM_MSG1] = {.name = "msglen", .type = BLOBMSG_TYPE_INT32 },
//[CM_MSG2] = {.name = "connecitonnum", .type = BLOBMSG_TYPE_INT32 },
};
static const struct blobmsg_policy cm_set_image_policy[] = {
[CM_MSG1] = {.name = "Image_type",.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy pdpinfo_table_pol[] = {
[CONNECTION_NUM] = {
.name = "connection_num",
.type = BLOBMSG_TYPE_STRING},
[ENABLE] = {
.name = "enable",
.type = BLOBMSG_TYPE_STRING},
[PDP_NAME] = {
.name = "pdp_name",
.type = BLOBMSG_TYPE_STRING},
[IP_TYPE] = {
.name = "ip_type",
.type = BLOBMSG_TYPE_STRING},
[QCI] = {
.name = "qci",
.type = BLOBMSG_TYPE_STRING},
[APN] = {
.name = "apn",
.type = BLOBMSG_TYPE_STRING},
[LTE_APN] = {
.name = "lte_apn",
.type = BLOBMSG_TYPE_STRING},
[USR_2G3G] = {
.name = "usr_2g3g",
.type = BLOBMSG_TYPE_STRING},
[PSWD_2G3G] = {
.name = "pswd_2g3g",
.type = BLOBMSG_TYPE_STRING},
[AUTHTYPE_2G3G] = {
.name = "authtype_2g3g",
.type = BLOBMSG_TYPE_STRING},
[USR_4G] = {
.name = "usr_4g",
.type = BLOBMSG_TYPE_STRING},
[PSWD_4G] = {
.name = "pswd_4g",
.type = BLOBMSG_TYPE_STRING},
[AUTHTYPE_4G] = {
.name = "authtype_4g",
.type = BLOBMSG_TYPE_STRING},
[TYPE] = {
.name = "type",
.type = BLOBMSG_TYPE_STRING},
[AUTO_APN] = {
.name = "auto_apn",
.type = BLOBMSG_TYPE_STRING},
[CONNECT_MODE] = {
.name = "connect_mode",
.type = BLOBMSG_TYPE_STRING},
[LTE_DEFAULT] = {
.name = "lte_default",
.type = BLOBMSG_TYPE_STRING},
[DATA_ON_ROAMING] = {
.name = "data_on_roaming",
.type = BLOBMSG_TYPE_STRING},
[MTU] = {
.name = "mtu",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy profile_tabel_pol[] = {
[PRO_NAME] = {
.name = "profile_name",
.type = BLOBMSG_TYPE_STRING},
[PRO_ACTION] = {
.name = "action",
.type = BLOBMSG_TYPE_STRING},
[CONN_NUM] = {
.name = "connection_num",
.type = BLOBMSG_TYPE_STRING},
[APN_TYPE] = {
.name = "type",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy configs_handler_pol[] = {
[PROFILE] = {
.name = "profile",
.type = BLOBMSG_TYPE_TABLE},
[PDPINFO] = {
.name = "pdp_info",
.type = BLOBMSG_TYPE_TABLE},
};
static const struct blobmsg_policy connection_switch_pol[] = {
[CONNECT_SWITCH] = {
.name = "connect_switch",
.type = BLOBMSG_TYPE_TABLE},
};
static const struct blobmsg_policy auto_switch_pol[] = {
[CONNECT_SWITCH] = {
.name = "enable",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy eng_mode_pol[] = {
[ENG_MODE] = {
.name = "mode",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy connection_switch_table_pol[] = {
[PROTO] = {
.name = "proto",
.type = BLOBMSG_TYPE_STRING},
[DIAL_SWITCH] = {
.name = "dial_switch",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy get_apn_info_pol[] = {
[APN_TYPE_QUERY] = {
.name = "type",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy del_nwactivity_pol[] = {
[NWACTIVITY_DEL_INDEX] = {
.name = "index",
.type = BLOBMSG_TYPE_STRING},
[NWACTIVITY_DEL_FLAG] = {
.name = "flag",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy mcc_mnc_pol[] = {
[E_MCC] = {
.name = "mcc",
.type = BLOBMSG_TYPE_STRING},
[E_MNC] = {
.name = "mnc",
.type = BLOBMSG_TYPE_STRING},
};
static const struct blobmsg_policy cm_get_ccinet_pol[] = {
[0] = {
.name = "ccinet_cid",
.type = BLOBMSG_TYPE_INT32,
},
};
static struct uloop_timeout cm_query_enginfo_timeout = {
.cb = cm_query_enginfo_timeout_cb,
};
#if 0
static struct uloop_timeout cm_toe_tuple_timeout = {
.cb = cm_query_enginfo_timeout_cb,
};
#endif
Apn_Info atcmd_apn_info[16];
int atcmd_apn_state[16];
struct ubus_context *cm_ctx;
struct blob_buf cm_b;
static struct uci_context *uci_ctx_wan = NULL;
static network_activity_array nwactivity_array[MAX_NWACTIVITY_ARRAYNUM];
static int cur_nwarray_index = 0;
static int cur_nwarray_num = 0;
static struct ml_fifo cm_fifo;
static network_duration_s nw_duration[MAX_CID_LIMITATION];
int g_auto_apn_parsed = 0;
bool NWLac;
bool NWReady = FALSE;
bool IsRoaming = FALSE;
int NW_status = -1;
bool last_NWReady = FALSE;
int last_NWstatus = -1;
bool last_IsRoaming = FALSE;
bool pipe_mode = FALSE;
unsigned char RegStatus = 0;
bool imsi_changed = FALSE;
bool data_on_roaming_configed = FALSE;
pthread_t redial_tid;
#ifdef CONFIG_CM_URSP
pthread_t ursp_server_tid;
#endif
struct uloop_fd cm_server_fd;
struct uloop_fd cm_client_fd;
struct uloop_fd cm_accept_fd;
struct uloop_fd cm_conn_fd;
struct uloop_fd cm_conn_accept_fd;
#ifdef CM_CONFIG_TOE
struct uloop_fd cm_genl_fd;
#endif
#ifdef CONFIG_CM_URSP
struct uloop_fd cm_ursp_server_fd;
struct uloop_fd cm_ursp_server_accept_fd;
#endif
char gGetelNullApnImsi[4][6] = {
"29401",
"29702",
"22603",
"22606"
};
#ifdef CONFIG_CM_P701
#define MAX_ZROAM_COUNT 100
RIL_ZROAM g_zroam_list[MAX_ZROAM_COUNT];
#endif
#define CM_INVALID_CID 0xFF
struct toe_tft_param g_toe_tft_param[MAX_CID_LIMITATION];
extern bool may_need_reload;
static void cm_activity_subscribe_cb(struct ubus_context *ctx, struct ubus_object *obj)
{
UNUSED(ctx);
UNUSED(obj);
}
static struct blob_buf cm_notify_blob;
static struct ubus_object_type service_object_type;
static struct ubus_object network_activity_obj =
{.name = "cm.nwactivity",.type = &service_object_type,.subscribe_cb = cm_activity_subscribe_cb };
static bool cm_fail_cause_has_subscriber = false;
static void cm_fail_cause_subscribe_cb(struct ubus_context *ctx,
struct ubus_object *obj)
{
UNUSED(ctx);
if (obj->has_subscribers && !cm_fail_cause_has_subscriber) {
cm_fail_cause_has_subscriber = true;
} else if (!obj->has_subscribers && cm_fail_cause_has_subscriber) {
cm_fail_cause_has_subscriber = false;
}
}
static struct ubus_object cm_fail_cause_obj = {
.name = "cm.fail.cause",
.type = &service_object_type,
.subscribe_cb = cm_fail_cause_subscribe_cb
};
extern Mnc_Apn *g_work_apn;
extern Mnc_Apn *IMSI_APN;
extern cm_ubus_ctx_id cm_ubus_id;
extern CM_Connection_Context *g_CM_Context;
static CMSimID gSimID = CM_SIM_0;
#ifdef CM_DUAL_SIM_SUPPORT
SimSwitchCtx gCmSimSwitchCtx;
int CM_DeactiveDataCallAll(void);
int CM_SetMasterSimID(CMSimID simID, SwitchSimDoneCb cb);
static int SetRadioPowerState(int cfun_value)
{
return cm_set_cfun(cfun_value);
}
static int PSServiceOption(int enable)
{
return cm_set_psdc(enable);
}
int CM_DeactiveDataCallAll(void)
{
DisconnectInfo disInfo;
disInfo.connectionNum = 0;
disInfo.deleteall = 1;
CM_DestroyConnection(&disInfo);
return 0;
}
static void CM_UpdateActivedProfile(void)
{
s_profile_param profile = { 0 };
if (isMasterSim0())
snprintf(profile.profile_name, sizeof(profile.profile_name), "default");
else
snprintf(profile.profile_name, sizeof(profile.profile_name), "default_SIM2");
update_actived_profile(&profile, SWITCH_PROFILE);
}
static int CM_SimSwitchDone(void)
{
/* need to update SPN name */
g_cell_basic_info.spn_info.spn_exist = false;
CM_UpdateActivedProfile();
return get_imsi(true, true);
}
int CM_SetMasterSimID(CMSimID simID, SwitchSimDoneCb cb)
{
SimSwitchCtx *ctx = &gCmSimSwitchCtx;
int dualSimType = getDualSimType();
int ret = 0;
CM_Log(CM_SetMasterSimID1, "%s: simID %d, gSimID %d, state %d", __func__, simID, gSimID, ctx->state);
if (gSimID == simID)
return -1;
if (ctx->state != CM_SIM_SWITCH_INIT)
return -1;
ctx->currSim = simID;
ctx->switchDone = cb;
ctx->state = CM_SIM_SWITCH_START;
//CM_SimSwitchStateMachine(ctx);
CM_DeactiveDataCallAll();
ctx->state = CM_SIM_SWITCH_PRESIM_PDP_DOWN;
if (dualSimType == (int)CM_DUAL_SIM_SGIT)
SetRadioPowerState(0);
else if (dualSimType == (int)CM_DUAL_SIM_SINGLE_STANDBY)
SetRadioPowerState(4);
else
PSServiceOption(0);
ctx->state = CM_SIM_SWITCH_PRESIM_PSDC_DOWN;
gSimID = ctx->currSim;
#if 0
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
ret = CM_ERR_MEM;
goto end;
}
snprintf(buf, sizeof(buf), "%d", ctx->currSim);
ret = uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_SIM_SWITCH_T, SEC_SIM_SWITCH_N, MASTER_SIM, buf);
if (!ret) {
ret = CM_ERR_INVAL;
goto end;
}
#endif
setMasterSimID(gSimID);
if (dualSimType == (int)CM_DUAL_SIM_SGIT)
SetRadioPowerState(1);
else if (dualSimType == (int)CM_DUAL_SIM_SINGLE_STANDBY)
SetRadioPowerState(1);
else
PSServiceOption(1);
ctx->state = CM_SIM_SWITCH_CURRSIM_PSDC_UP;
ctx->state = CM_SIM_SWITCH_INIT;
CM_SimSwitchDone();
return ret;
}
#endif
bool isMasterSim0(void)
{
return (gSimID == CM_SIM_0) ? TRUE : FALSE;
}
void setMasterSimID(int simID)
{
if (simID == CM_SIM_1)
setSim2Master(1);
else
setSim2Master(0);
}
int getMasterSimID(void)
{
int sim2_master;
sim2_master = isSim2Master();
if (sim2_master)
gSimID = CM_SIM_1;
else
gSimID = CM_SIM_0;
CM_Log(getMasterSimID1, "%s: %d", __func__, gSimID);
return (int)gSimID;
}
//TRUE --allow datalink, FALSE-- don't allow datalink
bool cm_allow_datalink(void)
{
bool ret;
struct uci_context *local_ctx = NULL;
char *value = NULL;
Apn_Info * apninfo = NULL;
ret = TRUE;
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
{
ret = FALSE;
goto END;
}
#endif
/*load /etc/config/wan */
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
ret = FALSE;
goto END;
}
value = uci_get_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_PROTO);
if (!value) {
ret = FALSE;
goto END;
}
if (!strcmp(value, "disabled")) {
ret = FALSE;
goto END;
}
value =
uci_get_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_DIAL_SWITCH);
if (!value) {
ret = FALSE;
goto END;
}
if (!strcmp(value, "disabled")) {
ret = FALSE;
goto END;
}
apninfo = get_default_apninfo(g_work_apn, NULL);
if(apninfo != NULL) {
if(apninfo->Extra_params.autoconnect == CM_CONTYPE_MANUAL) {
ret = FALSE;
goto END;
}
if(apninfo->Extra_params.data_on_roaming == 0 && check_roamStatus() == TRUE) {
ret = FALSE;
goto END;
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (g_CM_Context == NULL && apninfo->Extra_params.always_on == 0) {
ret = FALSE;
goto END;
}
#endif
}
else
ret = FALSE;
END:
CM_Log(cm_allow_datalink1, "cm_allow_datalink: ret %d", ret);
return ret;
}
static void cm_nw_duration_set(int cid, int status, int ticks)
{
network_duration_s *item = NULL;
if (cid < 0 || cid >= MAX_CID_LIMITATION)
return;
item = &nw_duration[cid];
item->cid = cid;
item->connect_status = status;
if(status == CM_CONNECT_CONSUCCESS)
{
if (item->connect_ticks == 0)
{
item->connect_ticks = ticks;
CM_Log(cm_nw_duration_set454, "cm_nw_duration_set: [connect]cid %d, connect ticks %d", cid, ticks);
}
}
else if (status == CM_CONNECT_DISCON || status == CM_CONNECT_DEACTIVATED || status == CM_CONNECT_WAIT_PS_ATTACH)
{
if (ticks >= item->connect_ticks && item->connect_ticks > 0)
{
item->current_duration_time = ticks - item->connect_ticks;
item->duration_time += (ticks - item->connect_ticks);
CM_Log(cm_nw_duration_set455, "cm_nw_duration_set: [disconnect]cid %d, current_duration_time %d, duration_time %d", cid,
item->current_duration_time, item->duration_time);
}
item->connect_ticks = 0;
}
}
void nwactivity_arrary_init(void)
{
int idx = 0;
cur_nwarray_index = 0;
cur_nwarray_num = 0;
memset(&nwactivity_array, 0, sizeof(network_activity_array)*MAX_NWACTIVITY_ARRAYNUM);
//indicate unused
for(idx = 0; idx < MAX_NWACTIVITY_ARRAYNUM; idx++)
nwactivity_array[idx].index = -1;
}
int cm_find_nwarrayindex(int cid)
{
int index;
for(index = cur_nwarray_index - 1; index >= 0; index--) {
if(nwactivity_array[index].cid == cid)
return index;
}
if((cur_nwarray_num == MAX_NWACTIVITY_ARRAYNUM) && (cur_nwarray_index != (MAX_NWACTIVITY_ARRAYNUM - 1))) {
for(index = MAX_NWACTIVITY_ARRAYNUM - 1; index != cur_nwarray_index; index--) {
if(nwactivity_array[index].cid == cid)
return index;
}
}
return -1;
}
void cm_nwactivity_notify_complete_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
CM_Log(cm_nwactivity_notify_complete_cb, "cm_nwactivity_notify_complete_cb(ret=%d)", ret);
if (req) {
free(req);
req = NULL;
}
}
static void cm_get_activity_duration(int cid, network_activity_msg *activity)
{
network_duration_s *item = NULL;
if (cid < 0 || cid >= MAX_CID_LIMITATION || activity == NULL)
return;
item = &nw_duration[cid];
if (item->connect_ticks > 0)
{
if (activity->notify_ticks >= item->connect_ticks)
activity->current_duration_time = activity->notify_ticks - item->connect_ticks;
activity->duration_time = activity->current_duration_time + item->duration_time;
}
else
{
activity->current_duration_time = item->current_duration_time;
activity->duration_time = item->duration_time;
}
CM_Log(cm_get_activity_duration531, "cm_get_activity_duration, cid %d, current_duration %d, duration %d", cid, activity->current_duration_time, activity->duration_time);
return;
}
int cm_nwactivity_notify(network_activity_msg * msg, bool sync)
{
int ret;
struct ubus_notify_request * nreq = NULL;
if (msg == NULL) {
return -1;
}
blob_buf_init(&cm_notify_blob, 0);
blobmsg_add_u32(&cm_notify_blob, "connectstatus", msg->connect_status);
blobmsg_add_u32(&cm_notify_blob, "cid", msg->cid);
blobmsg_add_u32(&cm_notify_blob, "iptype", msg->iptype);
blobmsg_add_u32(&cm_notify_blob, "current_duration_time", msg->current_duration_time);
blobmsg_add_u32(&cm_notify_blob, "duration_time", msg->duration_time);
blobmsg_add_u32(&cm_notify_blob, "notify_ticks", msg->notify_ticks);
CM_Log(cm_nwactivity_notify1, "cm_nwactivity_notify: connect status %d, iptype %d, cid %d, current_duration_time %d, duration_time %d, notify_ticks %d, sync %d",
msg->connect_status, msg->iptype, msg->cid, msg->current_duration_time, msg->duration_time, msg->notify_ticks, sync);
if (sync)
{
ret = ubus_notify(cm_ctx,&network_activity_obj, network_activity_obj.name, cm_notify_blob.head, 5000);
if (ret)
{
CM_Log(cm_nwactivity_notify2, "cm_nwactivity_notify: ubus_notify failed [err=%s]\n", ubus_strerror(ret));
}
}
else
{
nreq = (struct ubus_notify_request*)malloc(sizeof(struct ubus_notify_request));
ret = ubus_notify_async(cm_ctx,&network_activity_obj, network_activity_obj.name, cm_notify_blob.head, nreq);
if(ret != 0) {
free(nreq);
return ret;
}else {
nreq->complete_cb = (void *)&cm_nwactivity_notify_complete_cb;
//ubus_complete_request(cm_ctx, &(nreq->req), 5000);
ubus_complete_request_async(cm_ctx, &(nreq->req)) ;
}
}
return ret;
}
void cm_record_nwactivity(CM_Connection_Context * coninfo, bool sync)
{
int index, cid;
network_activity_msg nwmsg={0};
time_t cur_tim;
if(coninfo->pdpinfo->PDP_Type == 1)
cid = coninfo->pdpinfo->primaryCid;
else
cid = coninfo->pdpinfo->secondaryCid;
time(&cur_tim);
cm_nw_duration_set(cid - 1, coninfo->connectStatus, cur_tim);
//notify the network activity
nwmsg.connect_status = coninfo->connectStatus;
nwmsg.cid = cid;
nwmsg.iptype = coninfo->pdpinfo->IP_Type;
nwmsg.notify_ticks = cur_tim;
CM_Log(cm_record_nwactivity, "cm_record_nwactivity, connect status %d, cid %d, iptype %d", nwmsg.connect_status, nwmsg.cid, nwmsg.iptype);
cm_get_activity_duration(cid - 1, &nwmsg);
cm_nwactivity_notify(&nwmsg, sync);
if(coninfo->connectStatus == CM_CONNECT_CONSUCCESS) {
CM_Log(cm_record_nwactivity1, "cm_record_nwactivity, [connected] cur_nwarray_index:%d, connect_ticks %d",cur_nwarray_index, cur_tim);
strcpy(nwactivity_array[cur_nwarray_index].PDP_name, coninfo->pdpinfo->PDP_name);
strncpy(nwactivity_array[cur_nwarray_index].start_tim, ctime(&cur_tim), sizeof(nwactivity_array[cur_nwarray_index].start_tim) - 1);
nwactivity_array[cur_nwarray_index].connect_ticks = cur_tim;
//nwactivity_array[cur_nwarray_index].end_tim = 0;
nwactivity_array[cur_nwarray_index].cid = cid;
nwactivity_array[cur_nwarray_index].index = cur_nwarray_index;
if(coninfo->pdpinfo->PDP_Type == 1) {
nwactivity_array[cur_nwarray_index].iptype = coninfo->pdpinfo->IP_Type;
if(coninfo->ipv4info != NULL)
nwactivity_array[cur_nwarray_index].ipv4addr = coninfo->ipv4info->IPAddr;
if(coninfo->ipv6info != NULL) {
nwactivity_array[cur_nwarray_index].ipv6addr[0] = coninfo->ipv6info->IPV6Addr[0];
nwactivity_array[cur_nwarray_index].ipv6addr[1] = coninfo->ipv6info->IPV6Addr[1];
nwactivity_array[cur_nwarray_index].ipv6addr[2] = coninfo->ipv6info->IPV6Addr[2];
nwactivity_array[cur_nwarray_index].ipv6addr[3] = coninfo->ipv6info->IPV6Addr[3];
}
}
if(cur_nwarray_num < MAX_NWACTIVITY_ARRAYNUM)
cur_nwarray_num ++;
if(cur_nwarray_index < MAX_NWACTIVITY_ARRAYNUM - 1)
cur_nwarray_index ++;
else
cur_nwarray_index = 0;
}else if(coninfo->connectStatus == CM_CONNECT_DISCON || coninfo->connectStatus == CM_CONNECT_DEACTIVATED || coninfo->connectStatus == CM_CONNECT_WAIT_PS_ATTACH) {
index = cm_find_nwarrayindex(cid);
CM_Log(cm_record_nwactivity2, "cm_record_nwactivity: [disconnected] index:%d", index);
if(index != -1)
{
strncpy(nwactivity_array[index].end_tim, ctime(&cur_tim), sizeof(nwactivity_array[cur_nwarray_index].end_tim) - 1);
if (cur_tim >= nwactivity_array[index].connect_ticks && nwactivity_array[index].connect_ticks > 0)
{
nwactivity_array[index].current_duration_time = cur_tim - nwactivity_array[index].connect_ticks;
nwactivity_array[index].duration_time += (cur_tim - nwactivity_array[index].connect_ticks);
CM_Log(cm_record_nwactivity575, "cm_record_nwactivity: index %d, current_duration_time %d, duration_time %d", index,
nwactivity_array[index].current_duration_time, nwactivity_array[index].duration_time);
}
nwactivity_array[cur_nwarray_index].connect_ticks = 0;
}
}
}
static void cm_dial_failure_cause_notify_complete(struct ubus_notify_request *req, int idx, int ret)
{
UNUSED(idx);
UNUSED(ret);
CM_Log(cm_dial_failure_cause_notify_complete, "cm_dial_failure_cause_notify_complete %d", ret);
if (req) {
free(req);
req = NULL;
}
}
static int cm_dial_failure_cause_notify(s_cause_msg *msg)
{
int ret;
struct ubus_notify_request * nreq = NULL;
if (msg == NULL || !cm_fail_cause_has_subscriber) {
return -1;
}
blob_buf_init(&cm_notify_blob, 0);
blobmsg_add_u32(&cm_notify_blob, "connect_num", msg->connect_num);
blobmsg_add_u32(&cm_notify_blob, "cause", msg->cause);
CM_Log(cm_dial_failure_cause_notify, "cm_dial_failure_cause_notify: connect num %d, cause %d", msg->connect_num, msg->cause);
nreq = (struct ubus_notify_request*)malloc(sizeof(struct ubus_notify_request));
ret = ubus_notify_async(cm_ctx, &cm_fail_cause_obj, cm_fail_cause_obj.name, cm_notify_blob.head, nreq);
if (ret != 0) {
free(nreq);
return ret;
} else {
nreq->complete_cb = cm_dial_failure_cause_notify_complete;
//ubus_complete_request(cm_ctx, &(nreq->req), 5000);
ubus_complete_request_async(cm_ctx, &(nreq->req));
}
return ret;
}
void cm_notify_dial_failure(int connect_num, int status, int cause)
{
s_cause_msg cause_ind_msg = { 0 };
cause_ind_msg.connect_num = connect_num;
if (status == -2)
cause_ind_msg.cause = PDP_FAIL_NO_CCINET;
else if (status == -3)
cause_ind_msg.cause = PDP_FAIL_DHCP_SERVER_ERR_PIPE;
else
cause_ind_msg.cause = cause;
cm_dial_failure_cause_notify(&cause_ind_msg);
}
void spn_info_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno = 0;
void *response_data = NULL;
int response_len = 0;
char *spn_data;
char tmp[64] = { 0 };
char temp[3] = { 0 };
char *p, *endptr = NULL;
char ascii_char;
int i;
int ret = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
ret = 1;
goto end;
}
if (response_data && (response_len > 0)) {
if (rilerrno != RIL_E_SUCCESS) {
g_cell_basic_info.status = rilerrno;
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 2;
goto end;
}
spn_data = (char *)response_data;
if (sscanf(spn_data, "%*[^,],%*[^,],%s", tmp) != 1) {
rilutil_freeResponseData(requestid, response_data, response_len);
g_cell_basic_info.status = rilerrno;
ret = 3;
goto end;
}
memcpy(temp, tmp, 2);
temp[2] = '\0';
g_cell_basic_info.spn_info.dis_cond = atoi(temp);
p = tmp + 2;
memset(g_cell_basic_info.spn_info.spn_name, 0, MAX_SIM_INFO_STR_LEN);
for (i = 0; i < 16; i++) {
memcpy(temp, p, 2);
temp[2] = '\0';
if (strcmp(temp, "FF") == 0) {
break;
}
g_cell_basic_info.spn_info.spn_exist = 1;
ascii_char = (char)strtoul(temp, &endptr, 16);
g_cell_basic_info.spn_info.spn_name[i] = ascii_char;
CM_Log(spn_info_request_cb3, "spn_info_request_cb: spn ascii char %d\n", ascii_char);
p += 2;
}
g_cell_basic_info.status = 0;
rilutil_freeResponseData(requestid, response_data, response_len);
} else {
if (response_data) {
rilutil_freeResponseData(requestid, response_data, response_len);
}
g_cell_basic_info.status = rilerrno;
}
end:
CM_Log(spn_info_request_cb1, "spn_info_request_cb: ret %d, rilerrno %d\n", ret, rilerrno);
}
void rssi_info_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno = 0;
void *response_data = NULL;
int response_len = 0;
s_signal_quality *rssi_data;
int ret = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
ret = 1;
goto end;
}
if (response_data && (response_len > 0)) {
if (rilerrno != RIL_E_SUCCESS) {
g_cell_basic_info.status = rilerrno;
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 2;
goto end;
}
rssi_data = (s_signal_quality *) response_data;
if (g_cell_basic_info.sys_mode == E_2G_3G) {
g_cell_basic_info.rssi = rssi_data->GW_SignalStrength.signalStrength;
} else if (g_cell_basic_info.sys_mode == E_LTE ||g_cell_basic_info.sys_mode == E_LTEP) {
//g_cell_basic_info.rssi = rssi_data->LTE_SignalStrength.signalStrength;
if ( rssi_data->LTE_SignalStrength.rsrp >= 44 && rssi_data->LTE_SignalStrength.rsrp <= 141)
g_cell_basic_info.rssi =141 - rssi_data->LTE_SignalStrength.rsrp;
else
g_cell_basic_info.rssi = 0;
}
g_cell_basic_info.status = 0;
rilutil_freeResponseData(requestid, response_data, response_len);
} else {
if (response_data) {
rilutil_freeResponseData(requestid, response_data, response_len);
}
g_cell_basic_info.status = rilerrno;
}
end:
CM_Log(rssi_info_request_cb1, "rssi_info_request_cb: ret %d rilerrno %d\n", ret, rilerrno);
}
static void ims_reg_state_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
int *state;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data && (response_len > 0)) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
state = (int *) response_data;
g_cell_basic_info.ims_state = *state;
rilutil_freeResponseData(requestid, response_data, response_len);
} else {
if (response_data) {
rilutil_freeResponseData(requestid, response_data, response_len);
}
}
}
static void get_etiflag_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno;
char *response_data = NULL;
int response_len = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, (void *)&response_data, &response_len)) {
return;
}
if (response_data && (response_len > 0)) {
if (rilerrno != RIL_E_SUCCESS) {
g_cell_basic_info.etiflag = -1;
goto end;
}
if (requestid != RIL_REQUEST_GET_ETIFLAG)
{
g_cell_basic_info.etiflag = -1;
goto end;
}
g_cell_basic_info.etiflag = *(int *)response_data;
CM_Log_E(get_etiflag_request_cb2, "%s: etiflag %d\n", __func__, g_cell_basic_info.etiflag);
}
end:
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
void save_imsi_into_tmp_file(char *imsi)
{
int fd = 0, size = 0;
char buf[MAX_SIM_INFO_STR_LEN] = { 0 };
if (!imsi || !strlen(imsi)) {
CM_Log_E(save_imsi_into_tmp_file, "NO IMSI");
return;
}
fd = open(IMSI_FILE, O_WRONLY | O_TRUNC | O_CREAT, S_IRUSR|S_IWUSR);
if (fd < 0) {
return;
}
size = strlen(imsi) + 1;
strncpy(buf, imsi, MAX_SIM_INFO_STR_LEN - 1);
size = write(fd, buf, size);
close(fd);
return;
}
char *cm_get_cellular_imsi(void)
{
if (strlen(g_cell_basic_info.IMSI) > 0)
return g_cell_basic_info.IMSI;
else
return NULL;
}
void sim_info_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno = 0;
char *response_data = NULL;
int response_len = 0;
int ret = 0;
int *req_priv = 0;
int switch_sim = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, (void *)&response_data, &response_len)) {
ret = 1;
goto end;
}
if (response_data && (response_len > 0)) {
if (rilerrno != RIL_E_SUCCESS) {
g_cell_basic_info.status = rilerrno;
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 2;
goto end;
}
if (response_len >= MAX_SIM_INFO_STR_LEN) {
rilutil_freeResponseData(requestid, response_data, response_len);
g_cell_basic_info.status = -1;
ret = 3;
goto end;
}
if (requestid == RIL_REQUEST_GET_IMEI) {
memset(g_cell_basic_info.IMEI, 0, MAX_SIM_INFO_STR_LEN);
memcpy(g_cell_basic_info.IMEI, response_data, response_len);
} else if (requestid == RIL_REQUEST_GET_IMEISV) {
memset(g_cell_basic_info.IMEI_SV, 0, MAX_SIM_INFO_STR_LEN);
memcpy(g_cell_basic_info.IMEI_SV, response_data, response_len);
} else if (requestid == RIL_REQUEST_GET_IMSI) {
imsi_changed = FALSE;
if (strlen(g_cell_basic_info.IMSI)) {
CM_Log_E(sim_info_request_cb5, "sim_info_request_cb: last imsi %s, new imsi[%d] %s\n", g_cell_basic_info.IMSI, response_len, response_data);
if (strncmp(g_cell_basic_info.IMSI, response_data, sizeof(g_cell_basic_info.IMSI) - 1)) {
imsi_changed = TRUE;
}
}
memset(g_cell_basic_info.IMSI, 0, MAX_SIM_INFO_STR_LEN);
memcpy(g_cell_basic_info.IMSI, response_data, response_len);
save_imsi_into_tmp_file(g_cell_basic_info.IMSI);
req_priv = req->priv;
if (req_priv && *req_priv != RIL_REQUEST_GET_IMSI)
{
switch_sim = *req_priv;
free(req_priv);
}
if (imsi_changed)
{
if (is_ctcc_sim(g_cell_basic_info.IMSI) && switch_sim == 0)
{
cm_save_default_apn(NULL, NULL);
CM_Clear_ETIFlag(false);
}
reinit_apn_list();
}
}
g_cell_basic_info.status = 0;
rilutil_freeResponseData(requestid, response_data, response_len);
} else {
if (response_data) {
rilutil_freeResponseData(requestid, response_data, response_len);
}
ret = 4;
g_cell_basic_info.status = -1;
}
end:
CM_Log(sim_info_request_cb1, "sim_info_request_cb: ret %d rilerrno %d\n", ret, rilerrno);
}
void plmn_operator_request_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
rilutilstrings *response = NULL;
int i = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_OPERATOR) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
response = (rilutilstrings *) response_data;
i = 0;
for (i = 0; i < response->num; i++) {
CM_Log(plmn_operator_request_cb3, "plmn_operator_request_cb: response->str[%d] %s\n", i, response->str[i] ? response->str[i] : "NULL");
}
if (response->num > 1) {
if (response->str[1] && strlen(response->str[1]) > 0)
strncpy(g_cell_basic_info.ons_info.ons, response->str[1], MAX_SIM_INFO_STR_LEN - 1); // short ons
else if (response->str[0])
strncpy(g_cell_basic_info.ons_info.ons, response->str[0], MAX_SIM_INFO_STR_LEN - 1); // long ons
}
if (response->num > 2 && response->str[2])
strncpy(g_cell_basic_info.ons_info.plmn, response->str[2], 6);
// should free buffer this point
for (i = 0; i < response->num; i++) {
if (response->str[i]) {
free(response->str[i]);
response->str[i] = NULL;
}
}
if (response->str) {
free(response->str);
response->str = NULL;
}
free(response_data);
CM_Log(plmn_operator_request_cb989, "plmn_operator_request_cb: done\n");
}
}
int cm_get_nw_status_cache()
{
return NW_status;
}
void cm_reset_nw_last_param(void)
{
last_NWReady = FALSE;
last_NWstatus = 0;
last_IsRoaming = FALSE;
}
void CheckDataCallRegisterStatus_IndCall_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int requestid;
unsigned int rilerrno = 0;
void *response_data = NULL;
int response_len = 0;
int lac = 0;
int cid = -1;
int gprsState = 0;
int RejectCause = 0;
rilutilstrings *response = NULL;
int i = 0;
bool need_redial = TRUE;
may_need_reload = FALSE;
int ret = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
ret = 1;
goto end;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 2;
goto end;
}
if (requestid != RIL_REQUEST_DATA_REGISTRATION_STATE) {
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 3;
goto end;
}
response = (rilutilstrings *) response_data;
i = 0;
if (response->num > i)
RegStatus = atoi(response->str[i++]);
if (response->num > i)
lac = atoi(response->str[i++]);
if (response->num > i)
cid = atoi(response->str[i++]);
if (response->num > i)
gprsState = atoi(response->str[i++]);
if (response->num > i)
RejectCause = atoi(response->str[i++]);
// should free buffer this point
for (i = 0; i < response->num; i++) {
if (response->str[i]) {
free(response->str[i]);
response->str[i] = NULL;
}
}
if (response->str) {
free(response->str);
response->str = NULL;
}
free(response);
} else {
ret = 4;
goto end;
}
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb5, "IndRegStatus_data_cb: RegStatus is %d, lac is %d, cid is %d, gprsState is %d, RejectCause is %d\n",
RegStatus, lac, cid, gprsState, RejectCause);
if (lac != 0 && lac != NWLac)
{
NWLac = lac;
stop_2hours_redial_timer();
}
if (RegStatus == 5)
IsRoaming = TRUE;
else
IsRoaming = FALSE;
if ((RegStatus == 1) || (RegStatus == 5))
NWReady = TRUE;
else
NWReady = FALSE;
if (last_IsRoaming != IsRoaming) {
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb6, "IndRegStatus_data_cb: roam changed %d->%d", last_IsRoaming, IsRoaming);
if (last_IsRoaming == TRUE && IsRoaming == FALSE) {
send_redialmsg_to_redialthread(-1, REDIAL_ROAMCHANGE);
} else {
CM_Handle_ChangetoRoam();
}
last_IsRoaming = IsRoaming;
/*If roaming status changed, no need to redial accordding to network status, just update the network status*/
need_redial = FALSE;
}
g_cell_basic_info.roaming = IsRoaming;
g_cell_basic_info.data_mode = gprsState;
if ((RegStatus != 1) && (RegStatus != 5)) {
NW_status = CM_NW_STATUS_NOT_REGISTERED; //not registered
g_cell_basic_info.sys_mode = E_NO_SERVICE;
} else if (gprsState == RADIO_TECH_LTE || gprsState == RADIO_TECH_LTEP) {
NW_status = CM_NW_STATUS_LTE; //registered on 4G
g_cell_basic_info.sys_mode = E_LTE;
if (gprsState == RADIO_TECH_LTEP)
g_cell_basic_info.sys_mode = E_LTEP;
} else if ((gprsState == RADIO_TECH_GPRS) || (gprsState == RADIO_TECH_EDGE) || (gprsState == RADIO_TECH_GSM)
|| (gprsState == RADIO_TECH_UMTS) || (gprsState == RADIO_TECH_HSDPA)
|| (gprsState == RADIO_TECH_HSUPA) || (gprsState == RADIO_TECH_HSPA)) {
NW_status = CM_NW_STATUS_23G;//registered on 2/3G
g_cell_basic_info.sys_mode = E_2G_3G;
} else if (gprsState == RADIO_TECH_EUTRAN_TO_5GCN ||gprsState == RADIO_TECH_NR_TO_5GCN ||
gprsState == RADIO_TECH_NGRAN || gprsState == RADIO_TECH_EUTRAN_NR_DUAL_LINK) {
NW_status = CM_NW_STATUS_5G;//registered 5G
g_cell_basic_info.sys_mode = E_5G;
}
else
NW_status = -1;
if (last_NWstatus != NW_status) {
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb9, "IndRegStatus_data_cb: NWstatus changed %d -> %d {0: 2/3G, 1: LTE, 2: 5G, 3: Not registered, -1: Init}", last_NWstatus, NW_status);
if (last_NWstatus == 0 && need_redial == TRUE &&
(NW_status == CM_NW_STATUS_NOT_REGISTERED || NW_status == CM_NW_STATUS_LTE || NW_status == CM_NW_STATUS_5G)) {
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb10, "IndCall_data_cb, network status change from 2/3g to LTE/5G or not registered");
send_redialmsg_to_redialthread(-1, REDIAL_NWCHANGE);
}
last_NWstatus = NW_status;
}
if (last_NWReady != NWReady) {
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb11, "IndRegStatus_data_cb: NWReady changed %d-> %d", last_NWReady, NWReady);
if (last_NWReady == FALSE && NWReady == TRUE && need_redial == TRUE) {
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb12, "IndRegStatus_data_cb, network registered, send redial here!");
stop_2hours_redial_timer();
send_redialmsg_to_redialthread(-1, REDIAL_NWCHANGE);
}
last_NWReady = NWReady;
}
end:
if (ret != 0 || rilerrno != 0)
CM_Log(CheckDataCallRegisterStatus_IndCall_data_cb13, "IndRegStatus_data_cb: ret %d, rilerrno %d", ret, rilerrno);
}
void CheckDataCallRegisterStatus_data_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int requestid;
unsigned int rilerrno = 0;
void *response_data = NULL;
int response_len = 0;
int lac = 0;
int cid = -1;
int gprsState = 0;
int RejectCause = 0;
rilutilstrings *response = NULL;
int i = 0;
int ret = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
ret = 1;
goto end;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 2;
goto end;
}
if (requestid != RIL_REQUEST_DATA_REGISTRATION_STATE_NOCACHE) {
rilutil_freeResponseData(requestid, response_data, response_len);
ret = 3;
goto end;
}
response = (rilutilstrings *) response_data;
CM_Log_E(CheckDataCallRegisterStatus_data_cb12, "CheckDataCallRegisterStatus_data_cb: response->num %d \n", response->num );
i = 0;
if (response->num > i && response->str[i])
RegStatus = atoi(response->str[i++]);
if (response->num > i && response->str[i])
lac = atoi(response->str[i++]);
if (response->num > i && response->str[i])
cid = atoi(response->str[i++]);
if (response->num > i && response->str[i])
gprsState = atoi(response->str[i++]);
if (response->num > i && response->str[i])
RejectCause = atoi(response->str[i++]);
// should free buffer this point
for (i = 0; i < response->num; i++) {
if (response->str[i]) {
free(response->str[i]);
response->str[i] = NULL;
}
}
if (response->str) {
free(response->str);
response->str = NULL;
}
free(response);
} else {
ret = 4;
goto end;
}
CM_Log(CheckDataCallRegisterStatus_data_cb5, "data_cb: RegStatus is %d, lac is %d, cid is %d, gprsState is %d, RejectCause is %d\n",
RegStatus, lac, cid, gprsState, RejectCause);
if (RegStatus == 5)
IsRoaming = TRUE;
else
IsRoaming = FALSE;
if ((RegStatus == 1) || (RegStatus == 5))
NWReady = TRUE;
else
NWReady = FALSE;
if (last_IsRoaming != IsRoaming) {
CM_Log(CheckDataCallRegisterStatus_data_cb6, "data_cb, roam change %d -> %d", last_IsRoaming, IsRoaming);
if (last_IsRoaming == TRUE && IsRoaming == FALSE) {
send_redialmsg_to_redialthread(-1, REDIAL_ROAMCHANGE);
} else {
CM_Handle_ChangetoRoam();
}
last_IsRoaming = IsRoaming;
}
g_cell_basic_info.roaming = IsRoaming;
g_cell_basic_info.data_mode = gprsState;
if ((RegStatus != 1) && (RegStatus != 5)) {
NW_status = CM_NW_STATUS_NOT_REGISTERED; //not registered
g_cell_basic_info.sys_mode = E_NO_SERVICE;
} else if (gprsState == RADIO_TECH_LTE || gprsState == RADIO_TECH_LTEP) {
NW_status = CM_NW_STATUS_LTE; //registered on 4G
g_cell_basic_info.sys_mode = E_LTE;
} else if ((gprsState == RADIO_TECH_GPRS) || (gprsState == RADIO_TECH_EDGE) || (gprsState == RADIO_TECH_GSM)
|| (gprsState == RADIO_TECH_UMTS) || (gprsState == RADIO_TECH_HSDPA)
|| (gprsState == RADIO_TECH_HSUPA) || (gprsState == RADIO_TECH_HSPA ) ||(gprsState == RADIO_TECH_HSPAP)) {
NW_status = CM_NW_STATUS_23G; //registered on 2/3G
g_cell_basic_info.sys_mode = E_2G_3G;
} else if (gprsState == RADIO_TECH_EUTRAN_TO_5GCN ||gprsState == RADIO_TECH_NR_TO_5GCN ||
gprsState == RADIO_TECH_NGRAN || gprsState == RADIO_TECH_EUTRAN_NR_DUAL_LINK) {
NW_status = CM_NW_STATUS_5G;//registered 5G
g_cell_basic_info.sys_mode = E_5G;
}
else
NW_status = -1;
CM_Log(CheckDataCallRegisterStatus_data_cb8, "data_cb: NWReady %d, IsRoaming is %d, NW_status %d\n", NWReady, IsRoaming, NW_status);
if (last_NWReady != NWReady)
last_NWReady = NWReady;
end:
if (ret != 0 || rilerrno != 0)
CM_Log(CheckDataCallRegisterStatus_data_cb9, "data_cb: ret %d, rilerrno %d", ret, rilerrno);
}
void CheckDataCallRegisterStatus()
{
int ret_val;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_DATA_REGISTRATION_STATE_NOCACHE, NULL, 0);
CM_Log(CheckDataCallRegisterStatus1, "CheckDataCallRegisterStatus: enter");
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, CheckDataCallRegisterStatus_data_cb,
0, 0)) != UBUS_STATUS_OK) {
CM_Log_E(CheckDataCallRegisterStatus, "CheckDataCallRegisterStatus, ubus_invoke RIL_REQUEST_DATA_REGISTRATION_STATE failed %s\n",
ubus_strerror(ret_val));
}
}
void CheckDataCallRegisterStatus_complete_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
CM_Log(CheckDataCallRegisterStatus_complete_cb, "CheckDataCallRegisterStatus_complete_cb: enter, ret = %d", ret);
if (req) {
free(req);
req = NULL;
}
}
void CheckDataCallRegisterStatus_IndCallback()
{
int ret_val;
struct ubus_request *req = NULL;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_DATA_REGISTRATION_STATE, NULL, 0);
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
free(req);
return;
} else {
req->data_cb = CheckDataCallRegisterStatus_IndCall_data_cb;
req->complete_cb = CheckDataCallRegisterStatus_complete_cb;
ubus_complete_request_async(cm_ctx, req);
}
}
#define RULE_SHOW_PLMN 0x01
#define RULE_SHOW_SPN 0x02
#define NETWORK_NAME_TYPE 0
#define ROAMING_NETWORK_NAME_TYPE 1
char *ucs2_to_utf8(unsigned char *ucs2)
{
unsigned short ucs2_code = 0;
int len = 0, i = 0, j = 0;
int ucs2_count = 0;
int nbytes = 0;
unsigned char bytes[4] = { 0 };
char *utf8 = NULL;
if (!ucs2)
return NULL;
ucs2_count = strlen((const char *)ucs2);
if (ucs2_count <= 0 && ucs2_count % 2 != 0)
return NULL;
nbytes = (ucs2_count / 2) * 3 + 1;
utf8 = malloc(nbytes);
if (!utf8)
return NULL;
memset(utf8, 0, nbytes);
for (i = 0; i < ucs2_count; i=i+2) {
ucs2_code = (ucs2[i] << 8) + ucs2[i + 1];
if (ucs2_code < 0x80) {
bytes[0] = ucs2_code;
nbytes = 1;
} else if (ucs2_code < 0x800) {
bytes[1] = (ucs2_code & 0x3F) | 0x80;
bytes[0] = (((ucs2_code << 2) & 0x1F00) | 0xC000) >> 8;
nbytes = 2;
} else {
bytes[2] = (ucs2_code & 0x3F) | 0x80;
bytes[1] = (((ucs2_code << 2) & 0x3F00) | 0x8000) >> 8;
bytes[0] = (((ucs2_code << 4) & 0x0F0000) | 0xE00000) >> 16;
nbytes = 3;
}
for (j = 0; j < nbytes; j++) {
utf8[len] = bytes[j];
len++;
}
}
utf8[len] = '\0';
CM_Log(ucs2_to_utf8, "ucs2_to_utf8: utf8 str[%d] %s", len, utf8);
return utf8;
}
int get_network_display_rule(s_cellular_info * info)
{
int rule;
if (!info->spn_info.spn_exist) {
rule = RULE_SHOW_PLMN;
return rule;
}
if (!info->roaming) {
rule = RULE_SHOW_SPN;
if ((info->spn_info.dis_cond & RULE_SHOW_PLMN) == RULE_SHOW_PLMN)
rule |= RULE_SHOW_PLMN;
} else {
rule = RULE_SHOW_PLMN;
if ((info->spn_info.dis_cond & RULE_SHOW_SPN) == 0x00)
rule |= RULE_SHOW_SPN;
}
return rule;
}
int get_register_plmn()
{
int ret_val;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_OPERATOR, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, plmn_operator_request_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(get_register_plmn, "get_register_plmn, ubus_invoke RIL_REQUEST_OPERATOR failed %s\n", ubus_strerror(ret_val));
}
return ret_val;
}
char *get_network_name(int type)
{
#define PLMN_NAME_SIZE 32
RIL_SIM_IO_v6 sim_io_data;
int ret_val;
int rule;
unsigned char ucs2_str[16] = { 0 };
char *ret_plmn_name = NULL;
int len = 0;
//send sim io ril to get SPN
if (!g_cell_basic_info.spn_info.spn_exist) {
memset(&sim_io_data, 0, sizeof(RIL_SIM_IO_v6));
sim_io_data.command = 176;
len += sizeof(int);
sim_io_data.fileid = 28486;
len += sizeof(int);
sim_io_data.p1 = 0;
len += sizeof(int);
sim_io_data.p2 = 0;
len += sizeof(int);
sim_io_data.p3 = 17;
len += sizeof(int);
sim_io_data.path = strdup("3F007FFF"); // USIM pathid
len += strlen(sim_io_data.path) + 1;
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SIM_IO, (void *)&sim_io_data, len);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, spn_info_request_cb, 0,
0)) != UBUS_STATUS_OK) {
CM_Log_E(get_network_name, "get_network_name, ubus_invoke RIL_REQUEST_SIM_IO failed %s\n",
ubus_strerror(ret_val));
goto EXIT;
}
//free buffer this point
free(sim_io_data.path);
}
rule = get_network_display_rule(&g_cell_basic_info);
ret_plmn_name = malloc(PLMN_NAME_SIZE);
if (!ret_plmn_name)
return NULL;
memset(ret_plmn_name, 0, PLMN_NAME_SIZE);
if (g_cell_basic_info.roaming) {
if ((rule & RULE_SHOW_SPN) == RULE_SHOW_SPN && type == NETWORK_NAME_TYPE) {
if (g_cell_basic_info.spn_info.spn_exist) {
if (g_cell_basic_info.spn_info.spn_name[0] == 0x80) {
memcpy(ucs2_str, &g_cell_basic_info.spn_info.spn_name[1], 15);
free(ret_plmn_name);
ret_plmn_name = ucs2_to_utf8(ucs2_str);
} else {
strncpy(ret_plmn_name, g_cell_basic_info.spn_info.spn_name, PLMN_NAME_SIZE - 1);
}
} else {
if (get_register_plmn() == 0)
strncpy(ret_plmn_name, g_cell_basic_info.ons_info.ons, PLMN_NAME_SIZE - 1);
else {
free(ret_plmn_name);
ret_plmn_name = NULL;
}
}
} else {
if (get_register_plmn() == 0)
strncpy(ret_plmn_name, g_cell_basic_info.ons_info.ons, PLMN_NAME_SIZE - 1);
else {
free(ret_plmn_name);
ret_plmn_name = NULL;
}
}
} else {
if ((rule & RULE_SHOW_PLMN) == RULE_SHOW_PLMN && type == ROAMING_NETWORK_NAME_TYPE) {
if (get_register_plmn() == 0)
strncpy(ret_plmn_name, g_cell_basic_info.ons_info.ons, PLMN_NAME_SIZE - 1);
else {
free(ret_plmn_name);
ret_plmn_name = NULL;
}
} else {
if (g_cell_basic_info.spn_info.spn_exist) {
if (g_cell_basic_info.spn_info.spn_name[0] == 0x80) {
memcpy(ucs2_str, &g_cell_basic_info.spn_info.spn_name[1], 15);
free(ret_plmn_name);
ret_plmn_name = ucs2_to_utf8(ucs2_str);
} else {
strncpy(ret_plmn_name, g_cell_basic_info.spn_info.spn_name, PLMN_NAME_SIZE - 1);
}
} else {
if (get_register_plmn() == 0)
strncpy(ret_plmn_name, g_cell_basic_info.ons_info.ons, PLMN_NAME_SIZE - 1);
else {
free(ret_plmn_name);
ret_plmn_name = NULL;
}
}
}
}
EXIT:
return ret_plmn_name;
}
static int set_modem_version_ril(int version)
{
struct blob_buf *b = &cm_b;
int modem_ver = version, size = 0;
int ret = UBUS_STATUS_OK;
/* send EEMOPT to enable/disable enginerring mode */
blob_buf_init(b, 0);
size = 1;
rilutil_makeRequestBlobDSMaster(b, RIL_REQUEST_SET_MODEM_VERSION, (void *)&modem_ver, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", b->head, NULL, 0, 10000);
if (ret) {
goto exit;
}
exit:
return ret;
}
struct uci_context *uci_wan_ctx_get(void)
{
if (uci_ctx_wan) {
return uci_ctx_wan;
}
uci_ctx_wan = uci_alloc_context();
if (!uci_ctx_wan) {
CM_Log_E(uci_wan_ctx_get, "uci_wan_ctx_get, malloc failed");
return NULL;
}
return uci_ctx_wan;
}
void free_wan_uci_ctx(void)
{
if (uci_ctx_wan)
uci_free_context(uci_ctx_wan);
uci_ctx_wan = NULL;
}
#if 0
static void tftinfo_parse(struct blob_attr *msg, PacketFilterInfo * tftinfo)
{
struct blob_attr *tb[TFT_MAX];
blobmsg_parse(cm_tftinfo_policy, ARRAY_SIZE(cm_tftinfo_policy), tb, blobmsg_data(msg), blobmsg_data_len(msg));
if (tb[TFT1])
tftinfo->direction = atoi(blobmsg_get_string(tb[TFT1]));
if (tb[TFT2])
tftinfo->directionPresent = atoi(blobmsg_get_string(tb[TFT2]));
if (tb[TFT3_MIN])
tftinfo->localPortRange.min = atoi(blobmsg_get_string(tb[TFT3_MIN]));
if (tb[TFT3_MAX])
tftinfo->localPortRange.max = atoi(blobmsg_get_string(tb[TFT3_MAX]));
CM_Log("tftinfo_parse, %d,%d,%d", tftinfo->direction, tftinfo->directionPresent, tftinfo->localPortRange);
if (tb[TFT4_MIN])
tftinfo->remotePortRange.min = atoi(blobmsg_get_string(tb[TFT4_MIN]));
if (tb[TFT4_MAX])
tftinfo->remotePortRange.max = atoi(blobmsg_get_string(tb[TFT4_MAX]));
if (tb[TFT5])
tftinfo->localPortRangePresent = atoi(blobmsg_get_string(tb[TFT5]));
if (tb[TFT6])
tftinfo->remotePortRangePresent = atoi(blobmsg_get_string(tb[TFT6]));
if (tb[TFT7])
tftinfo->secondaryCid = atoi(blobmsg_get_string(tb[TFT7]));
if (tb[TFT8])
tftinfo->PfIdx = atoi(blobmsg_get_string(tb[TFT8]));
if (tb[TFT9])
tftinfo->EpIdx = atoi(blobmsg_get_string(tb[TFT9]));
}
#endif
void complete_create_pdp_async_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req) {
free(req);
}
CM_Log(complete_create_pdp_async_cb, "complete_create_pdp_async_cb(%d)\n", ret);
}
int create_connection(void)
{
struct ubus_request *req = NULL;
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
req = malloc(sizeof(struct ubus_request));
if (!req) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
memset(req, 0, sizeof(struct ubus_request));
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.cm_id, "create_pdp", cm_b.head, req)) != UBUS_STATUS_OK) {
free(req);
} else {
req->complete_cb = complete_create_pdp_async_cb;
ubus_complete_request_async(cm_ctx, req);
}
EXIT:
return ret_val;
}
void complete_destroy_pdp_async_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
if (req) {
free(req);
}
CM_Log(complete_destroy_pdp_async_cb, "complete_destroy_pdp_async_cb(%d)\n", ret);
}
int destroy_connection(int connection_num, int delete_all)
{
struct ubus_request *req = NULL;
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (!req) {
ret_val = UBUS_STATUS_INVALID_ARGUMENT;
goto EXIT;
}
memset(req, 0, sizeof(struct ubus_request));
blobmsg_add_u32(&cm_b, "connectionNum", connection_num);
blobmsg_add_u32(&cm_b, "deleteall", delete_all);
CM_Log(destroy_connection1, "destroy_connection: connection num %d, deleteall %d\n", connection_num, delete_all);
if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.cm_id, "destroy_pdp", cm_b.head, req)) != UBUS_STATUS_OK) {
free(req);
} else {
req->complete_cb = complete_destroy_pdp_async_cb;
ubus_complete_request_async(cm_ctx, req);
}
EXIT:
return ret_val;
}
static int DestroyConnecion_method(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);
DisconnectInfo *p_info;
struct blob_attr *tb[CM_MAX];
p_info = malloc(sizeof(DisconnectInfo));
if (!p_info) {
return 0;
}
memset(p_info, 0, sizeof(*p_info));
blobmsg_parse(destroy_connection_policy, ARRAY_SIZE(destroy_connection_policy), tb, blob_data(msg),
blob_len(msg));
if (tb[CM_MSG1])
p_info->connectionNum = blobmsg_get_u32(tb[CM_MSG1]);
if (tb[CM_MSG2])
p_info->deleteall = blobmsg_get_u32(tb[CM_MSG2]);
CM_DestroyConnection(p_info);
return 0;
}
static int GetLinkContext_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
Link_Context *p_linkcontext = NULL;
Link_Context *tmp_linkcontext = NULL;
void *array = NULL;
void *table = NULL;
char tmp[68] = { 0 };
int ret_val = UBUS_STATUS_OK;
char *oper_name = NULL;
char *roaming_oper_name = NULL;
Apn_Info *default_apn = NULL;
int ret = 0;
//p_linkcontext = malloc(sizeof(Link_Context));
blob_buf_init(&cm_b, 0);
CheckDataCallRegisterStatus();
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_IMEI, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, sim_info_request_cb, 0,
0)) != UBUS_STATUS_OK) {
ret = 1;
goto EXIT;
}
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_IMEISV, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, sim_info_request_cb, 0,
0)) != UBUS_STATUS_OK) {
ret = 2;
goto EXIT;
}
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_IMSI, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, sim_info_request_cb, 0,
0)) != UBUS_STATUS_OK) {
ret = 3;
goto EXIT;
}
/*open the power ind*/
SetCPPowerInd(0);
/*sleep 1ms to wait or the ind report to RIL*/
usleep(1000);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SIGNAL_STRENGTH, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, rssi_info_request_cb, 0,
0)) != UBUS_STATUS_OK) {
ret = 4;
goto EXIT;
}
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_IMS_REGISTRATION_STATE, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, ims_reg_state_request_cb, 0,
0)) != UBUS_STATUS_OK) {
ret = 5;
goto EXIT;
}
SetCPPowerInd(1);
//send reply
oper_name = get_network_name(NETWORK_NAME_TYPE);
roaming_oper_name = get_network_name(ROAMING_NETWORK_NAME_TYPE);
blob_buf_init(&cm_b, 0);
blobmsg_add_u32(&cm_b, "id", 4);
table = blobmsg_open_table(&cm_b, "celluar_basic_info");
blobmsg_add_u32(&cm_b, "sys_mode", g_cell_basic_info.sys_mode);
blobmsg_add_u32(&cm_b, "data_mode", g_cell_basic_info.data_mode);
blobmsg_add_u32(&cm_b, "rssi", g_cell_basic_info.rssi);
blobmsg_add_u32(&cm_b, "ims_state", g_cell_basic_info.ims_state);
blobmsg_add_string(&cm_b, "IMEI", g_cell_basic_info.IMEI);
//blobmsg_add_string(&cm_b, "IMEI_SV", g_cell_basic_info.IMEI_SV);
blobmsg_add_string(&cm_b, "IMSI", g_cell_basic_info.IMSI);
CM_Log(GetLinkContext_method4, "GetLinkContext_method: IMEI %s, IMSI %s", g_cell_basic_info.IMEI, g_cell_basic_info.IMSI);
if (oper_name) {
blobmsg_add_string(&cm_b, "network_name", oper_name);
free(oper_name);
}
if (roaming_oper_name) {
blobmsg_add_string(&cm_b, "roaming_network_name", roaming_oper_name);
free(roaming_oper_name);
}
blobmsg_close_table(&cm_b, table);
p_linkcontext = (Link_Context *) CM_GetLinkContext();
//send reply
array = blobmsg_open_array(&cm_b, "contextlist");
tmp_linkcontext = p_linkcontext;
while (tmp_linkcontext) {
table = blobmsg_open_table(&cm_b, "list");
CM_Log(GetLinkContext_method5, "GetLinkContext_method:connection_num %d connection_status %d pdp_type %d ip_type %d create_by %d\n", tmp_linkcontext->connectionNum,
tmp_linkcontext->connectStatus, tmp_linkcontext->pdpinfo.PDP_Type, tmp_linkcontext->pdpinfo.IP_Type, tmp_linkcontext->create_by);
blobmsg_add_u32(&cm_b, "connection_num", tmp_linkcontext->connectionNum);
if ( tmp_linkcontext->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)
{
if ((tmp_linkcontext->pdpinfo.IP_Type == 0) && tmp_linkcontext->ipv4info.IPAddr)
blobmsg_add_u32(&cm_b, "connection_status", CM_CONNECT_CONSUCCESS);
else
blobmsg_add_u32(&cm_b, "connection_status", CM_CONNECT_DISCON);
}
else
blobmsg_add_u32(&cm_b, "connection_status", tmp_linkcontext->connectStatus);
blobmsg_add_u32(&cm_b, "pdp_type", tmp_linkcontext->pdpinfo.PDP_Type);
blobmsg_add_u32(&cm_b, "ip_type", tmp_linkcontext->pdpinfo.IP_Type);
blobmsg_add_u32(&cm_b, "primary_cid", tmp_linkcontext->pdpinfo.primaryCid);
blobmsg_add_u32(&cm_b, "qci", tmp_linkcontext->pdpinfo.QCI);
blobmsg_add_string(&cm_b, "apn", tmp_linkcontext->pdpinfo.APN);
blobmsg_add_string(&cm_b, "lte_apn", tmp_linkcontext->pdpinfo.LteAPN);
blobmsg_add_string(&cm_b, "usr_2g3g", tmp_linkcontext->pdpinfo.Usr2G3G);
blobmsg_add_string(&cm_b, "pswd_2g3g", tmp_linkcontext->pdpinfo.PASWD2G3G);
blobmsg_add_string(&cm_b, "authtype_2g3g", tmp_linkcontext->pdpinfo.Authtype2G3G);
blobmsg_add_string(&cm_b, "usr_4g", tmp_linkcontext->pdpinfo.Usr4G);
blobmsg_add_string(&cm_b, "pswd_4g", tmp_linkcontext->pdpinfo.PASWD4G);
blobmsg_add_string(&cm_b, "authtype_4g", tmp_linkcontext->pdpinfo.Authtype4G);
blobmsg_add_u32(&cm_b, "mtu", tmp_linkcontext->pdpinfo.mtu);
if (tmp_linkcontext->create_by == 1) {
/*Context Create By CM*/
default_apn = get_default_apninfo(g_work_apn, NULL);
if (default_apn) {
blobmsg_add_u32(&cm_b, "auto_apn", default_apn->auto_apn);
if (strlen(default_apn->mmsc) > 0)
blobmsg_add_string(&cm_b, "mmsc", default_apn->mmsc);
if (strlen(default_apn->mmsproxy) > 0)
blobmsg_add_string(&cm_b, "mmsproxy", default_apn->mmsproxy);
if (strlen(default_apn->mmsport) > 0)
blobmsg_add_string(&cm_b, "mmsport", default_apn->mmsport);
blobmsg_add_u32(&cm_b, CONN_MODE_STR, default_apn->Extra_params.autoconnect);
blobmsg_add_u32(&cm_b, DATA_ON_ROAMING_STR, default_apn->Extra_params.data_on_roaming);
}
} else {
blobmsg_add_u32(&cm_b, "auto_apn", tmp_linkcontext->pdpinfo.autoapn);
if (strlen(tmp_linkcontext->pdpinfo.mmsc) > 0)
blobmsg_add_string(&cm_b, "mmsc", tmp_linkcontext->pdpinfo.mmsc);
if (strlen(tmp_linkcontext->pdpinfo.mmsproxy) > 0)
blobmsg_add_string(&cm_b, "mmsproxy", tmp_linkcontext->pdpinfo.mmsproxy);
if (strlen(tmp_linkcontext->pdpinfo.mmsport) > 0)
blobmsg_add_string(&cm_b, "mmsport", tmp_linkcontext->pdpinfo.mmsport);
blobmsg_add_u32(&cm_b, CONN_MODE_STR, tmp_linkcontext->pdpinfo.autoconnect);
blobmsg_add_u32(&cm_b, DATA_ON_ROAMING_STR, tmp_linkcontext->pdpinfo.data_on_roaming);
}
if ((tmp_linkcontext->pdpinfo.IP_Type != 2) && tmp_linkcontext->ipv4info.IPAddr) {
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(tmp_linkcontext->ipv4info.IPAddr), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method6, "ipv4info.IPAddr is 0x%x %s", tmp_linkcontext->ipv4info.IPAddr, tmp);
blobmsg_add_string(&cm_b, "ipv4_ip", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(tmp_linkcontext->ipv4info.PrimaryDNS), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method7, "ipv4info.PrimaryDNS is 0x%x %s", tmp_linkcontext->ipv4info.PrimaryDNS, tmp);
blobmsg_add_string(&cm_b, "ipv4_dns1", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(tmp_linkcontext->ipv4info.SecondaryDNS), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method8, "ipv4info.SecondaryDNS is 0x%x %s", tmp_linkcontext->ipv4info.SecondaryDNS, tmp);
blobmsg_add_string(&cm_b, "ipv4_dns2", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(tmp_linkcontext->ipv4info.GateWay), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method9, "ipv4info.GateWay is 0x%x %s", tmp_linkcontext->ipv4info.GateWay, tmp);
blobmsg_add_string(&cm_b, "ipv4_gateway", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET, &(tmp_linkcontext->ipv4info.Mask), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method10, "ipv4info.Mask is 0x%x %s", tmp_linkcontext->ipv4info.Mask, tmp);
blobmsg_add_string(&cm_b, "ipv4_submask", tmp);
}
if ((tmp_linkcontext->pdpinfo.IP_Type != 1)
&& (tmp_linkcontext->ipv6info.IPV6Addr[0] || tmp_linkcontext->ipv6info.IPV6Addr[1]
|| tmp_linkcontext->ipv6info.IPV6Addr[2] || tmp_linkcontext->ipv6info.IPV6Addr[3])) {
char interface_name[32];
char ipaddress[INET6_ADDRSTRLEN];
int IPV6Addr[4];
snprintf(interface_name, sizeof(interface_name), "ccinet%d", tmp_linkcontext->pdpinfo.primaryCid - 1);
if (getInterfaceAddr6(interface_name, ipaddress, sizeof(ipaddress)) == 0)
{
inet_pton(AF_INET6, ipaddress, IPV6Addr);
CM_Log(GetLinkContext_method1944, "%s: get global ip [%s]", __func__, ipaddress);
tmp_linkcontext->ipv6info.IPV6Addr[0] = IPV6Addr[0];
tmp_linkcontext->ipv6info.IPV6Addr[1] = IPV6Addr[1];
}
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(tmp_linkcontext->ipv6info.IPV6Addr), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method11, "ipv6info.IPV6Addr is 0x%x 0x%x 0x%x 0x%x", tmp_linkcontext->ipv6info.IPV6Addr[0],
tmp_linkcontext->ipv6info.IPV6Addr[1], tmp_linkcontext->ipv6info.IPV6Addr[2],
tmp_linkcontext->ipv6info.IPV6Addr[3]);
CM_Log(GetLinkContext_method12, "ipv6info.IPV6Addr %s", tmp);
blobmsg_add_string(&cm_b, "ipv6_ip", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(tmp_linkcontext->ipv6info.PrimaryDNS), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method13, "ipv6info.PrimaryDNS is 0x%x 0x%x 0x%x 0x%x", tmp_linkcontext->ipv6info.PrimaryDNS[0],
tmp_linkcontext->ipv6info.PrimaryDNS[1], tmp_linkcontext->ipv6info.PrimaryDNS[2],
tmp_linkcontext->ipv6info.PrimaryDNS[3]);
CM_Log(GetLinkContext_method14, "ipv6info.PrimaryDNS %s", tmp);
blobmsg_add_string(&cm_b, "ipv6_dns1", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(tmp_linkcontext->ipv6info.SecondaryDNS), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method15, "ipv6info.SecondaryDNS is 0x%x 0x%x 0x%x 0x%x",
tmp_linkcontext->ipv6info.SecondaryDNS[0], tmp_linkcontext->ipv6info.SecondaryDNS[1],
tmp_linkcontext->ipv6info.SecondaryDNS[2], tmp_linkcontext->ipv6info.SecondaryDNS[3]);
CM_Log(GetLinkContext_method16, "ipv6info.SecondaryDNS %s", tmp);
blobmsg_add_string(&cm_b, "ipv6_dns2", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(tmp_linkcontext->ipv6info.GateWay), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method17, "ipv6info.GateWay is 0x%x 0x%x 0x%x 0x%x", tmp_linkcontext->ipv6info.SecondaryDNS[0],
tmp_linkcontext->ipv6info.SecondaryDNS[1], tmp_linkcontext->ipv6info.SecondaryDNS[2],
tmp_linkcontext->ipv6info.SecondaryDNS[3]);
CM_Log(GetLinkContext_method18, "ipv6info.GateWay %s", tmp);
blobmsg_add_string(&cm_b, "ipv6_gateway", tmp);
memset(tmp, 0, sizeof(tmp));
inet_ntop(AF_INET6, &(tmp_linkcontext->ipv6info.Mask), tmp, sizeof(tmp));
CM_Log(GetLinkContext_method19, "ipv6info.Mask is 0x%x 0x%x 0x%x 0x%x", tmp_linkcontext->ipv6info.Mask[0],
tmp_linkcontext->ipv6info.Mask[1], tmp_linkcontext->ipv6info.Mask[2],
tmp_linkcontext->ipv6info.Mask[3]);
CM_Log(GetLinkContext_method20, "ipv6info.Mask %s", tmp);
blobmsg_add_string(&cm_b, "ipv6_submask", tmp);
}
blobmsg_close_table(&cm_b, table);
tmp_linkcontext = tmp_linkcontext->next;
}
blobmsg_close_array(&cm_b, array);
EXIT:
ubus_send_reply(ctx, req, cm_b.head);
LinkContext_free(p_linkcontext);
if (ret > 0 && ret_val > 0)
CM_Log_E(GetLinkContext_method1980, "GetLinkContext_method, ret %d, ubus_invoke fail with %s\n",
ret, ubus_strerror(ret_val));
return 0;
}
int CreatePdp_method(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);
UNUSED(msg);
CM_Create_Pdp(g_work_apn);
return 0;
}
static int SetImageType_method(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);
struct blob_attr *tb[CM_MAX];
struct blob_buf *b_rsp = &cm_b;
unsigned int type = 0;
char old_value[4] = { 0 };
int ret = UBUS_STATUS_OK;
void *table = NULL;
if (blobmsg_parse(cm_set_image_policy, ARRAY_SIZE(cm_set_image_policy), tb, blob_data(msg), blob_len(msg)) != 0) {
ret = UBUS_STATUS_INVALID_ARGUMENT;
goto exit;
}
if (!tb[CM_MSG1]) {
ret = UBUS_STATUS_INVALID_ARGUMENT;
goto exit;
}
type = atoi(blobmsg_get_string(tb[CM_MSG1]));
CM_Log(SetImageType_method3, "SetImageType_method: WebUI set type %d", type);
property_get(SYS_CURRENT_CP, old_value, LTG_CP);
if (type == 0) {
ret = set_modem_version_ril(4);
} else if (type == 1) {
ret = set_modem_version_ril(3);
}
property_get(SYS_CURRENT_CP, old_value, LTG_CP);
CM_Log(SetImageType_method7, "SetImageType_method: get type %s", old_value);
exit:
blob_buf_init(b_rsp, 0);
table = blobmsg_open_table(b_rsp, "response");
if (ret == CM_OK) {
blobmsg_add_string(b_rsp, "setting_response", "OK");
} else {
blobmsg_add_string(b_rsp, "setting_response", "ERROR");
}
blobmsg_close_table(b_rsp, table);
ubus_send_reply(ctx, req, b_rsp->head);
CM_Log(SetImageType_method8, "SetImageType_method: leave %d\n", ret);
return ret;
}
static int GetImageType_method(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(msg);
UNUSED(method);
char value[4] = { '\0' };
char exist_value[4] = { '\0' };
//send reply
blob_buf_init(&cm_b, 0);
blobmsg_add_u32(&cm_b, "id", 6);
property_get(SYS_CURRENT_CP, value, "0");
property_get(SYS_EXIST_CP, exist_value, "0");
CM_Log(GetImageType_method, "GetImageType_method value %s exist value %s\n", value, exist_value);
/*LWG*/
if (atoi(value) == 4) {
blobmsg_add_u32(&cm_b, "Image_type", 0);
}
else if(atoi(value) == 3) {
blobmsg_add_u32(&cm_b, "Image_type", 1);
}
else {
if ((atoi(exist_value)>>4) & 0x0F)
blobmsg_add_u32(&cm_b, "Image_type", 0);
else if (atoi(exist_value) & 0x0F)
blobmsg_add_u32(&cm_b, "Image_type", 1);
else
blobmsg_add_u32(&cm_b, "Image_type", 1);
}
ubus_send_reply(ctx, req, cm_b.head);
return 0;
}
void CM_disable_pdplist_touci(CM_Connection_Context * ConInfo)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char *option_value = NULL;
char need_commit = 0;
/*load /etc/config/wan */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
goto EXIT_disablepdp;
}
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
if (!p) {
goto EXIT_disablepdp;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_PDP_CONFIG) == 0) {
option_value = (char *)uci_lookup_option_string(local_ctx, uci_sec, "connectionNum");
if (!option_value)
goto EXIT_disablepdp;
if (atoi(option_value) == ConInfo->pdpinfo->connectionNum) {
CM_Log(CM_disable_pdplist_touci2, "CM_disable_pdplist_touci: set option enable to 0");
//enable
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "enable";
ptr.value = "0";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//IsCreated
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
//ptr.package = WAN_PACKAGE_NAME;
//ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "IsCreated";
ptr.value = "0";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
need_commit = 1;
} else
continue;
}
}
EXIT_disablepdp:
if (need_commit == 1)
uci_commit(local_ctx, &p, false);
free_wan_uci_ctx();
}
void CM_add_pdplist_touci(CM_Connection_Context * ConInfo)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char *option_value = NULL;
char sec_name[30];
char tmp_buf[10];
char match = 0;
char need_commit = 0;
/*load /etc/config/wan */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
goto EXIT_addpdp;
}
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
if (!p) {
CM_Log_E(CM_add_pdplist_touci3, "CM_add_pdplist_touci,load wan config failed!");
goto EXIT_addpdp;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_PDP_CONFIG) == 0) {
option_value = (char *)uci_lookup_option_string(local_ctx, uci_sec, "connectionNum");
if (!option_value)
goto EXIT_addpdp;
if (atoi(option_value) == ConInfo->pdpinfo->connectionNum) {
match = 1;
option_value = (char *)uci_lookup_option_string(local_ctx, uci_sec, "enable");
if (atoi(option_value) == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
//ptr.package = WAN_PACKAGE_NAME;
//ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "enable";
ptr.value = "1";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
need_commit = 1;
}
option_value = (char *)uci_lookup_option_string(local_ctx, uci_sec, "IsCreated");
if (atoi(option_value) == 0) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
//ptr.package = WAN_PACKAGE_NAME;
//ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "IsCreated";
ptr.value = "1";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
need_commit = 1;
}
goto EXIT_addpdp;
}
}
}
if (match == 0) {
need_commit = 1;
//add pdplist to uci
//add section firstly
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
strcpy(sec_name, "pdp_config");
sprintf(tmp_buf, "%x", ConInfo->pdpinfo->connectionNum);
strcat(sec_name, tmp_buf);
ptr.section = sec_name;
ptr.flags = UCI_LOOKUP_DONE;
ptr.value = WAN_SECTION_PDP_CONFIG;
uci_set(local_ctx, &ptr);
//backup uci_section
uci_sec = ptr.s;
//add <connectionNum/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.option = "connectionNum";
ptr.value = tmp_buf;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <enable/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.option = "enable";
ptr.value = "1";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <IsCreated/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.option = "IsCreated";
ptr.value = "1";
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <PDP_name/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.option = "PDP_name";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <IP_Type/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.option = "IP_Type";
memset(tmp_buf, 0, 10);
sprintf(tmp_buf, "%d", ConInfo->pdpinfo->IP_Type);
ptr.value = tmp_buf;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <QCI/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "QCI";
memset(tmp_buf, 0, 10);
sprintf(tmp_buf, "%d", ConInfo->pdpinfo->QCI);
ptr.value = tmp_buf;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <APN/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "APN";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <LteAPN/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "LteAPN";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <Usr2G3G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "Usr2G3G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <PASWD2G3G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "PASWD2G3G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <Authtype2G3G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "Authtype2G3G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <Usr4G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "Usr4G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <PASWD4G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "PASWD4G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
//add <Authtype4G/>
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.s = uci_sec;
ptr.option = "Authtype4G";
ptr.value = ConInfo->pdpinfo->PDP_name;
ptr.flags |= UCI_LOOKUP_DONE;
uci_set(local_ctx, &ptr);
}
EXIT_addpdp:
if (need_commit == 1) {
uci_commit(local_ctx, &p, false);
}
free_wan_uci_ctx();
}
//match_type
void CM_modify_pdplist_touci(CM_Connection_Context * ConInfo, char match_type)
{
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_ptr ptr;
char *option_value = NULL;
/*load /etc/config/wan */
local_ctx = uci_wan_ctx_get();
if (!local_ctx) {
goto EXIT_modifypdp;
}
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
if (!p) {
CM_Log_E(CM_modify_pdplist_touci3, "CM_modify_pdplist_touci,load wan config failed!");
goto EXIT_modifypdp;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_PDP_CONFIG) == 0) {
option_value = (char *)uci_lookup_option_string(local_ctx, uci_sec, "connectionNum");
if (!option_value)
goto EXIT_modifypdp;
if (atoi(option_value) == ConInfo->pdpinfo->connectionNum) {
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.package = WAN_PACKAGE_NAME;
ptr.s = uci_sec;
ptr.section = WAN_SECTION_PDP_CONFIG;
ptr.flags |= UCI_LOOKUP_DONE;
CM_Log(CM_modify_pdplist_touci4, "match_type:%d, IP_Type:%d", match_type, ConInfo->pdpinfo->IP_Type);
switch (match_type) {
case IP_TYPE:
ptr.option = "IP_Type";
if (ConInfo->pdpinfo->IP_Type == 0)
ptr.value = "0";
else if (ConInfo->pdpinfo->IP_Type == 1)
ptr.value = "1";
else if (ConInfo->pdpinfo->IP_Type == 2)
ptr.value = "2";
break;
case APN:
ptr.option = "APN";
ptr.value = ConInfo->pdpinfo->APN;
break;
case LTE_APN:
ptr.option = "LteAPN";
ptr.value = ConInfo->pdpinfo->LteAPN;
break;
case USR_2G3G:
ptr.option = "Usr2G3G";
ptr.value = ConInfo->pdpinfo->Usr2G3G;
break;
case PSWD_2G3G:
ptr.option = "PASWD2G3G";
ptr.value = ConInfo->pdpinfo->PASWD2G3G;
break;
case AUTHTYPE_2G3G:
ptr.option = "Authtype2G3G";
ptr.value = ConInfo->pdpinfo->Authtype2G3G;
break;
case USR_4G:
ptr.option = "Usr4G";
ptr.value = ConInfo->pdpinfo->Usr4G;
break;
case PSWD_4G:
ptr.option = "PASWD4G";
ptr.value = ConInfo->pdpinfo->PASWD4G;
break;
case AUTHTYPE_4G:
ptr.option = "Authtype4G";
ptr.value = ConInfo->pdpinfo->Authtype4G;
break;
default:
goto EXIT_modifypdp;
}
uci_set(local_ctx, &ptr);
} else
continue;
}
}
CM_Log(CM_modify_pdplist_touci5, "before uci_commit, package addr:0x%x", p);
uci_commit(local_ctx, &p, false);
EXIT_modifypdp:
free_wan_uci_ctx();
}
static int profile_info_parse(struct blob_attr *msg, s_profile_param * info)
{
struct blob_attr *tb[_PRO_MAX];
char *str = NULL;
int ret;
if (!info) {
return CM_ERR_INVAL;
}
ret =
blobmsg_parse(profile_tabel_pol, ARRAY_SIZE(profile_tabel_pol), tb, blobmsg_data(msg),
blobmsg_data_len(msg));
if (ret != CM_OK) {
return CM_ERR_PARSE;
}
if (tb[PRO_NAME]) {
str = blobmsg_get_string(tb[PRO_NAME]);
if (str) {
CM_Log(profile_info_parse3, "profile_info_parse: profile name %s\n", str);
strncpy(info->profile_name, str, MAX_STR_LEN - 1);
}
}
if (tb[PRO_ACTION]) {
str = blobmsg_get_string(tb[PRO_ACTION]);
if (str) {
CM_Log(profile_info_parse4, "profile_info_parse: profile action %s\n", str);
info->action = atoi(str);
}
}
if (tb[CONN_NUM]) {
str = blobmsg_get_string(tb[CONN_NUM]);
if (str) {
CM_Log(profile_info_parse5, "profile_info_parse: connection num %s\n", str);
info->connection_num = atoi(str);
}
}
if (tb[APN_TYPE]) {
str = blobmsg_get_string(tb[APN_TYPE]);
if (str) {
CM_Log(profile_info_parse6, "profile_info_parse: apn type %s\n", str);
strncpy(info->type, str, MAX_STR_LEN - 1);
}
}
return CM_OK;
}
int pdp_info_parse(struct blob_attr *msg, Apn_Info * info)
{
struct blob_attr *tb[_PARAM_MAX];
char *str = NULL;
int ret;
if (!info) {
return CM_ERR_INVAL;
}
ret =
blobmsg_parse(pdpinfo_table_pol, ARRAY_SIZE(pdpinfo_table_pol), tb, blobmsg_data(msg),
blobmsg_data_len(msg));
if (ret != CM_OK) {
return CM_ERR_PARSE;
}
if (tb[CONNECTION_NUM]) {
str = blobmsg_get_string(tb[CONNECTION_NUM]);
if (str) {
CM_Log(pdp_info_parse3, "pdp_info_parse: connection number %s\n", str);
info->connection_num = atoi(str);
}
}
if (tb[ENABLE]) {
str = blobmsg_get_string(tb[ENABLE]);
if (str) {
CM_Log(pdp_info_parse4, "pdp_info_parse: enable %s\n", str);
info->enable = atoi(str);
}
}
if (tb[PDP_NAME]) {
str = blobmsg_get_string(tb[PDP_NAME]);
if (str) {
strncpy(info->pdp_name, str, MAX_STR_LEN - 1);
}
}
if (tb[IP_TYPE]) {
str = blobmsg_get_string(tb[IP_TYPE]);
if (str) {
CM_Log(pdp_info_parse6, "pdp_info_parse: ip type %s\n", str);
info->iptype = atoi(str);
}
}
if (tb[QCI]) {
str = blobmsg_get_string(tb[QCI]);
if (str) {
info->qci = atoi(str);
}
}
if (tb[APN]) {
str = blobmsg_get_string(tb[APN]);
if (str) {
CM_Log(pdp_info_parse8, "pdp_info_parse: apn %s\n", str);
strncpy(info->apn, str, MAX_STR_LEN - 1);
}
}
if (tb[LTE_APN]) {
str = blobmsg_get_string(tb[LTE_APN]);
if (str) {
CM_Log(pdp_info_parse9, "pdp_info_parse: lte apn %s\n", str);
strncpy(info->lte_apn, str, MAX_STR_LEN - 1);
}
}
if (tb[USR_2G3G]) {
str = blobmsg_get_string(tb[USR_2G3G]);
if (str) {
strncpy(info->usrname, str, MAX_STR_LEN - 1);
}
}
if (tb[PSWD_2G3G]) {
str = blobmsg_get_string(tb[PSWD_2G3G]);
if (str) {
strncpy(info->paswd, str, MAX_STR_LEN - 1);
}
}
if (tb[AUTHTYPE_2G3G]) {
str = blobmsg_get_string(tb[AUTHTYPE_2G3G]);
if (str) {
strncpy(info->authtype, str, MAX_STR_LEN - 1);
}
}
if (tb[USR_4G]) {
str = blobmsg_get_string(tb[USR_4G]);
if (str) {
strncpy(info->lte_usrname, str, MAX_STR_LEN - 1);
}
}
if (tb[PSWD_4G]) {
str = blobmsg_get_string(tb[PSWD_4G]);
if (str) {
strncpy(info->lte_paswd, str, MAX_STR_LEN - 1);
}
}
if (tb[AUTHTYPE_4G]) {
str = blobmsg_get_string(tb[AUTHTYPE_4G]);
if (str) {
strncpy(info->lte_authtype, str, MAX_STR_LEN - 1);
}
}
if (tb[TYPE]) {
str = blobmsg_get_string(tb[TYPE]);
if (str) {
strncpy(info->type, str, MAX_STR_LEN - 1);
}
}
if (tb[AUTO_APN]) {
str = blobmsg_get_string(tb[AUTO_APN]);
if (str) {
info->auto_apn = atoi(str);
}
}
if (tb[CONNECT_MODE]) {
str = blobmsg_get_string(tb[CONNECT_MODE]);
if (str) {
info->Extra_params.autoconnect = atoi(str);
}
}
if (tb[LTE_DEFAULT]) {
str = blobmsg_get_string(tb[LTE_DEFAULT]);
if (str) {
CM_Log(pdp_info_parse19, "pdp_info_parse: lte default %s\n", str);
info->Extra_params.lte_default = atoi(str);
}
}
if (tb[DATA_ON_ROAMING]) {
str = blobmsg_get_string(tb[DATA_ON_ROAMING]);
if (str) {
CM_Log(pdp_info_parse20, "pdp_info_parse: data on roaming %s\n", str);
info->Extra_params.data_on_roaming = atoi(str);
}
}
if (tb[MTU]) {
str = blobmsg_get_string(tb[MTU]);
if (str) {
CM_Log(pdp_info_parse21, "pdp_info_parse: mtu %s\n", str);
info->mtu = atoi(str);
}
}
return CM_OK;
}
/***********************************************************************
ubus method, config PDP
request:
a. add profile
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>1</action>
</profile>
b. delete profile
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>2</action>
</profile>
c. switch profile
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>3</action>
</profile>
d. add pdp
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>4</action>
<connection_num/>
<type/><!-- apn type -->
</profile>
<pdp_info>
<connection_num/>
<type/>
<auto_apn/>
<connect_mode/>
<lte_default/>
<data_on_roaming/>
<pdp_name/>
<enable/>
<ip_type/>
<apn/>
<lte_apn/>
<usr_2g3g/>
<pswd_2g3g/>
<authtype_2g3g/>
<usr_4g/>
<pswd_4g/>
<authtype_4g/>
<mtu/>
</pdp_info>
e. delete pdp
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>5</action>
<connection_num/>
<type/><!-- apn type -->
</profile>
f. edit pdp
<profile>
<profile_name/><!-- unique profile name, can not be NULL -->
<action>6</action>
<connection_num/>
<type/><!-- apn type -->
</profile>
<pdp_info>
<connection_num/>
<type/>
<auto_apn/>
<connect_mode/>
<lte_default/>
<data_on_roaming/>
<pdp_name/>
<enable/>
<ip_type/>
<apn/>
<lte_apn/>
<usr_2g3g/>
<pswd_2g3g/>
<authtype_2g3g/>
<usr_4g/>
<pswd_4g/>
<authtype_4g/>
<mtu/>
</pdp_info>
response:
<response>
<response_status>OK/ERROR</response_status>
</reponse>
*************************************************************************/
int configs_handler(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(method);
UNUSED(obj);
s_profile_param profile_param;
int ret = CM_OK;
struct blob_attr *tb[_TABLE_MAX];
void *table = NULL;
memset(&profile_param, 0, sizeof(s_profile_param));
ret = blobmsg_parse(configs_handler_pol, ARRAY_SIZE(configs_handler_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[PROFILE]) {
ret = CM_ERR_INVAL;
goto END;
}
ret = profile_info_parse(tb[PROFILE], &profile_param);
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
switch (profile_param.action) {
case ADD_PROFILE:
ret = add_profile(&profile_param);
break;
case DELETE_PROFILE:
ret = delete_profile(&profile_param);
break;
case SWITCH_PROFILE:
ret = switch_profile(&profile_param);
break;
case ADD_PDP:
if (!(tb[PDPINFO])) {
ret = CM_ERR_INVAL;
goto END;
}
ret = add_pdp(tb[PDPINFO], &profile_param);
break;
case DELETE_PDP:
ret = delete_pdp(&profile_param);
break;
case EDIT_PDP:
if (!(tb[PDPINFO])) {
ret = CM_ERR_INVAL;
goto END;
}
ret = edit_pdp(tb[PDPINFO], &profile_param);
break;
default:
break;
}
END:
blob_buf_init(&cm_b, 0);
table = blobmsg_open_table(&cm_b, "response");
if (ret == CM_OK) {
blobmsg_add_string(&cm_b, "response_status", "OK");
} else {
blobmsg_add_string(&cm_b, "response_status", "ERROR");
}
blobmsg_close_table(&cm_b, table);
ubus_send_reply(ctx, req, cm_b.head);
CM_Log(configs_handler6, "configs_handler: leave with ret %d\n", ret);
return 0;
}
/***********************************************************************
ubus method, get auto_switch value
request:
<auto-switch>
<enable/><!--1 enbale, 0-disable -->
</auto-switch>
*************************************************************************/
int get_auto_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(msg);
UNUSED(method);
int ret = CM_OK;
struct uci_context *local_ctx = NULL;
const char * value = NULL;
int val = 0, single_version = 0;
char version[4] = { 0 };
/*load /etc/config/wan */
local_ctx = uci_alloc_context();
if (!local_ctx) {
ret = CM_ERR_MEM;
goto END;
}
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_element *e = NULL;
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
if(!p)
{
ret = CM_ERR_INVAL;
goto END;
}
uci_foreach_element(&p->sections, e)
{
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_AUTO_SWITCH) == 0)
{
value = uci_lookup_option_string(local_ctx, uci_sec, "enable");
break;
}
}
property_get(SYS_CURRENT_CP, version, "0");
if (!strcmp(version, LTG_CP) || !strcmp(version, LWG_CP))
single_version = 0;
else
single_version = 1;
if(!value)
{
uci_add_section(local_ctx, p, WAN_SECTION_AUTO_SWITCH, &uci_sec);
if(!uci_sec)
{
ret = CM_ERR_INVAL;
goto END;
}
struct uci_ptr ptr;
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "enable";
ptr.value = "0";
uci_set(local_ctx, &ptr);
uci_commit(local_ctx, &p, false);
}
else
{
val = (atoi(value) == 1)?1:0;
}
if (single_version)
val = 2;
blob_buf_init(&cm_b, 0);
blobmsg_add_u32(&cm_b, "enable", val);
ubus_send_reply(ctx, req, cm_b.head);
END:
uci_free_context(local_ctx);
return ret;
}
static int get_eng_mode_uci()
{
struct uci_context *local_ctx;
char *option_value = NULL;
int ret = 0;
/*get /etc/config/wan UCI context */
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
goto exit;
}
option_value =
uci_get_option(local_ctx, WAN_PACKAGE_NAME, WAN_SECTION_TYPE_ENG_MODE, WAN_SECTION_NAME_ENG_MODE,
WAN_ENG_MODE_OPTION);
if (option_value) {
ret = atoi(option_value);
}
exit:
return ret;
}
static void blobmsg_lte_svc_info(struct blob_buf *b, s_cellular_info *info)
{
void *t, *mode_t;
t = blobmsg_open_table(b, "eng");
mode_t = blobmsg_open_table(b, "lte");
blobmsg_add_u32(b, "mcc", info->lte_info.params.mcc);
blobmsg_add_u32(b, "mnc_len", info->lte_info.params.lenOfMnc);
blobmsg_add_u32(b, "mnc", info->lte_info.params.mnc);
blobmsg_add_u32(b, "tac", info->lte_info.params.tac);
blobmsg_add_u32(b, "phy_cell_id", info->lte_info.params.phyCellId);
blobmsg_add_u32(b, "cell_id", info->lte_info.params.cellId);
blobmsg_add_u32(b, "dl_euarfcn", info->lte_info.params.dlEuArfcn);
blobmsg_add_u32(b, "ul_euarfcn", info->lte_info.params.ulEuArfcn);
blobmsg_add_u32(b, "band", info->lte_info.params.band);
blobmsg_add_u32(b, "dl_bandwidth", info->lte_info.params.dlBandwidth);
blobmsg_add_u32(b, "transmission_mode", info->lte_info.params.transMode);
blobmsg_add_u32(b, "rsrp", info->lte_info.meas.rsrp);
blobmsg_add_u32(b, "rsrq", info->lte_info.meas.rsrq);
blobmsg_add_u32(b, "sinr", info->lte_info.meas.sinr);
blobmsg_add_u32(b, "main_rsrp", info->lte_info.meas.mainRsrp);
blobmsg_add_u32(b, "diversity_rsrp", info->lte_info.meas.diversityRsrp);
blobmsg_add_u32(b, "main_rsrq", info->lte_info.meas.mainRsrq);
blobmsg_add_u32(b, "diversity_rsrq", info->lte_info.meas.diversityRsrq);
blobmsg_add_u32(b, "rssi", info->lte_info.meas.rssi);
blobmsg_add_u32(b, "cqi", info->lte_info.meas.cqi);
blobmsg_add_u32(b, "dl_bler", info->lte_info.meas.dlBler);
blobmsg_add_u32(b, "ul_bler", info->lte_info.meas.ulBler);
blobmsg_add_u32(b, "dl_throughput", info->lte_info.meas.dlThroughPut);
blobmsg_add_u32(b, "dl_peak_throughput", info->lte_info.meas.dlPeakThroughPut);
blobmsg_add_u32(b, "ul_throughput", info->lte_info.meas.ulThroughPut);
blobmsg_add_u32(b, "ul_peak_throughput", info->lte_info.meas.ulPeakThroughPut);
blobmsg_add_u32(b, "tx_power", info->lte_info.meas.currPuschTxPower);
blobmsg_close_table(b, mode_t);
blobmsg_close_table(b, t);
}
static void blobmsg_umts_svc_info(struct blob_buf *b, s_cellular_info *info)
{
void *t, *mode_t;
t = blobmsg_open_table(b, "eng");
mode_t = blobmsg_open_table(b, "umts");
blobmsg_add_u32(b, "mcc", info->umts_info.sCellParam.mcc);
blobmsg_add_u32(b, "mnc_len", info->umts_info.sCellParam.lenOfMnc);
blobmsg_add_u32(b, "mnc", info->umts_info.sCellParam.mnc);
blobmsg_add_u32(b, "rac", info->umts_info.sCellParam.rac);
blobmsg_add_u32(b, "lac", info->umts_info.sCellParam.lac);
blobmsg_add_u32(b, "cell_id", info->umts_info.sCellParam.ci);
blobmsg_add_u32(b, "arfcn", info->umts_info.sCellParam.arfcn);
blobmsg_add_u32(b, "rscp", info->umts_info.sCellMeas.rscp);
blobmsg_add_u32(b, "rssi", info->umts_info.sCellMeas.utraRssi);
blobmsg_add_u32(b, "tx_power", info->umts_info.sCellMeas.txPower);
blobmsg_close_table(b, mode_t);
blobmsg_close_table(b, t);
}
#ifdef EEMOPT_QUERY_MODE
static int set_eng_mode_ril(int mode)
{
struct blob_buf *b = &cm_b;
int eemopt = mode, size = 0;
int ret = UBUS_STATUS_OK;
/* send EEMOPT to enable/disable enginerring mode */
blob_buf_init(b, 0);
size = 1;
rilutil_makeRequestBlobDSMaster(b, RIL_REQUEST_SET_EEMOPT, (void *)&eemopt, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", b->head, NULL, 0, 5000);
if (ret) {
goto exit;
}
exit:
return ret;
}
#endif
static void force_eng_info_timeout()
{
uloop_timeout_set(&cm_query_enginfo_timeout, 0);
}
static void cancel_eng_info_timeout()
{
uloop_timeout_cancel(&cm_query_enginfo_timeout);
}
static int query_eng_info_ril()
{
struct blob_buf *b = &cm_b;
int ret = UBUS_STATUS_OK;
/* send EEMGINGO request */
blob_buf_init(b, 0);
rilutil_makeRequestBlobDSMaster(b, RIL_REQUEST_GET_EEMGINFO, NULL, 0);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", b->head, NULL, 0, 5000);
if (ret) {
goto exit;
}
exit:
return ret;
}
static int match_auto_apn(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
Mnc_Apn *get_Apn = NULL;
struct blob_buf *b_rsp = &cm_b;
struct blob_attr *tb[E_MCC_MNC_MAX];
void *table;
int ret = UBUS_STATUS_OK;
ret =
blobmsg_parse(mcc_mnc_pol, ARRAY_SIZE(mcc_mnc_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto exit;
}
if (!tb[E_MCC] || !tb[E_MNC] ) {
CM_Log_E(match_auto_apn1, "match_auto_apn: no NCC or MNC\n");
ret = CM_ERR_INVAL;
goto exit;
}
get_Apn = malloc(sizeof(Mnc_Apn));
if (!get_Apn) {
CM_Log_E(match_auto_apn2, "match_auto_apn: malloc size %d failed\n", sizeof(Mnc_Apn));
return UBUS_STATUS_UNKNOWN_ERROR;
}
memset(get_Apn, 0, sizeof(Mnc_Apn));
fillApnInfo(blobmsg_get_string(tb[E_MCC]), blobmsg_get_string(tb[E_MNC]), get_Apn);
exit:
ret = blob_buf_init(b_rsp, 0);
table = blobmsg_open_table(b_rsp, "response");
if (ret != UBUS_STATUS_OK) {
blobmsg_add_string(b_rsp, "response_status", "ERROR");
} else {
blobmsg_add_string(b_rsp, "response_status", "OK");
}
blobmsg_close_table(b_rsp, table);
ubus_send_reply(ctx, req, b_rsp->head);
return ret;
}
static int get_eng_info(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
s_cellular_info *info = &g_cell_basic_info;
struct blob_buf *b_rsp = &cm_b;
int mode, net_mode;
int ret = UBUS_STATUS_OK;
char sys_mode[16] = { 0 };
void *table;
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
blob_buf_init(b_rsp, 0);
mode = get_eng_mode_uci();
if (!mode) {
ret = UBUS_STATUS_NO_DATA;
goto exit;
}
/* prepare Engneering param to blob */
if (info->sys_mode == E_NO_SERVICE) {
ret = UBUS_STATUS_NO_DATA;
goto exit;
} else if (info->sys_mode == E_LTE) {
strcpy(sys_mode, "lte");
net_mode = MODE_LTE;
} else {
if ((info->data_mode == RADIO_TECH_GPRS) || (info->data_mode == RADIO_TECH_EDGE) \
|| (info->data_mode == RADIO_TECH_GSM)) {
strcpy(sys_mode, "gsm");
net_mode = MODE_GSM;
} else if (info->data_mode == RADIO_TECH_TD_SCDMA) {
strcpy(sys_mode, "td");
net_mode = MODE_TD;
} else {
strcpy(sys_mode, "umts");
net_mode = MODE_UMTS;
}
}
switch (net_mode) {
case MODE_LTE:
blobmsg_lte_svc_info(b_rsp, info);
/* force to refresh the data */
force_eng_info_timeout();
break;
case MODE_UMTS:
blobmsg_umts_svc_info(b_rsp, info);
/* force to refresh the data */
force_eng_info_timeout();
break;
case MODE_TD:
case MODE_GSM:
default:
break;
}
exit:
table = blobmsg_open_table(b_rsp, "response");
if (ret != UBUS_STATUS_OK) {
blobmsg_add_string(b_rsp, "response_status", "ERROR");
} else {
blobmsg_add_string(b_rsp, "response_status", "OK");
}
blobmsg_close_table(b_rsp, table);
ubus_send_reply(ctx, req, b_rsp->head);
return ret;
}
static void eng_mode_init()
{
int mode;
mode = get_eng_mode_uci();
if (mode) {
uloop_timeout_set(&cm_query_enginfo_timeout, 0);
} else {
uloop_timeout_cancel(&cm_query_enginfo_timeout);
}
}
static int set_eng_mode(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
struct uci_context *local_ctx = NULL;
struct blob_buf *b_rsp = &cm_b;
struct blob_attr *tb[_ENG_MODE_MAX];
char * value = NULL;
void *table = NULL;
int ret = CM_OK, val = 0;
UNUSED(obj);
UNUSED(method);
ret =
blobmsg_parse(eng_mode_pol, ARRAY_SIZE(eng_mode_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto exit;
}
if (!tb[ENG_MODE]) {
ret = CM_ERR_INVAL;
goto exit;
}
value = blobmsg_get_string(tb[ENG_MODE]);
val = atoi(value);
if(val != 0 && val != 1) {
CM_Log_E(set_eng_mode2, "set_eng_mode: invalid eng-mode value %d \n", val);
val = 0;
}
/*load /etc/config/wan */
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
ret = CM_ERR_MEM;
goto exit;
}
ret = uci_set_option(local_ctx, WAN_PACKAGE_NAME, WAN_SECTION_TYPE_ENG_MODE, WAN_SECTION_NAME_ENG_MODE, WAN_ENG_MODE_OPTION, value);
CM_Log(set_eng_mode4, "set_eng_mode: eng mode:%d \n", val);
if (val) {
force_eng_info_timeout();
} else {
cancel_eng_info_timeout();
}
exit:
blob_buf_init(b_rsp, 0);
table = blobmsg_open_table(b_rsp, "response");
if (ret == CM_OK) {
blobmsg_add_string(b_rsp, "setting_response", "OK");
} else {
blobmsg_add_string(b_rsp, "setting_response", "ERROR");
}
blobmsg_close_table(b_rsp, table);
ubus_send_reply(ctx, req, b_rsp->head);
CM_Log(set_eng_mode5, "set_eng_mode: leave %d\n", ret);
return ret;
}
void cm_query_enginfo_timeout_cb(struct uloop_timeout *timeout)
{
/* enhance mode to get eng info */
#ifdef EEMOPT_QUERY_MODE
set_eng_mode_ril(1);
#endif
query_eng_info_ril();
#ifdef EEMOPT_QUERY_MODE
set_eng_mode_ril(0);
#endif
uloop_timeout_set(timeout, QUERY_ENG_INFO_TIMEOUT);
CM_Log(cm_query_enginfo_timeout_cb1, "cm_query_enginfo_timeout_cb: leave\n");
return;
}
int set_auto_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(ctx);
UNUSED(req);
UNUSED(method);
int ret = CM_OK;
struct uci_context *local_ctx = NULL;
struct blob_attr *tb[_CONN_SWITCH_MAX];
int val = 0;
ret =
blobmsg_parse(auto_switch_pol, ARRAY_SIZE(auto_switch_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[CONNECT_SWITCH]) {
ret = CM_ERR_INVAL;
goto END;
}
val = atoi(blobmsg_get_string(tb[CONNECT_SWITCH]));
if(val !=0 && val!=1)
{
CM_Log_E(set_auto_switch2, "set_auto_switch: invalid auto-switch value %d \n", val);
val =0;
}
/*load /etc/config/wan */
local_ctx = uci_alloc_context();
if (!local_ctx) {
ret = CM_ERR_MEM;
goto END;
}
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
struct uci_element *e = NULL;
struct uci_ptr ptr;
const char * value = NULL;
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
if(!p)
{
ret = CM_ERR_INVAL;
goto END;
}
uci_foreach_element(&p->sections, e)
{
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_AUTO_SWITCH) == 0)
{
value = uci_lookup_option_string(local_ctx, uci_sec, "enable");
break;
}
}
if(!value)
{
uci_add_section(local_ctx, p, WAN_SECTION_AUTO_SWITCH, &uci_sec);
if(!uci_sec)
{
ret = CM_ERR_INVAL;
goto END;
}
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "enable";
ptr.value = (val==1)?"1":"0";
uci_set(local_ctx, &ptr);
uci_commit(local_ctx, &p, false);
}
else
{
if(uci_sec)
{
memset(&ptr, 0, sizeof(struct uci_ptr));
ptr.p = p;
ptr.s = uci_sec;
ptr.option = "enable";
ptr.value = (val==1)?"1":"0";
uci_set(local_ctx, &ptr);
uci_commit(local_ctx, &p, false);
}
}
CM_Log_E(set_auto_switch7, "set_auto_switch: auto_switch enable:%d \n", val);
if (val) {
/*here force to switch if needed*/
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_IMSI, NULL, 0);
if ((ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, sim_info_request_cb, 0, 0)) != UBUS_STATUS_OK) {
CM_Log_E(set_auto_switch8, "set_auto_switch, ubus_invoke RIL_REQUEST_GET_IMSI failed %s\n", ubus_strerror(ret));
goto END;
}
}
END:
uci_free_context(local_ctx);
return ret;
}
/***********************************************************************
ubus method, enable/disable PDP
request:
<connect_switch>
<proto/><!-- cellular/disabled always take effect -->
<dial_switch/><!--cellular/disabled only take effect in this boot -->
</connect_switch>
response:
<response>
<response_status>OK/ERROR</response_status>
</reponse>
*************************************************************************/
int connection_switch(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
int ret = CM_OK;
struct blob_attr *tb[_CONN_SWITCH_MAX];
struct uci_context *local_ctx = NULL;
void *table = NULL;
char *value = NULL;
char *proto_value = NULL;
char *dial_value = NULL;
int need_commit = 0;
enum e_proto_switch proto_switch = 0;
enum e_dial_switch dial_switch = 0;
ret =
blobmsg_parse(connection_switch_pol, ARRAY_SIZE(connection_switch_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[CONNECT_SWITCH]) {
ret = CM_ERR_INVAL;
goto END;
}
ret = blobmsg_parse(connection_switch_table_pol, ARRAY_SIZE(connection_switch_table_pol), tb,
blobmsg_data(tb[CONNECT_SWITCH]), blobmsg_data_len(tb[CONNECT_SWITCH]));
if (ret != CM_OK) {
goto END;
}
if (!tb[PROTO]) {
ret = CM_ERR_INVAL;
goto END;
}
if (!tb[DIAL_SWITCH]) {
ret = CM_ERR_INVAL;
goto END;
}
proto_value = blobmsg_get_string(tb[PROTO]);
dial_value = blobmsg_get_string(tb[DIAL_SWITCH]);
CM_Log(connection_switch5, "connection_switch: post proto [%s] dial_switch [%s] \n", proto_value ? proto_value: "NULL", dial_value ? dial_value:"NULL");
/*load /etc/config/wan */
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
ret = CM_ERR_MEM;
goto END;
}
value = uci_get_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_PROTO);
if (!value) {
ret = CM_ERR_INVAL;
goto END;
}
CM_Log(connection_switch8, "connection_switch: uci proto %s \n", value);
if (!strcmp(value, "cellular")) {
if (!strcmp(proto_value, "cellular")) {
// proto not changed
proto_switch = PROTO_CELLULAR_NO_CHANGE;
} else if (!strcmp(proto_value, "disabled")) {
// proto change from celluar to disabled
proto_switch = PROTO_TO_DISABLED;
} else {
proto_switch = PROTO_ERROR;
}
} else if (!strcmp(value, "disabled")) {
if (!strcmp(proto_value, "disabled")) {
// proto not changed
proto_switch = PROTO_DISABLED_NO_CHANGE;
} else if (!strcmp(proto_value, "cellular")) {
// proto change from disabled to cellular
proto_switch = PROTO_TO_CELLULAR;
} else {
proto_switch = PROTO_ERROR;
}
}
value =
uci_get_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_DIAL_SWITCH);
if (!value) {
ret = CM_ERR_INVAL;
goto END;
}
CM_Log(connection_switch10, "connection_switch: uci dial_switch %s \n", value);
if (!strcmp(value, "cellular")) {
if (!strcmp(dial_value, "cellular")) {
// dial not changed
dial_switch = DIAL_CELLULAR_NO_CHANGE;
} else if (!strcmp(dial_value, "disabled")) {
// dial change from celluar to disabled
dial_switch = DIAL_TO_DISABLED;
} else {
dial_switch = DIAL_ERROR;
}
} else if (!strcmp(value, "disabled")) {
if (!strcmp(dial_value, "disabled")) {
// dial not changed
dial_switch = DIAL_DISABLED_NO_CHANGE;
} else if (!strcmp(dial_value, "cellular")) {
// dial change from disabled to cellular
dial_switch = DIAL_TO_CELLULAR;
} else {
dial_switch = DIAL_ERROR;
}
}
switch (proto_switch) {
case PROTO_TO_DISABLED:
ret = destroy_connection(0, 1);
if (ret != CM_OK) {
goto END;
}
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_PROTO,
"disabled");
if (ret != UCI_OK) {;
goto END;
}
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_DIAL_SWITCH,
"disabled");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
break;
case PROTO_TO_CELLULAR:
ret = create_connection();
if (ret != CM_OK) {
goto END;
}
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_PROTO,
"cellular");
if (ret != UCI_OK) {
goto END;
}
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N, OPT_DIAL_SWITCH,
"cellular");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
break;
case PROTO_CELLULAR_NO_CHANGE:
switch (dial_switch) {
case DIAL_TO_DISABLED:
ret = destroy_connection(0, 1);
if (ret != CM_OK) {
goto END;
}
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N,
OPT_DIAL_SWITCH, "disabled");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
break;
case DIAL_TO_CELLULAR:
ret = create_connection();
if (ret != CM_OK) {
goto END;
}
ret = uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N,
OPT_DIAL_SWITCH, "cellular");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
break;
default:
break;
}
break;
case PROTO_DISABLED_NO_CHANGE:
switch (dial_switch) {
case DIAL_TO_DISABLED:
ret =
uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N,
OPT_DIAL_SWITCH, "disabled");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
break;
case DIAL_TO_CELLULAR:
ret = uci_set_option(local_ctx, WAN_PACKAGE_NAME, SEC_CONNECT_SWITCH_T, SEC_CONNECT_SWITCH_N,
OPT_DIAL_SWITCH, "cellular");
if (ret != UCI_OK) {
goto END;
}
need_commit = 1;
default:
break;
}
break;
default:
break;
}
END:
#if 1
if (need_commit) {
ret = uci_commit_package(local_ctx, WAN_PACKAGE_NAME);
}
#endif
blob_buf_init(&cm_b, 0);
table = blobmsg_open_table(&cm_b, "response");
if (ret == CM_OK) {
blobmsg_add_string(&cm_b, "response_status", "OK");
} else {
blobmsg_add_string(&cm_b, "response_status", "ERROR");
}
blobmsg_close_table(&cm_b, table);
ubus_send_reply(ctx, req, cm_b.head);
free_wan_uci_ctx();
CM_Log(connection_switch24, "connection_switch: leave ret %d\n", ret);
return 0;
}
static void prop_set_ril_default_cid(void)
{
#ifdef CONFIG_ZGDCONT_MULTI_PDP
Apn_Info *default_apn = NULL;
char tmp[4] = { 0 };
default_apn = get_default_apninfo(g_work_apn, NULL);
if (default_apn && (default_apn->auto_apn || default_apn->config_by == PDP_CONFIG_ZGDCONT || default_apn->cid == CM_DEFAULT_ATTACH_CID))
{
snprintf(tmp, sizeof(tmp) - 1, "%d", CM_DEFAULT_ATTACH_CID);
property_set(PROP_DEFINED_CID, tmp);
}
#endif
return;
}
/***********************************************************************
ubus method, other modules modify the default UCI file, can call this method to reload
the PDP configuration and perform connection handler for those new PDP parameters.
*************************************************************************/
int connection_reload(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);
UNUSED(msg);
int ret = CM_OK;
free_wan_uci_ctx();
if (g_work_apn)
memset(g_work_apn, 0, sizeof (*g_work_apn));
ret = update_work_apn(IMSI_APN);
if (ret != CM_OK) {
goto END;
}
ret = CM_update_redialinterval(g_cell_basic_info.IMSI);
if (ret != CM_OK) {
goto END;
}
#ifdef CONFIG_ZGDCONT_SAVE_PDP
init_zgdcont_default_pdp_info();
#endif
property_set(PROP_DEFINED_CID, "-1");
prop_set_ril_default_cid();
ret = connection_handler(g_work_apn);
if (ret != CM_OK) {
goto END;
}
END:
return ret;
}
/*************************************************************
ubus method, for other modules to get the APN info
request:
<type/><!-- apn type like "default", "ims"-->
reponse:
<apn_info>
<type> <!-- same name as input type -->
<apn/>
<lte_apn/>
<usrname/>
<paswd/>
<authtype/>
<lte_usrname/>
<lte_paswd/>
<lte_authtype/>
<ip_type/>
</type>
</apn_info>
<response>
<response_status>OK/ERROR</response_status>
</reponse>
**************************************************************/
int get_apn_info(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
int ret = CM_OK;
struct blob_attr *tb[_APN_TYPE_MAX];
char *apn_type = NULL;
Apn_Info apn_info;
void *table = NULL;
memset(&apn_info, 0, sizeof(Apn_Info));
blob_buf_init(&cm_b, 0);
ret = blobmsg_parse(get_apn_info_pol, ARRAY_SIZE(get_apn_info_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[APN_TYPE_QUERY]) {
ret = CM_ERR_INVAL;
goto END;
}
apn_type = blobmsg_get_string(tb[APN_TYPE_QUERY]);
CM_Log(get_apn_info3, "get_apn_info: apn type %s\n", apn_type);
ret = get_apn_info_by_type(apn_type, &apn_info);
if (ret != CM_OK) {
ret = CM_ERR_INVAL;
goto END;
}
table = blobmsg_open_table(&cm_b, "apn_info");
blobmsg_add_string(&cm_b, "apn", apn_info.apn);
blobmsg_add_string(&cm_b, "lte_apn", apn_info.lte_apn);
blobmsg_add_string(&cm_b, "usrname", apn_info.usrname);
blobmsg_add_string(&cm_b, "paswd", apn_info.paswd);
blobmsg_add_string(&cm_b, "authtype", apn_info.authtype);
blobmsg_add_string(&cm_b, "lte_usrname", apn_info.lte_usrname);
blobmsg_add_string(&cm_b, "lte_paswd", apn_info.lte_paswd);
blobmsg_add_string(&cm_b, "lte_authtype", apn_info.lte_authtype);
blobmsg_add_u32(&cm_b, "ip_type", apn_info.iptype);
blobmsg_close_table(&cm_b, table);
END:
table = blobmsg_open_table(&cm_b, "response");
if (ret == CM_OK) {
blobmsg_add_string(&cm_b, "response_status", "OK");
} else {
blobmsg_add_string(&cm_b, "response_status", "ERROR");
}
blobmsg_close_table(&cm_b, table);
ubus_send_reply(ctx, req, cm_b.head);
CM_Log(get_apn_info5, "get_apn_info: leave\n");
return 0;
}
/*************************************************************
ubus method to get the auto APN info
request:
<type/><!-- apn type like "default", "ims"..., if type="all", will return all types info-->
reponse:
<type> <!-- same name as input type -->
<Item index="0">
<Item0>
<apn/>
<lte_apn/>
<usrname/>
<paswd/>
<authtype/>
<lte_usrname/>
<lte_paswd/>
<lte_authtype/>
<ip_type/>
</Item0>
</Item>
...
</type>
<response>
<response_status>OK/ERROR</response_status>
</reponse>
**************************************************************/
static int get_auto_apn_info(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
int ret = CM_OK;
struct blob_attr *tb[_APN_TYPE_MAX];
char *apn_type = NULL;
Apn_Info *apn_info;
int apn_num = 0, index = 0, i;
void *table = NULL, *array = NULL;
char item_buf[16] = { '\0' };
Mnc_Apn *mnc_apn = NULL;
apn_info = malloc(MAX_APN_NUM * sizeof(Apn_Info));
if(!apn_info){
ret = CM_ERR_MEM;
goto END;
}
memset(apn_info, 0, MAX_APN_NUM * sizeof(Apn_Info));
blob_buf_init(&cm_b, 0);
ret = blobmsg_parse(get_apn_info_pol, ARRAY_SIZE(get_apn_info_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[APN_TYPE_QUERY]) {
ret = CM_ERR_INVAL;
goto END;
}
apn_type = blobmsg_get_string(tb[APN_TYPE_QUERY]);
if (!strcmp(apn_type, "all")) {
mnc_apn = get_mnc_apn_info();
if (!mnc_apn) {
ret = CM_ERR_INVAL;
goto END;
}
for (i = 0; i < MAX_APN_NUM; i++) {
if (strlen(mnc_apn->apn_info_list[i].type) && strlen(mnc_apn->apn_info_list[i].apn)) {
array = blobmsg_open_array(&cm_b, mnc_apn->apn_info_list[i].type);
sprintf(item_buf, "Item0");
table = blobmsg_open_table(&cm_b, item_buf);
blobmsg_add_string(&cm_b, APN_TYPE_STR, mnc_apn->apn_info_list[i].type);
blobmsg_add_u32(&cm_b, CONN_MODE_STR, mnc_apn->apn_info_list[i].Extra_params.autoconnect);
blobmsg_add_u32(&cm_b, LTE_DEFAULT_STR, mnc_apn->apn_info_list[i].Extra_params.lte_default);
blobmsg_add_u32(&cm_b, DATA_ON_ROAMING_STR, mnc_apn->apn_info_list[i].Extra_params.data_on_roaming);
blobmsg_add_string(&cm_b, PDP_NAME_STR, mnc_apn->apn_info_list[i].pdp_name);
blobmsg_add_u32(&cm_b, IP_TYPE_STR, mnc_apn->apn_info_list[i].iptype);
blobmsg_add_string(&cm_b, APN_STR,mnc_apn->apn_info_list[i].apn);
blobmsg_add_string(&cm_b, LTE_APN_STR, mnc_apn->apn_info_list[i].lte_apn);
blobmsg_add_string(&cm_b, USR_2G3G_STR, mnc_apn->apn_info_list[i].usrname);
blobmsg_add_string(&cm_b, PSWD_2G3G_STR,mnc_apn->apn_info_list[i].paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_2G3G_STR, mnc_apn->apn_info_list[i].authtype);
blobmsg_add_string(&cm_b, USR_4G_STR, mnc_apn->apn_info_list[i].lte_usrname);
blobmsg_add_string(&cm_b, PSWD_4G_STR, mnc_apn->apn_info_list[i].lte_paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_4G_STR, mnc_apn->apn_info_list[i].lte_authtype);
blobmsg_add_u32(&cm_b, NET_MTU_STR, mnc_apn->apn_info_list[i].mtu);
blobmsg_add_string(&cm_b, MMSC_STR, mnc_apn->apn_info_list[i].mmsc);
blobmsg_add_string(&cm_b, MMS_PROXY_STR, mnc_apn->apn_info_list[i].mmsproxy);
blobmsg_add_string(&cm_b, MMS_PORT_STR, mnc_apn->apn_info_list[i].mmsport);
blobmsg_close_table(&cm_b, table);
blobmsg_close_array(&cm_b, array);
}
}
goto END;
}
mnc_apn = get_mnc_apn_info();
CM_Log(get_auto_apn_info4, "get_auto_apn_info: apn type %s\n", apn_type);
ret = get_auto_apn_info_by_type(apn_type, apn_info, &apn_num);
if (ret != CM_OK) {
ret = CM_ERR_INVAL;
goto END;
}
array = blobmsg_open_array(&cm_b, apn_type);
for (index = 0; index < apn_num; index++)
{
sprintf(item_buf, "Item%d", index);
table = blobmsg_open_table(&cm_b, item_buf);
blobmsg_add_string(&cm_b, APN_TYPE_STR, apn_info[index].type);
blobmsg_add_u32(&cm_b, CONN_MODE_STR, apn_info[index].Extra_params.autoconnect);
blobmsg_add_u32(&cm_b, LTE_DEFAULT_STR, apn_info[index].Extra_params.lte_default);
blobmsg_add_u32(&cm_b, DATA_ON_ROAMING_STR, apn_info[index].Extra_params.data_on_roaming);
blobmsg_add_string(&cm_b, PDP_NAME_STR, apn_info[index].pdp_name);
blobmsg_add_u32(&cm_b, IP_TYPE_STR, apn_info[index].iptype);
blobmsg_add_string(&cm_b, APN_STR, apn_info[index].apn);
blobmsg_add_string(&cm_b, LTE_APN_STR, apn_info[index].lte_apn);
blobmsg_add_string(&cm_b, USR_2G3G_STR, apn_info[index].usrname);
blobmsg_add_string(&cm_b, PSWD_2G3G_STR, apn_info[index].paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_2G3G_STR, apn_info[index].authtype);
blobmsg_add_string(&cm_b, USR_4G_STR, apn_info[index].lte_usrname);
blobmsg_add_string(&cm_b, PSWD_4G_STR, apn_info[index].lte_paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_4G_STR, apn_info[index].lte_authtype);
blobmsg_add_u32(&cm_b, NET_MTU_STR, apn_info[index].mtu);
blobmsg_add_string(&cm_b, MMSC_STR, apn_info[index].mmsc);
blobmsg_add_string(&cm_b, MMS_PROXY_STR, apn_info[index].mmsproxy);
blobmsg_add_string(&cm_b, MMS_PORT_STR, apn_info[index].mmsport);
blobmsg_close_table(&cm_b, table);
}
blobmsg_close_array(&cm_b, array);
END:
if(apn_info){
free(apn_info);
apn_info = NULL;
}
table = blobmsg_open_table(&cm_b, "response");
if (ret == CM_OK) {
blobmsg_add_string(&cm_b, "response_status", "OK");
} else {
blobmsg_add_string(&cm_b, "response_status", "ERROR");
}
blobmsg_close_table(&cm_b, table);
ubus_send_reply(ctx, req, cm_b.head);
CM_Log(get_auto_apn_info6, "get_auto_apn_info: done\n");
return 0;
}
/*************************************************************
ubus method, for get all PDP configuration parameters with all profiles which
are located in /etc/config/
response:
<connect_switch>
<proto/>
<dial_switch/>
</connect_switch>
<profile>
<actived_profile/>
<profile_names/> <!-- profile0, profile1,profile2-->
</profile>
<profile_name> <!--named profile name if exist>
<Item index="1">
<type><!-- apn type -->
<connection_num/>
<type/>
<auto_apn/>
<connect_mode/>
<lte_default/>
<data_on_roaming/>
<pdp_name/>
<enable/>
<ip_type/>
<apn/>
<lte_apn/>
<usr_2g3g/>
<pswd_2g3g/>
<authtype_2g3g/>
<usr_4g/>
<pswd_4g/>
<authtype_4g/>
<mtu/>
</type>
</Item>
<Item index="2">
<type><!-- apn type -->
<connection_num/>
<type/>
<auto_apn/>
<connect_mode/>
<lte_default/>
<data_on_roaming/>
<pdp_name/>
<enable/>
<ip_type/>
<apn/>
<lte_apn/>
<usr_2g3g/>
<pswd_2g3g/>
<authtype_2g3g/>
<usr_4g/>
<pswd_4g/>
<authtype_4g/>
<mtu/>
</type>
</Item>
...
</profile_name>
<profile_name1><!--named profile name if exist>
...
</profile_name1>
...
**************************************************************/
static int get_wan_configs(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
struct uci_context *local_ctx = NULL;
struct uci_element *e = NULL;
struct uci_package *p = NULL;
struct uci_section *uci_sec = NULL;
const char *option_value = NULL;
void *tb = NULL, *array_tb = NULL;
int ret_val = 0;
char default_name[MAX_STR_LEN] = { 0 };
char package_name[MAX_STR_LEN] = { 0 };
int profile_count = 0, i, j, n = 0;
char tmp_buf[MAX_PROFILE_NUM * MAX_STR_LEN] = { 0 };
Mnc_Apn *uci_apn[MAX_APN_NUM] = { NULL };
char *profile_name[MAX_APN_NUM] = { NULL };
Apn_Info *apn_info = NULL;
blob_buf_init(&cm_b, 0);
/*load /etc/config/wan */
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
goto END;
}
uci_foreach_element(&local_ctx->root, e) {
if (strcmp(e->name, WAN_PACKAGE_NAME) != 0)
continue;
p = uci_to_package(e); //have found
}
if (!p) {
uci_load(local_ctx, WAN_PACKAGE_NAME, &p);
}
if (!p) {
goto END;
}
uci_foreach_element(&p->sections, e) {
uci_sec = uci_to_section(e);
if (strcmp(uci_sec->type, WAN_SECTION_WAN_CONNECT_WITCH) == 0) {
if (uci_sec->e.name) {
tb = blobmsg_open_table(&cm_b, uci_sec->e.name);
} else {
memset(default_name, 0, MAX_STR_LEN);
snprintf(default_name, MAX_STR_LEN - 1, "connect_switch");
tb = blobmsg_open_table(&cm_b, default_name);
}
option_value = uci_lookup_option_string(local_ctx, uci_sec, "proto");
if (option_value) {
/*get proto */
blobmsg_add_string(&cm_b, "proto", option_value);
}
option_value = uci_lookup_option_string(local_ctx, uci_sec, "dial_switch");
if (option_value) {
/*get dial_switch */
CM_Log(get_wan_configs3, "get dial_switch %s", option_value);
blobmsg_add_string(&cm_b, "dial_switch", option_value);
}
if (tb) {
blobmsg_close_table(&cm_b, tb);
tb = NULL;
}
}else if (strcmp(uci_sec->type, WAN_SECTION_TYPE_ENG_MODE) == 0) {
if (uci_sec->e.name) {
tb = blobmsg_open_table(&cm_b, uci_sec->e.name);
option_value = uci_lookup_option_string(local_ctx, uci_sec, WAN_ENG_MODE_OPTION);
if (option_value) {
/*get enable option */
blobmsg_add_string(&cm_b, WAN_ENG_MODE_OPTION, option_value);
}
blobmsg_close_table(&cm_b, tb);
}
}
}
//get profile info
option_value =
uci_get_option(local_ctx, WAN_PACKAGE_NAME, PROFILE_CONFIG_TYPE_STR, PROFILE_CONFIG_NAME_STR,
ACTIVE_PROFILE_STR);
tb = blobmsg_open_table(&cm_b, "profile");
if(option_value != NULL)
blobmsg_add_string(&cm_b, "actived_profile", option_value);
profile_count =
uci_get_list_number(local_ctx, WAN_PACKAGE_NAME, PROFILE_CONFIG_TYPE_STR, PROFILE_CONFIG_NAME_STR,
PROFILE_LIST_STR);
if (profile_count > 0 && profile_count <= MAX_APN_NUM) {
for (i = 0; i < profile_count; i++) {
option_value =
uci_get_list_value(local_ctx, WAN_PACKAGE_NAME, PROFILE_CONFIG_TYPE_STR,
PROFILE_CONFIG_NAME_STR, PROFILE_LIST_STR, i);
if (option_value != NULL) {
CM_Log(get_wan_configs5, "list[%d] %s\n", i, option_value);
profile_name[i] = malloc(MAX_STR_LEN);
if (!profile_name[i]) {
goto END;
}
memset(profile_name[i], 0, MAX_STR_LEN);
strncpy(profile_name[i], option_value, MAX_STR_LEN - 1);
n += snprintf(tmp_buf + n, MAX_PROFILE_NUM * MAX_STR_LEN - n - 1, "%s,", option_value);
uci_apn[i] = malloc(sizeof(Mnc_Apn));
if (!uci_apn[i]) {
goto END;
}
memset(uci_apn[i], 0, sizeof(Mnc_Apn));
snprintf(package_name, MAX_STR_LEN - 1, "wan_%s", option_value);
ret_val = fill_uci_apn(package_name, uci_apn[i]);
if (ret_val != CM_OK) {
goto END;
}
}
}
CM_Log(get_wan_configs9, "profile_names %s\n", tmp_buf);
blobmsg_add_string(&cm_b, "profile_names", tmp_buf);
} else {
CM_Log_E(get_wan_configs10, "get_wan_configs:[ERROR] no profile_names list\n");
goto END;
}
if (tb) {
blobmsg_close_table(&cm_b, tb);
tb = NULL;
}
for (i = 0; i < profile_count; i++) {
array_tb = blobmsg_open_array(&cm_b, profile_name[i]);
for (j = 0; j < MAX_APN_NUM; j++) {
apn_info = &(uci_apn[i]->apn_info_list[j]);
if (!strlen(apn_info->type))
continue;
tb = blobmsg_open_table(&cm_b, apn_info->type);
blobmsg_add_u32(&cm_b, CONN_NUM_STR, apn_info->connection_num);
blobmsg_add_string(&cm_b, APN_TYPE_STR, apn_info->type);
blobmsg_add_u32(&cm_b, AUTO_APN_STR, apn_info->auto_apn);
blobmsg_add_u32(&cm_b, CONN_MODE_STR, apn_info->Extra_params.autoconnect);
blobmsg_add_u32(&cm_b, LTE_DEFAULT_STR, apn_info->Extra_params.lte_default);
blobmsg_add_u32(&cm_b, DATA_ON_ROAMING_STR, apn_info->Extra_params.data_on_roaming);
blobmsg_add_string(&cm_b, PDP_NAME_STR, apn_info->pdp_name);
blobmsg_add_u32(&cm_b, ENABLE_STR, apn_info->enable);
blobmsg_add_u32(&cm_b, IP_TYPE_STR, apn_info->iptype);
blobmsg_add_string(&cm_b, APN_STR, apn_info->apn);
blobmsg_add_string(&cm_b, LTE_APN_STR, apn_info->lte_apn);
blobmsg_add_string(&cm_b, USR_2G3G_STR, apn_info->usrname);
blobmsg_add_string(&cm_b, PSWD_2G3G_STR, apn_info->paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_2G3G_STR, apn_info->authtype);
blobmsg_add_string(&cm_b, USR_4G_STR, apn_info->lte_usrname);
blobmsg_add_string(&cm_b, PSWD_4G_STR, apn_info->lte_paswd);
blobmsg_add_string(&cm_b, AUTHTYPE_4G_STR, apn_info->lte_authtype);
blobmsg_add_u32(&cm_b, NET_MTU_STR, apn_info->mtu);
if (tb) {
blobmsg_close_table(&cm_b, tb);
tb = NULL;
}
}
if (array_tb) {
blobmsg_close_array(&cm_b, array_tb);
array_tb = NULL;
}
}
END:
for (i = 0; i < profile_count; i++) {
if (profile_name[i]) {
free(profile_name[i]);
profile_name[i] = NULL;
}
if (uci_apn[i]) {
free(uci_apn[i]);
uci_apn[i] = NULL;
}
}
if (tb) {
blobmsg_close_table(&cm_b, tb);
tb = NULL;
}
if (array_tb) {
blobmsg_close_array(&cm_b, array_tb);
array_tb = NULL;
}
ubus_send_reply(ctx, req, cm_b.head);
//free_uci_profile_ctx();
CM_Log(get_wan_configs11, "get_wan_configs: leave %d\n", ret_val);
return ret_val;
}
/*
<network_activity>
<Item index="1">
<Item0>
<pdp_name/>
<cid/>
<index/>
<start_time/>
<end_time/>
<ip_type/>
<ipv4addr/>
<ipv6addr/>
</Item0>
</Item>
<Item index="2">
<Item1>
<pdp_name/>
<cid/>
<index/>
<start_time/>
<end_time/>
<ip_type/>
<ipv4addr/>
<ipv6addr/>
</Item1>
</Item>
...
</network_activity>
*/
static int get_network_activity(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
void * array;
void * table;
int index, array_idx;
char item_buf[16];
char ip_buf[68];
time_t cur_time;
unsigned int connect_seconds = 0;
unsigned int total_seconds = 0;
blob_buf_init(&cm_b, 0);
array = blobmsg_open_array(&cm_b, "network_activity");
index = 0;
time(&cur_time);
while(index < cur_nwarray_num) {
if(index < cur_nwarray_index)
array_idx = cur_nwarray_index - index - 1;
else
array_idx = MAX_NWACTIVITY_ARRAYNUM - (index - cur_nwarray_index) - 1;
CM_Log(get_network_activity1, "get_network_activity, index:%d, array index:%d", index, array_idx);
if(nwactivity_array[array_idx].index == -1) {
index++;
continue;
}
sprintf(item_buf, "Item%d", index);
table = blobmsg_open_table(&cm_b, item_buf);
blobmsg_add_string(&cm_b, "pdp_name", nwactivity_array[array_idx].PDP_name);
blobmsg_add_u32(&cm_b, "cid", nwactivity_array[array_idx].cid);
blobmsg_add_u32(&cm_b, "index", nwactivity_array[array_idx].index);
blobmsg_add_string(&cm_b, "start_time", nwactivity_array[array_idx].start_tim);
blobmsg_add_string(&cm_b, "end_time", nwactivity_array[array_idx].end_tim);
blobmsg_add_u32(&cm_b, "ip_type", nwactivity_array[array_idx].iptype);
if (nwactivity_array[array_idx].connect_ticks > 0)
{
if (cur_time >= nwactivity_array[array_idx].connect_ticks)
connect_seconds = cur_time - nwactivity_array[array_idx].connect_ticks;
total_seconds = connect_seconds + nwactivity_array[array_idx].duration_time;
}
else
{
connect_seconds = nwactivity_array[array_idx].current_duration_time;
total_seconds = nwactivity_array[array_idx].duration_time;
}
blobmsg_add_u32(&cm_b, "current_duration", connect_seconds);
blobmsg_add_u32(&cm_b, "duration", total_seconds);
CM_Log(get_network_activity4425, "get_network_activity, current_duration %d, duration %d", connect_seconds, total_seconds);
memset(ip_buf, 0, 68);
inet_ntop(AF_INET, &(nwactivity_array[array_idx].ipv4addr), ip_buf, 68);
blobmsg_add_string(&cm_b, "ipv4addr", ip_buf);
memset(ip_buf, 0, 68);
inet_ntop(AF_INET6, &(nwactivity_array[array_idx].ipv6addr), ip_buf, 68);
blobmsg_add_string(&cm_b, "ipv6addr", ip_buf);
blobmsg_close_table(&cm_b, table);
index ++;
}
blobmsg_close_array(&cm_b, array);
ubus_send_reply(ctx, req, cm_b.head);
return 0;
}
/*
<network_duration>
<Item index="1">
<Item0>
<current_duration/>
<duration/>
</Item0>
</Item>
<Item index="2">
<Item1>
<current_duration/>
<duration/>
</Item1>
</Item>
...
</network_duration>
*/
static int get_network_duration(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
UNUSED(msg);
void * array;
void * table;
int index;
char item_buf[8];
time_t cur_time;
unsigned int connect_seconds = 0;
unsigned int total_seconds = 0;
network_duration_s *item = NULL;
blob_buf_init(&cm_b, 0);
array = blobmsg_open_array(&cm_b, "network_duration");
index = 0;
time(&cur_time);
while(index < MAX_CID_LIMITATION) {
item = &nw_duration[index];
if(item->cid != index && item->connect_ticks == 0 && item->duration_time == 0) {
index++;
continue;
}
sprintf(item_buf, "Item%d", index);
table = blobmsg_open_table(&cm_b, item_buf);
blobmsg_add_u32(&cm_b, "cid", item->cid);
if (item->connect_ticks > 0)
{
if (cur_time >= item->connect_ticks)
connect_seconds = cur_time - item->connect_ticks;
total_seconds = connect_seconds + item->duration_time;
}
else
{
connect_seconds = item->current_duration_time;
total_seconds = item->duration_time;
}
blobmsg_add_u32(&cm_b, "current_duration", connect_seconds);
blobmsg_add_u32(&cm_b, "duration", total_seconds);
CM_Log(get_network_duration4572, "get_network_duration, current_duration %d, duration %d", connect_seconds, total_seconds);
blobmsg_close_table(&cm_b, table);
index ++;
}
blobmsg_close_array(&cm_b, array);
ubus_send_reply(ctx, req, cm_b.head);
return 0;
}
static int get_network_duration_ccinet(struct ubus_context *ctx, struct ubus_object *obj,
struct ubus_request_data *req, const char *method, struct blob_attr *msg)
{
UNUSED(obj);
UNUSED(method);
struct blob_attr *cm_ccinet[ARRAY_SIZE(cm_get_ccinet_pol)];
void * table;
int cid;
time_t cur_time;
unsigned int connect_seconds = 0;
unsigned int total_seconds = 0;
network_duration_s *item = NULL;
if (blobmsg_parse
(cm_get_ccinet_pol, ARRAY_SIZE(cm_get_ccinet_pol), cm_ccinet, blob_data(msg),
blob_len(msg)) != 0) {
return UBUS_STATUS_INVALID_ARGUMENT;
}
if (!cm_ccinet[0]) {
return UBUS_STATUS_NO_DATA;
}
cid = blobmsg_get_u32(cm_ccinet[0]);
item = &nw_duration[cid];
blob_buf_init(&cm_b, 0);
table = blobmsg_open_table(&cm_b, "network_duration");
time(&cur_time);
if (item->connect_ticks > 0)
{
if (cur_time >= item->connect_ticks)
connect_seconds = cur_time - item->connect_ticks;
total_seconds = connect_seconds + item->duration_time;
}
else
{
connect_seconds = item->current_duration_time;
total_seconds = item->duration_time;
}
blobmsg_add_u32(&cm_b, "current_duration", connect_seconds);
blobmsg_add_u32(&cm_b, "duration", total_seconds);
CM_Log(get_network_duration_ccinet4676, "get_network_duration_ccinet: current_duration %d, duration %d", connect_seconds, total_seconds);
blobmsg_close_table(&cm_b, table);
ubus_send_reply(ctx, req, cm_b.head);
blob_buf_free(&cm_b);
return 0;
}
static int delete_network_activity(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);
int ret, index, flag, idx;
char * str = NULL;
struct blob_attr *tb[NWACTIVITY_MAX];
blob_buf_init(&cm_b, 0);
ret = blobmsg_parse(del_nwactivity_pol, ARRAY_SIZE(del_nwactivity_pol), tb, blob_data(msg), blob_len(msg));
if (ret != CM_OK) {
ret = CM_ERR_PARSE;
goto END;
}
if (!tb[NWACTIVITY_DEL_INDEX]) {
ret = CM_ERR_INVAL;
goto END;
}
str = blobmsg_get_string(tb[NWACTIVITY_DEL_INDEX]);
index = atoi(str);
if (!tb[NWACTIVITY_DEL_FLAG]) {
ret = CM_ERR_INVAL;
goto END;
}
str = blobmsg_get_string(tb[NWACTIVITY_DEL_FLAG]);
flag = atoi(str);
if(flag == 0){
//delete the index
CM_Log(delete_network_activity4, "delete_network_activity, delete index:%d", index);
if(index >= cur_nwarray_num) {
ret = CM_ERR_INVAL;
goto END;
}
for(idx = 0; idx < MAX_NWACTIVITY_ARRAYNUM; idx++) {
if(nwactivity_array[idx].index == index) {
CM_Log(delete_network_activity6, "find the index in array:%d",idx);
memset(&nwactivity_array[idx], 0, sizeof(network_activity_array));
nwactivity_array[idx].index = -1;
break;
}
}
}else if(flag == 1) {
CM_Log(delete_network_activity7, "delete_network_activity, delete all items");
nwactivity_arrary_init();
}
END:
return ret;
}
int is_pdp_auto_apn(Mnc_Apn * work_apn, char *apn_type)
{
int i;
Apn_Info *apn_info = NULL;
if (!work_apn) {
return 0;
}
for (i = 0; i < MAX_APN_NUM; i++) {
apn_info = &(work_apn->apn_info_list[i]);
if (strstr(apn_info->type, apn_type)) {
CM_Log(is_pdp_auto_apn, "is_pdp_auto_apn: leave, auto apn %d\n", apn_info->auto_apn);
return apn_info->auto_apn;
}
}
return 0;
}
int is_pdp_auto_mode(Mnc_Apn * work_apn, char *apn_type)
{
int i;
Apn_Info *apn_info = NULL;
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return 0;
#endif
if (!work_apn) {
return 0;
}
for (i = 0; i < MAX_APN_NUM; i++) {
apn_info = &(work_apn->apn_info_list[i]);
if (strstr(apn_info->type, apn_type)) {
if (apn_info->enable) {
CM_Log(is_pdp_auto_mode, "is_pdp_auto_mode: leave, autoconnect %d\n", apn_info->Extra_params.autoconnect);
return apn_info->Extra_params.autoconnect;
}
}
}
return 0;
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
static int is_pdp_data_on_boot(Mnc_Apn * work_apn, char *apn_type)
{
int i;
Apn_Info *apn_info = NULL;
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
return 0;
#endif
if (!work_apn) {
return 0;
}
for (i = 0; i < MAX_APN_NUM; i++) {
apn_info = &(work_apn->apn_info_list[i]);
if (strstr(apn_info->type, apn_type)) {
if (apn_info->enable) {
CM_Log(is_pdp_data_on_boot, "is_pdp_data_on_boot: leave, always_on(data_on_boot) %d\n", apn_info->Extra_params.always_on);
return apn_info->Extra_params.always_on;
}
}
}
return 0;
}
#endif
int set_default_data_call()
{
int ret = CM_OK;
#ifdef CONFIG_CM_P701
#ifdef PIPE_MANUAL_CONNECT
if (pipe_mode)
ret = cm_get_zroam_list_ril();
#endif
#endif
ret = init_apn_list();
if (ret != CM_OK) {
CM_Log_E(set_default_data_call1, "set_default_data_call: init APN list failed\n");
goto end;
}
property_set(PROP_DEFINED_CID, "-1");
prop_set_ril_default_cid();
if (!cm_allow_datalink())
{
CM_Log(set_default_data_call4834, "set_default_data_call: cm not allow datalink\n");
return ret;
}
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (is_pdp_data_on_boot(g_work_apn, "default"))
#else
if (is_pdp_auto_mode(g_work_apn, "default"))
#endif
{
CM_Log(set_default_data_call2, "set_default_data_call: auto connect\n");
ret = connection_handler(g_work_apn);
return ret;
}
end:
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (!is_pdp_data_on_boot(g_work_apn, "default"))
{
CM_Log(set_default_data_call4612, "set_default_data_call: data on boot disabled\n");
return ret;
}
#else
dialer_query_defaultdatacall();
if (ret != CM_OK && !CM_IsDefaultCtxExist())
{
send_redialmsg_to_redialthread(-1, REDIAL_DEFAULT_DATACALL);
}
#endif
CM_Log(set_default_data_call4, "set_default_data_call: ret %d\n", ret);
return ret;
}
extern pthread_mutex_t cm_mutex;
static void set_single_stack_data_call()
{
CM_Connection_Context *ctx = NULL;
CM_Connection_Context *connect_ctx = NULL;
Apn_Info apn_info;
char value_buf[16];
CM_Log(set_single_stack_data_call4876, "set_single_stack_data_call: current cid %d\n", get_current_cid());
connect_ctx = cm_get_ctx_by_cid(get_current_cid());
if (connect_ctx == NULL || connect_ctx->pdpinfo == NULL)
return;
memset(&apn_info, 0, sizeof(apn_info));
CM_Log(set_single_stack_data_call4876, "set_single_stack_data_call: IP_Type %d\n", connect_ctx->pdpinfo->IP_Type);
if (connect_ctx->pdpinfo->IP_Type == IPV4V6 )
{
CM_Log(set_single_stack_data_call4876, "set_single_stack_data_call: eps_ipType %d\n", connect_ctx->pdpinfo->eps_ipType);
if (connect_ctx->pdpinfo->eps_ipType == IPV4)
apn_info.iptype = IPV6;
else if (connect_ctx->pdpinfo->eps_ipType == IPV6)
apn_info.iptype = IPV4;
else
return;
}
else if (connect_ctx->pdpinfo->eps_ipType == IPV4)
apn_info.iptype = IPV6;
else if (connect_ctx->pdpinfo->eps_ipType == IPV6)
apn_info.iptype = IPV4;
strncpy(apn_info.apn, connect_ctx->pdpinfo->APN, sizeof(apn_info.apn) - 1);
strncpy(apn_info.lte_apn, connect_ctx->pdpinfo->LteAPN, sizeof(apn_info.lte_apn) - 1);
strncpy(apn_info.pdp_name, connect_ctx->pdpinfo->PDP_name, sizeof(apn_info.pdp_name) - 1);
strncpy(apn_info.authtype, connect_ctx->pdpinfo->Authtype2G3G, sizeof(apn_info.authtype) - 1);
strncpy(apn_info.usrname, connect_ctx->pdpinfo->Usr2G3G, sizeof(apn_info.usrname) - 1);
strncpy(apn_info.paswd, connect_ctx->pdpinfo->PASWD2G3G, sizeof(apn_info.paswd) - 1);
strncpy(apn_info.lte_authtype, connect_ctx->pdpinfo->Authtype4G, sizeof(apn_info.lte_authtype) - 1);
strncpy(apn_info.lte_usrname, connect_ctx->pdpinfo->Usr4G, sizeof(apn_info.lte_usrname) - 1);
strncpy(apn_info.lte_paswd, connect_ctx->pdpinfo->PASWD4G, sizeof(apn_info.lte_paswd) - 1);
apn_info.mtu = connect_ctx->pdpinfo->mtu;
apn_info.Extra_params.autoconnect = 0;
apn_info.Extra_params.always_on = 0;
apn_info.Extra_params.data_on_roaming = connect_ctx->pdpinfo->data_on_roaming;
apn_info.auto_apn = 0;
if (get_current_cid() > 1)
apn_info.cid = get_current_cid() - 1;
else
apn_info.cid = get_current_cid() + 1;
pthread_mutex_lock(&cm_mutex);
CM_Log(set_single_stack_data_call4964, "set_single_stack_data_call: cm_mutex locked\n");
//coverity[string_null:SUPPRESS]
ctx = create_new_pdp_ctx(&apn_info);
if (ctx == NULL)
return;
ctx->pdpinfo->parent_cid = get_current_cid();
ctx->connectStatus = CM_CONNECT_CONNING;
snprintf(value_buf, sizeof(value_buf), "%d", apn_info.cid);
property_set(PROP_DEFINED_CID, value_buf);
property_set(PROP_SINGLE_STACK_CID, value_buf);
pthread_mutex_unlock(&cm_mutex);
CM_Log(set_single_stack_data_call4976, "set_single_stack_data_call: cm_mutex unlocked\n");
SetupDataCall(ctx);
QueryDataCall(ctx);
property_set(PROP_DEFINED_CID, "-1");
}
static const struct ubus_method cm_methods[] = {
UBUS_METHOD_NOARG("create_pdp", CreatePdp_method),
UBUS_METHOD("destroy_pdp", DestroyConnecion_method, destroy_connection_policy),
UBUS_METHOD("get_link_context", GetLinkContext_method, get_link_context_policy),
UBUS_METHOD("cm_set_image_type", SetImageType_method, cm_set_image_policy),
UBUS_METHOD_NOARG("cm_get_image_type", GetImageType_method),
UBUS_METHOD_NOARG("get_wan_configs", get_wan_configs),
UBUS_METHOD_NOARG("reload", connection_reload),
UBUS_METHOD("connection_switch", connection_switch, connection_switch_pol),
UBUS_METHOD("configs_handler", configs_handler, configs_handler_pol),
UBUS_METHOD("get_apn_info", get_apn_info, get_apn_info_pol),
UBUS_METHOD_NOARG("get_network_activity", get_network_activity),
UBUS_METHOD("delete_network_activity", delete_network_activity, del_nwactivity_pol),
UBUS_METHOD("set_auto_switch", set_auto_switch, auto_switch_pol),
UBUS_METHOD_NOARG("get_auto_switch",get_auto_switch),
UBUS_METHOD("set_eng_mode", set_eng_mode, eng_mode_pol),
UBUS_METHOD_NOARG("get_eng_info",get_eng_info),
UBUS_METHOD("match_auto_apn", match_auto_apn, mcc_mnc_pol),
UBUS_METHOD("get_auto_apn", get_auto_apn_info, get_apn_info_pol),
UBUS_METHOD_NOARG("get_network_duration", get_network_duration),
UBUS_METHOD("get_network_duration_ccinet", get_network_duration_ccinet, cm_get_ccinet_pol),
};
static struct ubus_object_type cm_object_type = UBUS_OBJECT_TYPE("test", cm_methods);
static struct ubus_object cm_object = {
.name = "cm",
.type = &cm_object_type,
.methods = cm_methods,
.n_methods = ARRAY_SIZE(cm_methods),
//.subscribe_cb = cm_subscribe_cb,
};
void *redial_task(void *argv)
{
UNUSED(argv);
msg_hdr receive_msg;
int read_len = 0;
cm_client_fd.fd = usock(USOCK_UNIX, CM_INNER_CONN_SOCKET, NULL);
if (cm_client_fd.fd < 0) {
CM_Log_E(redial_task, "Failed to connect to server\n");
return NULL;
}
CM_Log(redial_task1, "client fd %d", cm_client_fd.fd);
while (1) {
CM_Log(redial_task2, "redial_task:[client] pending to read the data from socket %d\n", cm_client_fd.fd);
read_len = read(cm_client_fd.fd, &receive_msg, sizeof(msg_hdr));
if (read_len <= 0)
continue;
if (read_len != sizeof(msg_hdr)) {
continue;
}
CM_Log(redial_task3, "redial_task:[<<<<][client] receive msg id [0x%x] type [%d] done\n", receive_msg.id, receive_msg.msgtype);
//logic handle here
CM_Redial_Function(&receive_msg);
}
}
void send_dialmsg_to_mainthread(int connectionNum, redialmsg_type msgtype)
{
int writen = 0;
msg_hdr send_msg;
struct timeval tv;
gettimeofday(&tv, NULL);
send_msg.id = ((UINT32)((tv.tv_sec % 86400) << 15) + (tv.tv_usec >> 5));
send_msg.connectionNum = connectionNum;
send_msg.msgtype = msgtype;
// send msg to server
writen = write(cm_client_fd.fd, &send_msg, sizeof(msg_hdr));
CM_Log(send_dialmsg_to_mainthread, "[>>>][client] send msg id [0x%x] type [%d] size [%d] to mainthread via socket %d done\n", send_msg.id, msgtype, writen, cm_client_fd.fd);
}
void send_redialmsg_to_redialthread(int connectionNum, redialmsg_type msgtype)
{
int writen = 0;
msg_hdr send_msg;
struct timeval tv;
gettimeofday(&tv, NULL);
send_msg.id = ((UINT32)((tv.tv_sec % 86400) << 15) + (tv.tv_usec >> 5));
send_msg.connectionNum = connectionNum;
send_msg.msgtype = msgtype;
// send msg to server
writen = write(cm_accept_fd.fd, &send_msg, sizeof(msg_hdr));
CM_Log(send_redialmsg_to_redialthread, "[>>>>][server] send msg id [0x%x] type [%d] size [%d] to redialthread via socket %d done\n", send_msg.id, msgtype, writen, cm_accept_fd.fd);
}
#ifdef CONFIG_CM_P701
static void cm_get_zroam_list_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
RIL_ZROAM *response = NULL;
RIL_ZROAM *zroam_list = g_zroam_list;
int i = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
CM_Log_E(cm_get_zroam_list_cb, "cm_get_zroam_list_cb: Parse failed\n");
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
CM_Log_E(cm_get_zroam_list_cb1, "cm_get_zroam_list_cb: rilerrno %d\n", rilerrno);
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_GET_ZROAM) {
CM_Log_E(cm_get_zroam_list_cb2, "cm_get_zroam_list_cb: The response not for the request\n");
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (response_len > MAX_ZROAM_COUNT)
{
CM_Log_E(cm_get_zroam_list_cb3, "cm_get_zroam_list_cb: The response not for the request\n");
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
for ( i = 0; i < MAX_ZROAM_COUNT; i++)
{
if (zroam_list[i].mccmnc)
free(zroam_list[i].mccmnc);
memset(&zroam_list[i], 0, sizeof(RIL_ZROAM));
}
response = (RIL_ZROAM *) response_data;
CM_Log(cm_get_zroam_list_cb4, "cm_get_zroam_list_cb: count %d \n", response_len);
for (i = 0; i < response_len; i++) {
zroam_list->mccmnc = strdup(response->mccmnc);
zroam_list->pdptype = response->pdptype;
CM_Log(cm_get_zroam_list_cb4312, "cm_get_zroam_list_cb: mccmnc %s, iptype %d \n", zroam_list->mccmnc, zroam_list->pdptype);
response++;
zroam_list++;
}
rilutil_freeResponseData(requestid, response_data, response_len);
} else {
CM_Log_E(cm_get_zroam_list_cb5, "cm_get_zroam_list_cb:rilerror code %d\n", rilerrno);
}
return;
}
static int cm_get_zroam_list_ril()
{
int ret_val;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_ZROAM, NULL, 0);
ret_val = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, cm_get_zroam_list_cb, 0, 0);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(cm_get_zroam_list_ril, "cm_get_zroam_list_ril: ubus_invoke RIL_REQUEST_GET_ZROAM failed %s\n", ubus_strerror(ret_val));
}
CM_Log(cm_get_zroam_list_ril1, "cm_get_zroam_list_ril: ret %d \n", ret_val);
return ret_val;
}
#endif
int cm_get_zroam_iptype()
{
int iptype = 0; /* 0 means invalid*/
#ifdef CONFIG_CM_P701
RIL_ZROAM *zroam_list = g_zroam_list;
char mccmnc[7] = {0};
if (!pipe_mode)
goto end;
if (!IsRoaming)
goto end;
if ( cm_get_imsi_mccmnc(mccmnc) != UBUS_STATUS_OK)
{
CM_Log_E(cm_get_zroam_iptype, "%s: FATAL ERROR!\n", __func__);
goto end;
}
CM_Log(cm_get_zroam_iptype1, "%s:mccmnc %s", __func__, mccmnc);
CM_Log(cm_get_zroam_iptype4362, "%s:zroam_list mccmnc %s, iptype %d", __func__, zroam_list->mccmnc, zroam_list->pdptype);
while(zroam_list->mccmnc)
{
if (!strcmp(mccmnc, zroam_list->mccmnc))
{
iptype = zroam_list->pdptype;
CM_Log(cm_get_zroam_iptyp2, "%s: roaming iptype %d", __func__, zroam_list->pdptype);
break;
}
zroam_list++;
}
#else
goto end;
#endif
end:
return iptype;
}
void accept_cl_receive_cb(struct uloop_fd *u, unsigned int events)
{
UNUSED(events);
int data_len = 0;
msg_hdr msg_buffer;
CM_Connection_Context *ConInfo = NULL;
Apn_Info *apninfo;
memset(&msg_buffer, 0, sizeof(msg_hdr));
data_len = read(u->fd, &msg_buffer, sizeof(msg_hdr));
if (data_len != sizeof(msg_hdr)) {
CM_Log_E(accept_cl_receive_cb1, "[server] receive data failed\n");
return;
}
CM_Log(accept_cl_receive_cb2, "accept_cl_receive_cb: [<<<][server] receive msg id [0x%x], msg type [%d], connectionNum:0x%x", msg_buffer.id, msg_buffer.msgtype,
msg_buffer.connectionNum);
//invoke dial func call here
if (msg_buffer.msgtype == REDIAL_IMMED) {
ConInfo = findContextByConnum(msg_buffer.connectionNum);
if (ConInfo != NULL)
{
CM_Log(accept_cl_receive_cb4759, "accept_cl_receive_cb:[server] find context 0x%x, connectStatus %d", ConInfo, ConInfo->connectStatus);
if (ConInfo->connectStatus != CM_CONNECT_CONSUCCESS)
{
CM_StartDialer(ConInfo);
if (CM_CheckContextValid(ConInfo))
{
if ((ConInfo->dialFailureCode != 0) && (ConInfo->dialFailureCode != PDP_FAIL_GET_GLOBALIP) &&
(ConInfo->dialFailureCode != PDP_FAIL_BACKOFF_TIME)) {
if (ConInfo->retryTime != CM_INT_MAX) {
ConInfo->connectStatus = CM_CONNECT_REDIAL;
//call redial method here
send_redialmsg_to_redialthread(ConInfo->pdpinfo->connectionNum, REDIAL_IMMED);
} else {
ConInfo->connectStatus = CM_CONNECT_REDIAL;
//call redial method here
send_redialmsg_to_redialthread(ConInfo->pdpinfo->connectionNum, REDIAL_NEWAPN);
}
}
}
}
}
} else if (msg_buffer.msgtype == REDIAL_NEWAPN) {
ConInfo = findContextByConnum(msg_buffer.connectionNum);
if (ConInfo != NULL) {
apninfo = get_apninfo_from_LteAPN(g_work_apn, ConInfo->pdpinfo->LteAPN);
if (apninfo != NULL)
SetInitialAttachAPN(apninfo, true);
}
} else if (msg_buffer.msgtype == REDIAL_NEWAPN_CLEARETIF) {
CM_Clear_ETIFlag(true);
cm_set_cfun(4);
sleep(1);
cm_set_cfun(1);
}
else if (msg_buffer.msgtype == REDIAL_DEFAULT_DATACALL) {
set_default_data_call();
} else if (msg_buffer.msgtype == REDIAL_SINGLE_STACK) {
set_single_stack_data_call();
}
CM_Log(accept_cl_receive_cb3, "accept_cl_receive_cb:[server] done");
}
#ifdef CONFIG_CM_URSP
extern int cm_get_current_cid(void);
static struct list_head g_ursp_list_head = LIST_HEAD_INIT(g_ursp_list_head);
static struct list_head *cm_get_ursp_list_head(void)
{
return &g_ursp_list_head;
}
static ursp_list_s *cm_new_ursp_list(void)
{
struct list_head *head = cm_get_ursp_list_head();
/*malloc ursp memory*/
ursp_list_s *ursp_list = malloc(sizeof(ursp_list_s));
if (!ursp_list)
goto fail;
memset(ursp_list, 0, sizeof(ursp_list_s));
INIT_LIST_HEAD(&ursp_list->list);
list_add_tail(&ursp_list->list, head);
return ursp_list;
fail:
return NULL;
}
static void cm_free_ursp_list(void)
{
struct list_head *head = cm_get_ursp_list_head();
ursp_list_s *ursp_list = NULL;
while (!list_empty(head)) {
ursp_list = list_first_entry(head, ursp_list_s, list);
list_del(&ursp_list->list);
free(ursp_list);
}
}
static ursp_list_s *cm_find_ursp_by_qos(int curr_preceduce)
{
ursp_list_s *ursp_list = NULL, *high_pri_ursp_list = NULL;
struct list_head *head = cm_get_ursp_list_head();
int precedence = curr_preceduce;
int precedence_processed = -1;
int next = 0;
if (precedence)
precedence_processed = precedence;
list_for_each_entry(ursp_list, head, list) {
if (ursp_list)
{
if (precedence == -1)
{
precedence = ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule;
high_pri_ursp_list = ursp_list;
CM_Log(cm_find_ursp_by_qos4915, "cm_find_ursp_by_qos: first precedence %d, ursp_list %x", precedence, high_pri_ursp_list);
}
else if (precedence_processed == -1)
{
if (ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule < precedence)
{
precedence = ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule;
high_pri_ursp_list = ursp_list;
CM_Log(cm_find_ursp_by_qos4922, "cm_find_ursp_by_qos: find high precedence %d, ursp_list %x", precedence, high_pri_ursp_list);
}
}
else
{
if (next == 0)
{
if (ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule > precedence)
{
precedence = ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule;
high_pri_ursp_list = ursp_list;
next = 1;
CM_Log(cm_find_ursp_by_qos4941, "cm_find_ursp_by_qos: find next high precedence %d, ursp_list %x", precedence, high_pri_ursp_list);
}
}
else
{
if (ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule > precedence_processed && ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule < precedence)
{
precedence = ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule;
high_pri_ursp_list = ursp_list;
CM_Log(cm_find_ursp_by_qos4950, "cm_find_ursp_by_qos: find next higher precedence %d, ursp_list %x", precedence, high_pri_ursp_list);
}
}
}
}
}
return high_pri_ursp_list;
}
static int cm_find_rsd_by_qos(ursp_list_s *ursp, int curr_index)
{
int i = 0;
int precedence = -1, precedence_processed = -1;
int high_pri_index = -1;
if (!ursp)
return -1;
if (curr_index >= 0)
precedence = ursp->ursp.matchedUrspInfo.rsd[curr_index].precedenceOfRSD;
CM_Log(cm_find_rsd_by_qos4939, "cm_find_rsd_by_qos: numOfRSD %d, curr precedence %d", ursp->ursp.matchedUrspInfo.numOfRSD, precedence);
for (i = 0; i < ursp->ursp.matchedUrspInfo.numOfRSD; i++)
{
CM_Log(cm_find_rsd_by_qos4944, "cm_find_rsd_by_qos: matchedUrspInfo.rsd[%d].precedenceOfRSD %d", i, ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD);
if (precedence == -1)
{
precedence = ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD;
high_pri_index = i;
CM_Log(cm_find_rsd_by_qos4945, "cm_find_rsd_by_qos: first precedence %d, high_pri_index %d", precedence, high_pri_index);
}
else if (curr_index == -1)
{
if (ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD < precedence)
{
precedence = ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD;
high_pri_index = i;
CM_Log(cm_find_rsd_by_qos4952, "cm_find_rsd_by_qos: find higher precedence %d, high_pri_index %d", precedence, high_pri_index);
}
}
else if (i != curr_index)
{
if (precedence_processed == -1)
{
if (ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD > precedence)
{
precedence_processed = precedence;
precedence = ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD;
high_pri_index = i;
CM_Log(cm_find_rsd_by_qos4970, "cm_find_rsd_by_qos: find next high precedence %d, high_pri_index %d", precedence, high_pri_index);
}
}
else
{
if (ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD > precedence_processed && ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD < precedence)
{
precedence = ursp->ursp.matchedUrspInfo.rsd[i].precedenceOfRSD;
high_pri_index = i;
CM_Log(cm_find_rsd_by_qos4980, "cm_find_rsd_by_qos: find next higher precedence %d, high_pri_index %d", precedence, high_pri_index);
}
}
}
}
if (high_pri_index >= 0)
return high_pri_index;
else
return -1;
}
static void ConvertApn2Ap(char *pOutString, const char *pInString, int *pOutLen, int inLen)
{
int indx = 0;
char tmpLen = *pInString;
for (indx = 0; indx < inLen; indx++)
*(pOutString+indx) = *(pInString+indx+1);
while((tmpLen+1) < inLen)
{
*(pOutString+tmpLen) = 0x2e;
tmpLen += *(pInString+tmpLen+1)+1;
}
*pOutLen = inLen - 1;
return;
}
static BOOL update_pdp_ctx_by_ursp(CM_Connection_Context *cm_ctx)
{
ursp_list_s *high_pri_ursp_list = NULL;
int precedence = -1;
RSD *rsd = NULL;
BOOL changed = FALSE;
int rsd_index = 0;
Apn_Info apnInfo, *apninfo = NULL;
memset(&apnInfo, 0, sizeof(Apn_Info));
apninfo = &apnInfo;
if (cm_ctx->pdpinfo->ursp_list)
{
precedence = cm_ctx->pdpinfo->ursp_list->ursp.matchedUrspInfo.precedenceOfURSPRule;
}
high_pri_ursp_list = cm_find_ursp_by_qos(precedence);
if (high_pri_ursp_list)
{
rsd_index = cm_find_rsd_by_qos(high_pri_ursp_list, precedence);
if (rsd_index >= 0)
{
rsd = &high_pri_ursp_list->ursp.matchedUrspInfo.rsd[rsd_index];
if (rsd->rsdComponents.dnnPresent)
{
int apnLen;
ConvertApn2Ap(apninfo->apn, (char *)rsd->rsdComponents.dnn.name, &apnLen, rsd->rsdComponents.dnn.length);
strncpy(apninfo->lte_apn, (char *)apninfo->apn, sizeof(apninfo->lte_apn) - 1);
}
if (rsd->rsdComponents.pduSessionTypePresent)
apninfo->iptype = rsd->rsdComponents.pduSessionType;
apninfo->Extra_params.data_on_roaming = 1;
changed = check_merger_pdpcontext(apninfo, cm_ctx, 0);
cm_ctx->pdpinfo->ursp_list = high_pri_ursp_list;
cm_ctx->pdpinfo->ursp_processed++;
cm_ctx->pdpinfo->rsd_index = rsd_index;
cm_ctx->pdpinfo->rsd_processed = 1;
}
}
return changed;
}
static BOOL update_pdp_ctx_by_rsd(CM_Connection_Context *cm_ctx)
{
ursp_list_s *high_pri_ursp_list = NULL;
Apn_Info apnInfo, *apninfo = NULL;
int rsd_index = -1;
RSD *rsd = NULL;
bool changed = TRUE;
memset(&apnInfo, 0, sizeof(Apn_Info));
apninfo = &apnInfo;
apninfo->connection_num = INVALID_CID;
apninfo->cid = INVALID_CID;
high_pri_ursp_list = cm_ctx->pdpinfo->ursp_list;
rsd_index = cm_find_rsd_by_qos(high_pri_ursp_list, cm_ctx->pdpinfo->rsd_index);
if (rsd_index >= 0)
{
rsd = &high_pri_ursp_list->ursp.matchedUrspInfo.rsd[rsd_index];
if (rsd->rsdComponents.dnnPresent)
{
int apnLen;
ConvertApn2Ap(apninfo->apn, (char *)rsd->rsdComponents.dnn.name, &apnLen, rsd->rsdComponents.dnn.length);
strncpy(apninfo->lte_apn, (char *)apninfo->apn, sizeof(apninfo->lte_apn) - 1);
}
if (rsd->rsdComponents.pduSessionTypePresent)
apninfo->iptype = rsd->rsdComponents.pduSessionType;
apninfo->Extra_params.data_on_roaming = 1;
changed = check_merger_pdpcontext(apninfo, cm_ctx, 0);
cm_ctx->pdpinfo->ursp_list = high_pri_ursp_list;
cm_ctx->pdpinfo->rsd_index = rsd_index;
cm_ctx->pdpinfo->rsd_processed++;
}
return changed;
}
static CM_Connection_Context *create_new_pdp_ctx_by_ursp(int ursp_num, AppInfo *app_info)
{
CM_Connection_Context *cm_ctx = NULL;
ursp_list_s *high_pri_ursp_list = NULL;
Apn_Info apnInfo, *apninfo = NULL;
int rsd_index = -1;
RSD *rsd = NULL;
high_pri_ursp_list = cm_find_ursp_by_qos(-1);
memset(&apnInfo, 0, sizeof(Apn_Info));
apninfo = &apnInfo;
CM_Log(create_new_pdp_ctx_by_ursp5050, "create_new_pdp_ctx_by_ursp: high_pri_ursp_list %x", high_pri_ursp_list);
if (high_pri_ursp_list)
{
apninfo->connection_num = INVALID_CID;
apninfo->cid = INVALID_CID;
rsd_index = cm_find_rsd_by_qos(high_pri_ursp_list, -1);
if (rsd_index >= 0)
{
rsd = &high_pri_ursp_list->ursp.matchedUrspInfo.rsd[rsd_index];
if (rsd->rsdComponents.dnnPresent)
{
int apnLen;
ConvertApn2Ap(apninfo->apn, (char *)rsd->rsdComponents.dnn.name, &apnLen, rsd->rsdComponents.dnn.length);
strncpy(apninfo->lte_apn, (char *)apninfo->apn, sizeof(apninfo->lte_apn) - 1);
}
else if (app_info->DNNPresent)
{
strncpy(apninfo->apn, (char *)app_info->DNN, sizeof(apninfo->apn) - 1);
strncpy(apninfo->lte_apn, (char *)apninfo->apn, sizeof(apninfo->lte_apn) - 1);
}
if (rsd->rsdComponents.pduSessionTypePresent)
{
if (rsd->rsdComponents.pduSessionType == 3)
apninfo->iptype = IPV4V6;
else if (rsd->rsdComponents.pduSessionType > 3)
apninfo->iptype = TYPE_ETH;
else
apninfo->iptype = rsd->rsdComponents.pduSessionType;
}
apninfo->Extra_params.data_on_roaming = 1;
cm_ctx = create_new_pdp_ctx(apninfo);
if (cm_ctx)
{
cm_ctx->pdpinfo->ursp_list = high_pri_ursp_list;
cm_ctx->pdpinfo->rsd_index = rsd_index;
cm_ctx->pdpinfo->ursp_total = ursp_num;
cm_ctx->pdpinfo->ursp_processed = 1;
cm_ctx->pdpinfo->rsd_processed = 1;
CM_Log(create_new_pdp_ctx_by_ursp5094, "create_new_pdp_ctx_by_ursp: rsd_index %d", rsd_index);
}
}
}
return cm_ctx;
}
static void cm_send_ursp_rsp_2atcmd(int fd, UrspCommRsp *rsp)
{
if (rsp && fd > 0)
{
write(fd, rsp, sizeof(*rsp));
CM_Log(cm_send_ursp_rsp_2atcmd5134, "cm_send_ursp_rsp_2atcmd: send done with fd %d", fd);
}
}
static UrspCommRsp *cm_prepare_ursp_rsp(CM_Connection_Context *ctx, int fail_code)
{
int cid = cm_get_current_cid();
RSD *rsd = NULL;
UrspCommRsp *rsp = NULL;
rsp = malloc(sizeof(UrspCommRsp));
if (!rsp)
return NULL;
memset(rsp, 0, sizeof(UrspCommRsp));
if (ctx && fail_code == 0)
{
rsp->result = 1;
rsp->cid = cid;
if (ctx->pdpinfo && ctx->pdpinfo->ursp_req)
rsp->reqID = ctx->pdpinfo->ursp_req->reqID;
if (ctx->pdpinfo && ctx->pdpinfo->ursp_list)
{
rsd = &(ctx->pdpinfo->ursp_list->ursp.matchedUrspInfo.rsd[ctx->pdpinfo->rsd_index]);
memcpy(&(rsp->active_rsd), rsd, sizeof(rsp->active_rsd));
}
}
else
{
rsp->result = 0;
rsp->cid = cid;
}
CM_Log(cm_prepare_ursp_rsp5167, "cm_prepare_ursp_rsp: result %d for cid %d", rsp->result, cid);
return rsp;
}
static void accept_ursp_receive_cb(struct uloop_fd *u, unsigned int events)
{
UNUSED(events);
int data_len = 0;
ursp_req_s msg_buffer;
char *urspBuf = NULL;
UrspCtx *urspCtx = NULL;
int urspDataLen = 0;
CM_Connection_Context *ConInfo = NULL;
ursp_list_s *ursp_list = NULL;
int i = 0;
UrspCommRsp *rsp = NULL;
char discard_buffer[100];
int fail_code = 1;
memset(&msg_buffer, 0, sizeof(msg_buffer));
data_len = read(u->fd, &msg_buffer, sizeof(msg_buffer));
CM_Log(accept_ursp_receive_cb5146, "accept_ursp_receive_cb: socket fd %d data len %d, urspCtxNum %d, mode %d", u->fd, data_len, msg_buffer.urspCtxNum, msg_buffer.mode);
urspDataLen = VALID_URSP_NUM * sizeof(UrspCtx);
urspBuf = malloc(urspDataLen);
if (urspBuf == NULL)
goto end;
memset(urspBuf, 0, urspDataLen);
data_len = read(u->fd, urspBuf, urspDataLen);
while (data_len != urspDataLen)
{
i = read(u->fd, urspBuf + data_len, urspDataLen - data_len);
if (i < 0)
break;
data_len += i;
}
CM_Log(accept_ursp_receive_cb5535, "accept_ursp_receive_cb: read more date_len %d", data_len);
/* create pdp */
if (msg_buffer.mode == URSP_ACTION_CREATE_PDP)
{
urspCtx = (UrspCtx *)urspBuf;
for (i = 0; i < msg_buffer.urspCtxNum; i++)
{
ursp_list = cm_new_ursp_list();
if (ursp_list)
{
memcpy(&(ursp_list->ursp), urspCtx, sizeof(UrspCtx));
urspCtx++;
}
}
ConInfo = create_new_pdp_ctx_by_ursp(msg_buffer.urspCtxNum, &msg_buffer.appInfo);
if (ConInfo)
{
ConInfo->pdpinfo->ursp_req = malloc(sizeof(ursp_req_s));
if ( ConInfo->pdpinfo->ursp_req == NULL)
goto end;
memset(ConInfo->pdpinfo->ursp_req, 0, sizeof(ursp_req_s));
memcpy(ConInfo->pdpinfo->ursp_req, &msg_buffer, sizeof(ursp_req_s));
start_dialer:
CM_StartDialer(ConInfo);
if (CM_CheckContextValid(ConInfo))
{
if ((ConInfo->dialFailureCode != 0) && (ConInfo->dialFailureCode != PDP_FAIL_GET_GLOBALIP)) {
if (ConInfo->pdpinfo->rsd_processed < ConInfo->pdpinfo->ursp_list->ursp.matchedUrspInfo.numOfRSD) {
ConInfo->connectStatus = CM_CONNECT_CONNING;
//call redial method here
//send_redialmsg_to_redialthread(ConInfo->pdpinfo->connectionNum, REDIAL_NEXT_RSD);
if (update_pdp_ctx_by_rsd(ConInfo))
goto start_dialer;
} else if (ConInfo->pdpinfo->ursp_processed < ConInfo->pdpinfo->ursp_total){
ConInfo->connectStatus = CM_CONNECT_CONNING;
//call redial method here
//send_redialmsg_to_redialthread(ConInfo->pdpinfo->rsd_index, REDIAL_NEXT_RSD);
if (update_pdp_ctx_by_ursp(ConInfo))
goto start_dialer;
}
}
else
{
fail_code = 0;
}
}
}
}
else if (msg_buffer.mode == URSP_ACTION_DESTROY_PDP)
{
DeleteIPInfo(msg_buffer.cid, IPV4);
DeleteIPInfo(msg_buffer.cid, IPV6);
StopDialer(msg_buffer.cid + 1);
//send_disconnect_2host(msg_buffer.cid, IPV4V6);
}
else if (msg_buffer.mode == URSP_ACTION_ADD_ROUTER)
{
}
end:
/*read all data in socket*/
data_len = read(u->fd, discard_buffer, sizeof(discard_buffer));
while (data_len > 0)
{
data_len = read(u->fd, discard_buffer, sizeof(discard_buffer));
}
rsp = cm_prepare_ursp_rsp(ConInfo, fail_code);
if (rsp)
{
cm_send_ursp_rsp_2atcmd(u->fd, rsp);
free(rsp);
}
cm_free_ursp_list();
if (ConInfo && ConInfo->pdpinfo)
{
ConInfo->pdpinfo->ursp_list = NULL;
ConInfo->pdpinfo->ursp_total = 0;
ConInfo->pdpinfo->ursp_processed = 0;
ConInfo->pdpinfo->rsd_index = -1;
ConInfo->pdpinfo->rsd_processed = 0;
if (ConInfo->pdpinfo->ursp_req)
{
free(ConInfo->pdpinfo->ursp_req);
ConInfo->pdpinfo->ursp_req = NULL;
}
}
CM_Log(accept_ursp_receive_cb5271, "accept_ursp_receive_cb: done ");
}
static void *ursp_server_task(void *argv)
{
UNUSED(argv);
int connected_fd = -1;
int sleep_msec = 0;
int accept_fail_times = 0;
unlink(CM_URSP_CONN_SOCKET);
umask(0177);
cm_ursp_server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, CM_URSP_CONN_SOCKET, NULL);
if (cm_ursp_server_fd.fd < 0) {
CM_Log_E(ursp_server_task, "[ursp] usock failed\n");
return NULL;
}
while (1) {
connected_fd = accept(cm_ursp_server_fd.fd, NULL, 0);
if (connected_fd < 0) {
accept_fail_times++;
if (accept_fail_times < 22)
sleep_msec = pow(2, accept_fail_times);
else
sleep_msec = 1000*3600;
CM_Log_E(ursp_server_task4682, "[ursp] accept socket failed times %d, sleep_msec %d\n", accept_fail_times, sleep_msec);
usleep(sleep_msec*1000);
} else
break;
}
CM_Log(ursp_server_task4687, "[ursp] accept client fd %d", connected_fd);
cm_ursp_server_accept_fd.fd = connected_fd;
cm_ursp_server_accept_fd.cb = accept_ursp_receive_cb;
uloop_fd_add(&cm_ursp_server_accept_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
return NULL;
}
static int ursp_trigger_atcmd_connect(void)
{
char at_str[MAX_STR_LEN];
int size = 0, ret = 0;
memset(at_str, 0, MAX_STR_LEN);
snprintf(at_str, sizeof(at_str), "AT+LOG=15");
size = strlen(at_str) + 1;
CM_Log(ursp_trigger_atcmd_connect5639, "ursp_trigger_atcmd_connect:send_atcmd %s\n", at_str);
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, NULL, 0, 0);
if (ret != UBUS_STATUS_OK) {
CM_Log_E(ursp_trigger_atcmd_connect5649, "ursp_trigger_atcmd_connect, ubus_invoke failed %s\n", ubus_strerror(ret));
}
return ret;
}
#endif
static void cm_ursp_init(void)
{
#ifdef CONFIG_CM_URSP
pthread_create(&ursp_server_tid, NULL, ursp_server_task, NULL);
usleep(1000);
ursp_trigger_atcmd_connect();
#endif
}
#ifdef CM_CONFIG_TOE
static void cm_trigger_tft_query_complete_cb(struct ubus_request *req, int ret)
{
UNUSED(ret);
CM_Log(cm_trigger_tft_query_complete_cb, "cm_trigger_tft_query_complete_cb: ret = %d", ret);
if (req) {
free(req);
req = NULL;
}
}
int cm_trigger_tft_query(bool force)
{
int ret_val = UBUS_STATUS_OK;
struct ubus_request *req = NULL;
CM_Connection_Context *ctx = NULL;
int i = 0;
bool need_query = false;
if (!cm_ctx)
return -1;
if (force == false) {
for (i = 1; i < MAX_CID_LIMITATION; i++) {
ctx = cm_get_ctx_by_cid(i);
if (ctx && (ctx->connectStatus == CM_CONNECT_CONSUCCESS ||ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)) {
if (g_toe_tft_param[i-1].mcid != CM_INVALID_CID && g_toe_tft_param[i-1].pdu != 0)
{
CM_Log(cm_trigger_tft_query5663, "cm_trigger_tft_query: cid [%d] qfi [%d] pdu [%d] not changed",
g_toe_tft_param[i-1].mcid, g_toe_tft_param[i-1].qfi, g_toe_tft_param[i-1].pdu);
}
else {
need_query = true;
}
}
}
if (need_query == false)
{
CM_Log(cm_trigger_tft_query56635674, "cm_trigger_tft_query: all tft not changed, no need CGTFT query, config toe directly");
cm_toe_tuple_send();
return 0;
}
}
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_QUERY_TFT, NULL, 0);
req = (struct ubus_request *)malloc(sizeof(struct ubus_request));
if (!req)
return -1;
if ((ret_val =
ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) {
CM_Log_E(cm_trigger_tft_query5331, "cm_trigger_tft_query: fail: %s\n", ubus_strerror(ret_val));
free(req);
return -1;
} else {
req->data_cb = NULL;
req->complete_cb = cm_trigger_tft_query_complete_cb;
ubus_complete_request_async(cm_ctx, req);
}
if (ret_val != UBUS_STATUS_OK)
ret_val = -1;
CM_Log(cm_trigger_tft_query5343, "cm_trigger_tft_query: ret %d\n", ret_val);
return ret_val;
}
static void genl_receive_cb(struct uloop_fd *u, unsigned int events)
{
UNUSED(events);
CM_Log(genl_receive_cb, "genl_receive_cb sock_fd %d", u->fd);
genl_parse_msg(u->fd);
cm_trigger_tft_query(false);
}
#endif
int get_etiflag()
{
int ret_val = UBUS_STATUS_OK;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_ETIFLAG, NULL, 0);
if ((ret_val =
ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, get_etiflag_request_cb, 0, 0)) != UBUS_STATUS_OK) {
CM_Log_E(get_etiflag1, "get_etiflag: ubus_invoke RIL_REQUEST_GET_ETIFLAG failed %s\n", ubus_strerror(ret_val));
goto end;
}
if (ret_val == UBUS_STATUS_OK)
ret_val = g_cell_basic_info.etiflag;
else
ret_val = -1;
end:
CM_Log(get_etiflag2, "get_etiflag: %d\n", ret_val);
return ret_val;
}
#ifdef CONFIG_CM_P701
static int cm_get_imsi_mccmnc(char *mccmnc)
{
int ret = UBUS_STATUS_OK;
if (strlen(g_cell_basic_info.IMSI) > 0)
{
/*mnc is 2 digitals*/
memcpy(mccmnc, g_cell_basic_info.IMSI, 5);
}
else
{
ret = get_imsi(true, false);
if (ret != UBUS_STATUS_OK) {
goto exit;
}
memcpy(mccmnc, g_cell_basic_info.IMSI, 5);
}
exit:
CM_Log_E(cm_get_imsi_mccmnc1, "cm_get_imsi_mccmnc: get mccmnc %s with ret %d\n", strlen(mccmnc)?mccmnc:"NULL", ret);
return ret;
}
#endif
/*@return 0: no need special handle 1: need NULL APN attach*/
static int cm_imsi_special_handle()
{
int ret;
#if 0
char mccmnc[7] = {0};
int i;
if ( cm_get_imsi_mccmnc(mccmnc) != UBUS_STATUS_OK)
{
CM_Log_E(cm_imsi_special_handle, "%s: FATAL ERROR!\n", __func__);
goto end;
}
for (i = 0; i < 4; i++)
{
if (!strcmp(mccmnc, gGetelNullApnImsi[i]))
{
ret = 1;
break;
}
}
end:
CM_Log(cm_imsi_special_handle, "cm_imsi_special_handle: return with ret %d\n", ret);
#endif
/*0: NULL APN attach*/
ret = get_etiflag();
return (ret == 0)?1:0;
}
int g_pdn_type_zcfg = 0;
static void cm_get_pdn_type_zcfg_ril_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_GET_ZCFGBYID) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
g_pdn_type_zcfg = *(int *)response_data;
CM_Log(cm_get_pdn_type_zcfg_ril_cb3, "cm_get_pdn_type_zcfg_ril_cb: g_pdn_type_zcfg %d\n", g_pdn_type_zcfg);
rilutil_freeResponseData(requestid, response_data, response_len);
}
}
/*1 : zgdcont will modify attach apn, 0: zgdcont not modify attach apn*/
int g_zgdcont_attach_zcfg = 1;
static void cm_get_zgdcont_attach_zcfg_ril_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(type);
UNUSED(req);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_GET_ZCFGBYID) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (*(int *)response_data == 1)
g_zgdcont_attach_zcfg = 0;
else
g_zgdcont_attach_zcfg = 1;
CM_Log(cm_get_zgdcont_attach_zcfg_ril_cb3, "%s: g_pdn_type_zcfg %d\n", __func__, g_zgdcont_attach_zcfg);
rilutil_freeResponseData(requestid, response_data, response_len);
}
}
static int cm_get_pdn_type_zcfg_ril()
{
int ret_val = 0;
int zcfg_id = 11;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_ZCFGBYID, (void *)&zcfg_id, sizeof(zcfg_id)/sizeof(int));
ret_val = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, cm_get_pdn_type_zcfg_ril_cb, 0, 0);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(cm_get_pdn_type_zcfg_ril, "cm_get_pdn_type_zcfg_ril: ubus_invoke RIL_REQUEST_GET_ZCFGBYID failed %s\n", ubus_strerror(ret_val));
}
ret_val = g_pdn_type_zcfg;
CM_Log(cm_get_pdn_type_zcfg_ril1, "cm_get_pdn_type_zcfg_ril: ret %d \n", ret_val);
return ret_val;
}
/**
@return: 0 - ZGDCONT will not modify attach APN, 1 - ZGDCONT will modify attach APN
*/
static int cm_get_zgdcont_attach_zcfg_ril()
{
int ret_val = 0;
int zcfg_id = 14;
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_GET_ZCFGBYID, (void *)&zcfg_id, sizeof(zcfg_id)/sizeof(int));
ret_val = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, cm_get_zgdcont_attach_zcfg_ril_cb, 0, 0);
if (ret_val != UBUS_STATUS_OK) {
CM_Log_E(cm_get_zgdcont_attach_zcfg_ril, "%s: ubus_invoke RIL_REQUEST_GET_ZCFGBYID failed %s\n", __func__, ubus_strerror(ret_val));
}
ret_val = g_zgdcont_attach_zcfg;
CM_Log(cm_get_zgdcont_attach_zcfg_ril1, "%s: ret %d \n",__func__, ret_val);
return ret_val;
}
static int cm_get_special_handle_flag()
{
struct uci_context *local_ctx = NULL;
struct uci_package *p = NULL;
struct uci_section *s = NULL;
int ret = 0;
local_ctx = (struct uci_context *)uci_wan_ctx_get();
if (!local_ctx) {
goto end;
}
p = get_uci_package(local_ctx, WAN_PACKAGE_NAME, false);
if (!p) {
goto end;
}
s = uci_lookup_section(local_ctx, p, SEC_GETELCOM);
if (!s) {
goto end;
}
CM_Log(cm_get_special_handle_flag3, "%s: section type %s\n", __func__, s->type);
if (!strcmp(s->type, "1"))
ret = 1;
end:
CM_Log(cm_get_special_handle_flag4, "%s: ret %d\n", __func__, ret);
return ret;
}
void init_zgdcont_pdp_info(void)
{
unsigned int i = 1;
Apn_Info *apn_info = NULL, *default_apn = NULL;
for ( i = 1; i < (sizeof(atcmd_apn_info) / sizeof(atcmd_apn_info[0])); i++)
{
apn_info = &atcmd_apn_info[i];
if (load_pdp_info_from_uci(apn_info, i) == CM_OK)
{
CM_Log(init_zgdcont_pdp_info, "%s: load pdp info for cid %d done\n", __func__, i);
if ( i == CM_DEFAULT_ATTACH_CID)
{
default_apn = get_default_apninfo(g_work_apn, NULL);
if (default_apn && default_apn->auto_apn)
{
CM_Log(init_zgdcont_pdp_info5070, "[AT DIAL] init_zgdcont_pdp_info: auto apn , cid %d, connection_num %d", default_apn->cid, default_apn->connection_num);
default_apn->cid = CM_DEFAULT_ATTACH_CID;
CM_Log(init_zgdcont_pdp_info5072, "[AT DIAL] init_zgdcont_pdp_info: auto apn , cid %d, apn %s, iptype %d", default_apn->cid, strlen(default_apn->apn) ? default_apn->apn : "NULL", default_apn->iptype);
send_zgdcont_info_2atcmd(default_apn);
continue;
}
}
send_zgdcont_info_2atcmd(apn_info);
}
}
}
void init_zgdcont_default_pdp_info(void)
{
Apn_Info *apn_info = NULL, *default_apn = NULL;
unsigned int default_cid = CM_DEFAULT_ATTACH_CID;
if (default_cid >= (sizeof(atcmd_apn_info) / sizeof(atcmd_apn_info[0])))
return;
apn_info = &atcmd_apn_info[default_cid];
if (load_pdp_info_from_uci(apn_info, CM_DEFAULT_ATTACH_CID) == CM_OK)
{
default_apn = get_default_apninfo(g_work_apn, NULL);
if (default_apn && default_apn->auto_apn)
{
default_apn->cid = CM_DEFAULT_ATTACH_CID;
send_zgdcont_info_2atcmd(default_apn);
return;
}
send_zgdcont_info_2atcmd(apn_info);
}
}
int cm_save_default_apn(char *apn, char *lte_apn)
{
Apn_Info *apn_info = NULL;
unsigned int default_cid = CM_DEFAULT_ATTACH_CID;
bool need_save = false;
int ret = 0;
if (default_cid >= (sizeof(atcmd_apn_info) / sizeof(atcmd_apn_info[0])))
return ret;
apn_info = &atcmd_apn_info[default_cid];
if (apn == NULL && lte_apn == NULL)
{
/* which means SIM changed to reset APN to NULL*/
if (strlen(apn_info->apn) > 0)
{
apn_info->apn[0] = '\0';
need_save = true;
}
if (strlen(apn_info->lte_apn) > 0)
{
apn_info->lte_apn[0] = '\0';
need_save = true;
}
}
if (apn && strlen(apn))
{
if (strlen(apn_info->apn) == 0)
{
strncpy(apn_info->apn, apn, sizeof(apn_info->apn) - 1);
if (strlen(apn_info->lte_apn) == 0)
strncpy(apn_info->lte_apn, apn, sizeof(apn_info->lte_apn) - 1);
need_save = true;
}
}
if (lte_apn && strlen(lte_apn))
{
if (strlen(apn_info->lte_apn) == 0)
{
strncpy(apn_info->lte_apn, lte_apn, sizeof(apn_info->lte_apn) - 1);
if (strlen(apn_info->apn) == 0)
strncpy(apn_info->apn, lte_apn, sizeof(apn_info->apn) - 1);
need_save = true;
}
}
if (need_save)
{
ret = add_pdp_info_into_uci(apn_info);
CM_Log(cm_save_default_apn1, "%s: add pdp info with cid %d done with ret %d",__func__, apn_info->cid, ret);
}
return ret;
}
void cm_process_cgdcont_msg(fifo_msg_cgdcont_s *msg)
{
Apn_Info *apn_info = &atcmd_apn_info[msg->cid];
if (msg->is_delete)
{
/* clear up uci*/
#ifdef CONFIG_ZGDCONT_SAVE_PDP
if (delete_pdp_info_from_uci(apn_info) != CM_OK)
CM_Log(cm_process_cgdcont_msg5053, "[AT DIAL] %s: delete pdp info with cid %d failed",__func__, msg->cid);
#endif
memset(apn_info, 0 , sizeof(Apn_Info));
return;
}
strcpy(apn_info->apn, msg->apn);
strcpy(apn_info->lte_apn, msg->apn);
strcpy(apn_info->type, "default");
if (strlen(msg->netif) > 0)
strcpy(apn_info->netif, msg->netif);
else
memset(apn_info->netif, 0, MAX_STR_LEN);
apn_info->cid = msg->cid;
apn_info->iptype = msg->ip_type;
apn_info->Extra_params.lte_default = msg->is_default;
#ifdef CONFIG_CM_URSP
memcpy(&(apn_info->config_rsd), &(msg->config_rsd), sizeof(apn_info->config_rsd));
CM_Log(cm_process_cgdcont_msg6221, "[AT DIAL] %s: sscModePresent %d, sscMode %d, snssaiPresent %d, snssai %s, preferredAccessTypePresent %d, preferredAccessType %d ",
__func__,apn_info->config_rsd.sscModePresent, apn_info->config_rsd.sscMode, apn_info->config_rsd.snssaiPresent,
strlen(apn_info->config_rsd.snssai) ? apn_info->config_rsd.snssai : "NULL", apn_info->config_rsd.prefAccessTypePresent, apn_info->config_rsd.prefAccessType);
#endif
#if 0
#ifndef PIPE_MANUAL_CONNECT
apn_info->Extra_params.autoconnect = CM_CONTYPE_AUTO;
apn_info->Extra_params.always_on = 1;
#endif
apn_info->Extra_params.data_on_roaming = 1;
update_apn_info_connnum(apn_info);
#endif
/* enable data on roaming by default */
if (data_on_roaming_configed == FALSE)
apn_info->Extra_params.data_on_roaming = 1;
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if (apn_info->cid == CM_DEFAULT_ATTACH_CID)
{
apn_info->Extra_params.lte_default = 1;
apn_info->auto_apn = is_pdp_auto_apn(g_work_apn, apn_info->type);
}
else
{
apn_info->Extra_params.lte_default = 0;
apn_info->auto_apn = 0;
//apn_info->Extra_params.autoconnect = CM_CONTYPE_MANUAL;
}
#else
if (cm_get_special_handle_flag() == 1)
{
if (cm_get_pdn_type_zcfg_ril() == 1 ||cm_imsi_special_handle() == 1)
{
apn_info->connection_num = apn_info->cid;
goto end;
}
}
else
{
if (cm_imsi_special_handle() == 1)
{
apn_info->connection_num = apn_info->cid;
goto end;
}
}
if (cm_get_zgdcont_attach_zcfg_ril() == 0)
{
apn_info->connection_num = apn_info->cid;
goto end;
}
#endif
apn_info->connection_num = apn_info->cid;
if (!apn_info->Extra_params.lte_default)
{
goto end;
}
else
{
#ifdef CONFIG_ZGDCONT_MULTI_PDP
if ( is_pdp_auto_apn(g_work_apn, apn_info->type))
goto end;
#endif
SetInitialAttachAPN(apn_info, true);
}
end:
#ifdef CONFIG_ZGDCONT_SAVE_PDP
apn_info->enable = 1;
if (add_pdp_info_into_uci(apn_info) != CM_OK)
CM_Log(cm_process_cgdcont_msg5137, "[AT DIAL] %s: add pdp info with cid %d failed",__func__, msg->cid);
#endif
CM_Log(cm_process_cgdcont_msg, "[AT DIAL] %s: cid %d, ip_type %d, is_default %d, lte apn [%s], data_on_roaming[%d],auto_connect[%d],always_on[%d], mtu [%d]", __func__,
apn_info->cid, apn_info->iptype, apn_info->Extra_params.lte_default, apn_info->lte_apn, apn_info->Extra_params.data_on_roaming,
apn_info->Extra_params.autoconnect, apn_info->Extra_params.always_on, apn_info->mtu);
}
void cm_process_auth_msg(fifo_msg_auth_s *msg)
{
Apn_Info *apn_info = &atcmd_apn_info[msg->cid];
strcpy(apn_info->type, "default");
apn_info->cid = msg->cid;
update_apn_info_authtype_str(apn_info, msg->auth_type);
if (msg->auth_type != 0) {
strcpy(apn_info->usrname, msg->username);
strcpy(apn_info->lte_usrname, msg->username);
strcpy(apn_info->paswd, msg->password);
strcpy(apn_info->lte_paswd, msg->password);
}
else
{
strcpy(apn_info->usrname, "any");
strcpy(apn_info->lte_usrname, "any");
strcpy(apn_info->paswd, "any");
strcpy(apn_info->lte_paswd, "any");
}
if (cm_get_special_handle_flag() == 1)
{
if (cm_get_pdn_type_zcfg_ril() == 1 ||cm_imsi_special_handle() == 1)
{
goto end;
}
}
if (cm_get_zgdcont_attach_zcfg_ril() == 0)
goto end;
if (apn_info->Extra_params.lte_default)
SetInitialAttachAPN(apn_info, true);
end:
#ifdef CONFIG_ZGDCONT_SAVE_PDP
if (add_pdp_auth_info_into_uci(apn_info) != CM_OK)
CM_Log(cm_process_auth_msg5182, "[AT DIAL] %s: update auth info into uci failed",__func__);
#endif
CM_Log(cm_process_auth_msg, "[AT DIAL] %s: [cid] [%d] auth [%d] username [%s] password [%s]", __func__, msg->cid, msg->auth_type,
strlen(msg->username)?msg->username:"NULL", strlen(msg->password)?msg->password:"NULL");
}
void cm_set_atcmd_apn_state(int cid, int state)
{
if (cid <= 0 ||(unsigned int)cid >= sizeof(atcmd_apn_state)/sizeof(atcmd_apn_state[0]))
return;
atcmd_apn_state[cid] = state;
}
int cm_get_atcmd_apn_state(int cid)
{
if (cid <= 0 || (unsigned int)cid >= sizeof(atcmd_apn_state)/sizeof(atcmd_apn_state[0]))
return 0;
return atcmd_apn_state[cid];
}
void cm_process_act_msg(fifo_msg_act_s *msg)
{
Apn_Info *apn_info = &atcmd_apn_info[msg->cid];
apn_info->enable = msg->state;
apn_info->cid = msg->cid;
if (apn_info->connection_num == 0)
apn_info->connection_num = apn_info->cid;
cm_set_atcmd_data_call(apn_info);
}
void cm_process_confex_msg(fifo_msg_confex_s *msg)
{
int i = 0;
Apn_Info *apn_info = NULL;
if (msg->cid == 0xFF)
{
for (i = 0; i < (signed)ARRAY_SIZE(atcmd_apn_info) - 1; i++)
{
apn_info = &atcmd_apn_info[i+1];
if (msg->data_on_roaming_present)
{
apn_info->Extra_params.data_on_roaming = msg->data_on_roaming;
data_on_roaming_configed = TRUE;
}
if (msg->auto_connect_present)
apn_info->Extra_params.autoconnect = msg->auto_connect;
if (msg->data_on_boot_present)
apn_info->Extra_params.always_on = msg->data_on_boot;
if (add_pdp_ext_info_into_uci(apn_info) != CM_OK)
CM_Log(cm_process_confex_msg1, "[AT DIAL] %s: add pdp ext info with cid %d failed",__func__, msg->cid);
}
}
else if (msg->cid < (signed)ARRAY_SIZE(atcmd_apn_info))
{
apn_info = &atcmd_apn_info[msg->cid];
if (msg->data_on_roaming_present)
apn_info->Extra_params.data_on_roaming = msg->data_on_roaming;
if (msg->auto_connect_present)
apn_info->Extra_params.autoconnect = msg->auto_connect;
if (msg->data_on_boot_present)
apn_info->Extra_params.always_on = msg->data_on_boot;
if (add_pdp_ext_info_into_uci(apn_info) != CM_OK)
CM_Log(cm_process_confex_msg2, "[AT DIAL] %s: add pdp ext info with cid %d failed",__func__, msg->cid);
}
}
void cm_process_mtu_msg(fifo_msg_mtu_s *msg)
{
Apn_Info *apn_info = NULL;
CM_Connection_Context *ctx = NULL;
if (msg == NULL)
return;
if (msg->cid < (signed)ARRAY_SIZE(atcmd_apn_info))
{
apn_info = &atcmd_apn_info[msg->cid];
apn_info->cid = msg->cid;
apn_info->mtu = msg->mtu;
ctx = cm_get_ctx_by_cid(msg->cid);
if (ctx && ctx->pdpinfo)
ctx->pdpinfo->mtu = msg->mtu;
CM_Log(cm_process_mtu_msg, "[AT DIAL] %s: config mtu %d for cid %d",__func__, msg->mtu, msg->cid);
}
return;
}
int cm_get_config_mtu(int cid)
{
Apn_Info *apn_info = NULL;
if (cid < (signed)ARRAY_SIZE(atcmd_apn_info))
{
apn_info = &atcmd_apn_info[cid];
return apn_info->mtu;
}
return 0;
}
void cm_process_switchsim_msg(fifo_msg_switchsim_s *msg)
{
if (msg == NULL)
return;
#ifdef CM_DUAL_SIM_SUPPORT
int ret;
ret = CM_SetMasterSimID(msg->sim_id, NULL);
CM_Log(cm_process_mtu_msg, "[AT DIAL] %s: switch sim_id %d done with ret %d",__func__, msg->sim_id, ret);
#endif
return;
}
int g_netmask = 0;
static void cm_set_netmask_last_oct(int netmask)
{
g_netmask = netmask;
}
int cm_get_netmask_last_oct(void)
{
return g_netmask;
}
static void cm_process_netmask_msg(fifo_msg_netmask_s *msg)
{
CM_Log(cm_process_netmask_msg, "[AT DIAL] %s: netmask %d", __func__, msg->mask);
cm_set_netmask_last_oct(msg->mask);
}
extern unsigned char UnknownPdpCause;
static void cm_query_reject_cause_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
char *response = NULL;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_SEND_ATCMD) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
response = (char *) response_data;
CM_Log(cm_query_reject_cause_cb5078, "cm_query_reject_cause_cb: response %s\n", response);
while(*response++ != '\0')
{
if (*response == ':')
{
response++;
UnknownPdpCause = atoi(response);
CM_Log(cm_query_reject_cause_cb5087, "cm_query_reject_cause_cb: UnknownPdpCause %d\n", UnknownPdpCause);
if (UnknownPdpCause == 50)
set_ipv4_only_allowed(true);
else if (UnknownPdpCause == 51)
set_ipv6_only_allowed(true);
break;
}
}
rilutil_freeResponseData(requestid, response_data, response_len);
}
}
static int cm_query_reject_cause(void)
{
int ret = 0, size = 0;
char at_str[MAX_STR_LEN] = { 0 };
snprintf(at_str, sizeof(at_str) - 1, "AT*REJECTCAUSE=%d", CM_DEFAULT_ATTACH_CID);
size = strlen(at_str) + 1;
CM_Log(cm_query_reject_cause5056, "cm_query_reject_cause: send %s\n", at_str);
blob_buf_init(&cm_b, 0);
rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size);
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, cm_query_reject_cause_cb, 0, 0);
return ret;
}
int g_mnc_length = 2;
int cm_get_mnc_length(void)
{
return g_mnc_length;
}
static void cm_query_admindata_cb(struct ubus_request *req, int type, struct blob_attr *msg)
{
UNUSED(req);
UNUSED(type);
unsigned int requestid;
unsigned int rilerrno;
void *response_data = NULL;
int response_len = 0;
char *response = NULL;
int comma_count = 0;
int mnc_length;
if (rilutil_parseResponseDSMaster(msg, &requestid, &rilerrno, &response_data, &response_len)) {
return;
}
if (response_data) {
if (rilerrno != RIL_E_SUCCESS) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
if (requestid != RIL_REQUEST_SEND_ATCMD) {
rilutil_freeResponseData(requestid, response_data, response_len);
return;
}
response = (char *) response_data;
CM_Log(cm_query_admindata_cb1, "%s: response %s\n", __func__, response);
while(*response++ != '\0')
{
if (*response == ',')
{
comma_count++;
if (comma_count == 1)
{
response++;
if (*response == 0x20)
response++;
{
mnc_length = *response - 0x30;
CM_Log(cm_query_admindata_cb2, "%s: mnc length %d %d\n", __func__, mnc_length, *response);
if (mnc_length == 2 || mnc_length == 3)
g_mnc_length = mnc_length;
goto end;
}
}
}
}
end:
rilutil_freeResponseData(requestid, response_data, response_len);
}
}
int cm_query_admindata(void)
{
int ret = 0, size = 0;
char at_str[MAX_STR_LEN] = { 0 };
snprintf(at_str, sizeof(at_str) - 1, "AT*ADMINDATA?");
size = strlen(at_str) + 1;
CM_Log(cm_query_admindata6396, "%s:: send %s\n", __func__, at_str);
blob_buf_init(&cm_b, 0);
ret = rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size);
if (ret != UBUS_STATUS_OK) {
ret = UBUS_STATUS_UNKNOWN_ERROR;
goto end;
}
ret = ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, cm_query_admindata_cb, 0, 0);
end:
return ret;
}
static void dump_buffer(char *buf, int buf_size)
{
char *printf_buf = NULL;
char temp_buf[8] = { '\0' };
int i = 0;
printf_buf = malloc(buf_size * 2 + 1);
memset(printf_buf, 0, buf_size * 2 + 1);
for (i = 0; i < buf_size; i++)
{
sprintf(temp_buf, "%02x", buf[i]);
strcat(printf_buf, temp_buf);
//sprintf(printf_buf + 2*i, "%02x", *(pbuf+i));
}
CM_Log(dump_buffer, "[AT DIAL] %s: size %d, hex %s", __func__, buf_size, printf_buf);
free(printf_buf);
}
void fifo_read_cb(struct uloop_fd *u, unsigned int events)
{
UNUSED(events);
char buf[512] = { 0 };
fifo_msg_cgdcont_s *msg_cgdcont_p;
fifo_msg_auth_s *msg_auth_p;
fifo_msg_act_s *msg_act_p;
fifo_msg_confex_s *msg_confex_p;
fifo_msg_netmask_s *msg_netmask_p;
fifo_msg_mtu_s *msg_mtu_p;
fifo_msg_switchsim_s *msg_switchsim_p;
fifo_msg_type_e msg_type = FIFO_MSG_MAX;
int data_len = 0;
char *pbuf = NULL;
while(1)
{
if (u->error)
{
CM_Log_E(fifo_read_cbe5056, "[AT DIAL] %s: met error for fd %d, registered %d", __func__, u->fd, u->registered);
return;
}
data_len = read(u->fd, &msg_type, sizeof(fifo_msg_type_e));
if (data_len != sizeof(fifo_msg_type_e))
{
CM_Log_E(fifo_read_cbe, "[AT DIAL] %s: error read size %d, receive done", __func__, data_len);
return;
}
CM_Log(fifo_read_cb10, "[AT DIAL] %s: receive msg size %d, type %d", __func__, data_len, msg_type);
pbuf = buf;
memset(buf, 0, 512);
switch(msg_type)
{
case MSG_CGDCONT:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_cgdcont_s));
if (data_len != sizeof(fifo_msg_cgdcont_s))
{
CM_Log_E(fifo_read_cbe1, "[AT DIAL] %s: error MSG CGDCONT read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_cgdcont_s));
return;
}
dump_buffer(pbuf, data_len);
msg_cgdcont_p = (fifo_msg_cgdcont_s *)pbuf;
CM_Log(fifo_read_cb, "[AT DIAL] %s: receive [cgdcont] msg, [cid] - %d,[apn] - %s,[ip_type] - %d", __func__, msg_cgdcont_p->cid, msg_cgdcont_p->apn, msg_cgdcont_p->ip_type);
//coverity[string_null:SUPPRESS]
//coverity[tainted_data:SUPPRESS]
cm_process_cgdcont_msg(msg_cgdcont_p);
break;
case MSG_AUTH:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_auth_s));
if (data_len != sizeof(fifo_msg_auth_s))
{
CM_Log_E(fifo_read_cbe2, "[AT DIAL] %s: error MSG AUTH read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_auth_s));
return;
}
dump_buffer(pbuf, data_len);
msg_auth_p = (fifo_msg_auth_s *)pbuf;
CM_Log(fifo_read_cb1, "[AT DIAL] %s: receive [auth] msg, [cid] %d [auth] %d", __func__, msg_auth_p->cid, msg_auth_p->auth_type);
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_auth_msg(msg_auth_p);
break;
case MSG_ACT:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_act_s));
if (data_len != sizeof(fifo_msg_act_s))
{
CM_Log_E(fifo_read_cbe3, "[AT DIAL] %s: error MSG ACT read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_act_s));
return;
}
dump_buffer(pbuf, data_len);
msg_act_p = (fifo_msg_act_s *)pbuf;
CM_Log(fifo_read_cb2, "[AT DIAL] %s: receive [act] msg, [cid] %d [state] %d", __func__, msg_act_p->cid, msg_act_p->state);
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_act_msg(msg_act_p);
break;
case MSG_ZROAM:
#ifdef CONFIG_CM_P701
cm_get_zroam_list_ril();
#endif
break;
case MSG_CONFEX:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_confex_s));
if (data_len != sizeof(fifo_msg_confex_s))
{
CM_Log_E(fifo_read_cbe3, "[AT DIAL] %s: error MSG CONFEX read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_confex_s));
return;
}
dump_buffer(pbuf, data_len);
msg_confex_p = (fifo_msg_confex_s *)pbuf;
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_confex_msg(msg_confex_p);
break;
case MSG_NETMASK:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_netmask_s));
if (data_len != sizeof(fifo_msg_netmask_s))
{
CM_Log_E(fifo_read_cbe5518, "[AT DIAL] %s: error MSG NETMASK read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_netmask_s));
return;
}
dump_buffer(pbuf, data_len);
msg_netmask_p = (fifo_msg_netmask_s *)pbuf;
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_netmask_msg(msg_netmask_p);
break;
case MSG_MTU:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_mtu_s));
if (data_len != sizeof(fifo_msg_mtu_s))
{
CM_Log_E(fifo_read_cbe5519, "[AT DIAL] %s: error MSG_MTU read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_mtu_s));
return;
}
dump_buffer(pbuf, data_len);
msg_mtu_p = (fifo_msg_mtu_s *)pbuf;
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_mtu_msg(msg_mtu_p);
break;
case MSG_SWITCHSIM:
data_len = read(u->fd, pbuf, sizeof(fifo_msg_switchsim_s));
if (data_len != sizeof(fifo_msg_switchsim_s))
{
CM_Log_E(fifo_read_cbe5519, "[AT DIAL] %s: error MSG_SWITCHSIM read size %d, msg size %d", __func__, data_len, sizeof(fifo_msg_switchsim_s));
return;
}
dump_buffer(pbuf, data_len);
msg_switchsim_p = (fifo_msg_switchsim_s *)pbuf;
//coverity[tainted_data:SUPPRESS]
//coverity[string_null:SUPPRESS]
cm_process_switchsim_msg(msg_switchsim_p);
break;
default:
CM_Log(fifo_read_cbe4, "[AT DIAL] %s: wong msg, read fifo", __func__, msg_act_p->cid, msg_act_p->state);
while((data_len = read(u->fd, pbuf, sizeof(buf))) > 0)
{
dump_buffer(pbuf, data_len);;
}
CM_Log_E(fifo_read_cbe5, "[AT DIAL] %s: read fifo data done", __func__);
return;
break;
}
}
}
int cm_fifo_init(void)
{
int ret, retries;
struct stat buf;
cm_fifo.fname = CM_FIFO_NAME;
CM_Log(cm_fifo_init4, "cm_fifo_init with name %s\n", cm_fifo.fname);
unlink(cm_fifo.fname);
ret = mkfifo(cm_fifo.fname, 0666);
if (ret != 0) {
if (errno == EEXIST) {
if (stat(cm_fifo.fname, &buf) != 0 || !S_ISFIFO(buf.st_mode)) {
CM_Log_E(cm_fifo_init, "%s is not fifo\n", cm_fifo.fname);
return -1;
}
} else {
CM_Log_E(cm_fifo_init1, "fifo not created %s\n", strerror(errno));
return -1;
}
}
retries = 5;
while ((cm_fifo.fdr = open(cm_fifo.fname, O_RDONLY | O_NONBLOCK)) == -1) {
if (errno == EINTR && --retries > 0)
continue;
CM_Log_E(cm_fifo_init2, "failed open %s %s\n", cm_fifo.fname, strerror(errno));
return -1;
}
cm_conn_fd.fd = cm_fifo.fdr;
cm_conn_fd.cb = fifo_read_cb;
uloop_fd_add(&cm_conn_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
CM_Log(cm_fifo_init3, "fifo init done with read fd %d\n", cm_fifo.fdr);
return 0;
}
int cm_start_thread()
{
int connected_fd = -1;
int flags = 0;
unlink(CM_INNER_CONN_SOCKET);
umask(0177);
cm_server_fd.fd = usock(USOCK_UNIX | USOCK_SERVER | USOCK_NONBLOCK, CM_INNER_CONN_SOCKET, NULL);
if (cm_server_fd.fd < 0) {
CM_Log_E(cm_start_thread, "usock failed\n");
return -1;
}
#if 0
cm_server_fd.cb = server_receive_cb;
LOG_OUT("server fd %d", cm_server_fd.fd);
uloop_fd_add(&cm_server_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
#endif
pthread_create(&redial_tid, NULL, redial_task, NULL);
while (1) {
connected_fd = accept(cm_server_fd.fd, NULL, 0);
if (connected_fd < 0) {
CM_Log_E(cm_start_thread1, "accept socket failed\n");
usleep(1000);
} else
break;
}
CM_Log(cm_start_thread2, "accept client fd %d", connected_fd);
flags = fcntl(connected_fd, F_GETFL, 0);
fcntl(connected_fd, F_SETFL, flags|O_NONBLOCK);
cm_accept_fd.fd = connected_fd;
cm_accept_fd.cb = accept_cl_receive_cb;
uloop_fd_add(&cm_accept_fd, ULOOP_READ);
return 0;
}
#if 0
static void cm_toe_tuple_set_timeout(int msec)
{
uloop_timeout_set(&cm_toe_tuple_timeout, msec);
}
static void cm_toe_tuple_cancel_timeout()
{
uloop_timeout_cancel(&cm_toe_tuple_timeout);
}
#define CM_TOE_TUPLE_COUNT_UNSEND 10
int cm_toe_tuple_count(void)
{
struct list_head *head = cm_get_toe_tuple_list_head();
struct toe_tuple_list *tuple = NULL;
int count = 0;
list_for_each_entry(tuple, head, list) {
if (tuple) {
count++;
}
}
}
#endif
#ifdef CM_CONFIG_TOE
void cm_toe_tft_param_init(void)
{
unsigned int i = 0;
memset(g_toe_tft_param, 0, sizeof(g_toe_tft_param));
for ( i = 0; i < ARRAY_SIZE(g_toe_tft_param); i++)
g_toe_tft_param[i].mcid = CM_INVALID_CID;
}
static void cm_toe_tft_param_update_entry(struct toe_tft_param *paras)
{
unsigned int i = 0;
if (!paras)
return;
for (i = 0; i < ARRAY_SIZE(g_toe_tft_param); i++)
{
if (paras->mcid == CM_INVALID_CID)
g_toe_tft_param[i].mcid = CM_INVALID_CID;
else
{
if (i == paras->mcid - 1)
{
memcpy(&g_toe_tft_param[i], paras, sizeof(struct toe_tft_param));
CM_Log(cm_toe_tft_param_update_entry5508, "cm_toe_tft_param_update_entry: tft_param[%d] cid %d, qfi %d, pdu %d\n", i, g_toe_tft_param[i].mcid, g_toe_tft_param[i].qfi, g_toe_tft_param[i].pdu);
break;
}
}
}
return;
}
TftInfoList g_tft_pf_list;
void cm_toe_tft_pf_prepare(PacketFilterInfo *data, int data_len)
{
PacketFilterInfo *ptr = NULL, *target_pf = NULL;
TftInfoList *tft_list_head = &g_tft_pf_list;
int len = 0;
target_pf = &tft_list_head->packetinfo;
for (ptr = data, len = 0; len < data_len; len += sizeof(PacketFilterInfo), ptr++)
{
if (target_pf->PfIdx == 0 && target_pf->EpIdx == 0)
{
memcpy(target_pf, ptr, sizeof(PacketFilterInfo));
tft_list_head->filter_num = 1;
target_pf->next = NULL;
}
else
{
while (target_pf->next)
{
target_pf = target_pf->next;
}
target_pf->next = malloc(sizeof(PacketFilterInfo));
if (target_pf->next == NULL)
goto end;
target_pf = target_pf->next;
memset(target_pf, 0, sizeof(PacketFilterInfo));
memcpy(target_pf, ptr, sizeof(PacketFilterInfo));
tft_list_head->filter_num++;
target_pf->next = NULL;
}
CM_Log(cm_toe_tft_pf_prepare6787, "cm_toe_tft_pf_prepare: add PfIdx %d, EpIdx %d\n", target_pf->PfIdx, target_pf->EpIdx);
}
end:
tft_list_head->cid = tft_list_head->packetinfo.secondaryCid - 1;
CM_Log(cm_toe_tft_pf_prepare6683, "cm_toe_tft_pf_prepare: filter_num %d, cid %d\n", tft_list_head->filter_num, tft_list_head->cid);
}
void cm_toe_tft_pf_list_clear(void)
{
TftInfoList *tft_list_head = &g_tft_pf_list;
PacketFilterInfo *pf_list = NULL;
PacketFilterInfo *pf_list_next = NULL;
pf_list = &tft_list_head->packetinfo;
pf_list_next = pf_list->next;
while(pf_list_next)
{
pf_list = pf_list_next->next;
free(pf_list_next);
pf_list_next = pf_list;
}
memset(tft_list_head, 0, sizeof(TftInfoList));
}
void cm_toe_tft_pf_delete(int p_cid, int cid)
{
qos_delete_qos((unsigned char)p_cid, (unsigned char)cid, false);
}
void cm_toe_tft_pf_update(TftExtendInfo *data, int data_len)
{
TftExtendInfo *ptr = NULL;
TftInfoList *tft_list_head = &g_tft_pf_list;
int i = 0;
int len = 0;
struct toe_tft_param toe_param = { 0 };
for (ptr = data, len = 0; len < data_len; len += sizeof(TftExtendInfo), ptr++, i++)
{
memcpy(&toe_param, ptr, sizeof(toe_param));
cm_toe_tft_param_update_entry(&toe_param);
if ((ptr->mcid - 1) == tft_list_head->cid)
{
memcpy(&tft_list_head->extend_info, ptr, sizeof(TftExtendInfo));
tft_list_head->bearer_type = 1;
if (ptr->p_cid != INVALID_CID && ptr->mcid != ptr->p_cid)
{
tft_list_head->bearer_type = 2;
tft_list_head->Pcid = ptr->p_cid - 1;
}
else
{
tft_list_head->bearer_type = 1;
tft_list_head->Pcid = INVALID_CID;
}
break;
}
}
cm_qos_update_pf(tft_list_head, false);
}
void cm_toe_tft_param_update(void *data, int len)
{
struct toe_tft_param toe_param = { 0 };
unsigned int nums = len/sizeof(struct toe_tft_param) ;
unsigned int i;
struct toe_tft_param *p = ( struct toe_tft_param *)data;
CM_Log(cm_toe_tft_param_update5524, "cm_toe_tft_param_update: len %d\n", len);
for( i = 0; i < nums; i++)
{
memcpy(&toe_param, p, sizeof(toe_param));
p++;
cm_toe_tft_param_update_entry(&toe_param);
}
/* only report one cid once, no need to clean other cid entry */
#if 0
for (i = 0; i < ARRAY_SIZE(g_toe_tft_param); i++)
{
unsigned int j;
p = ( struct toe_tft_param *)data;
for (j = 0; j < nums; j++)
{
if (g_toe_tft_param[i].mcid == p->mcid)
break;
p++;
}
/* clean entry */
if ( j == nums)
g_toe_tft_param[i].mcid = CM_INVALID_CID;
}
#endif
CM_Log(cm_toe_tft_param_update6048, "cm_toe_tft_param_update: done\n");
}
extern CM_Connection_Context *g_CM_Context;
bool cm_ctx_toe_tuple_match(int cid, struct toe_tuple_list *tuple)
{
#define TOE_SNAT 1
CM_Connection_Context *ctx = g_CM_Context;
bool match = false;
while(ctx)
{
if ((ctx->connectStatus == CM_CONNECT_CONSUCCESS ||ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)
&& (ctx->pdpinfo->primaryCid -1) == cid)
{
if (ctx->pdpinfo->IP_Type == tuple->type ||ctx->pdpinfo->IP_Type == IPV4V6)
{
if (tuple->type == IPV4)
{
CM_Log(cm_ctx_toe_tuple_match, "cm_ctx_toe_tuple_match: V4 nat %d, nat_ip 0x%x, src_ip 0x%x, dst_ip 0x%x, cm.ip 0x%x\n",
tuple->tuple.nat, tuple->tuple.nat_ip, tuple->tuple.src_ip, tuple->tuple.dst_ip, ctx->ipv4info->IPAddr);
if (tuple->tuple.nat == TOE_SNAT)
{
if ( tuple->tuple.in_pkt == 0)
{
if (ctx->ipv4info && (unsigned)ctx->ipv4info->IPAddr == tuple->tuple.dst_ip)
{
match = true;
break;
}
}
else if ( tuple->tuple.out_pkt == 0)
{
if (ctx->ipv4info && (unsigned)ctx->ipv4info->IPAddr == tuple->tuple.nat_ip)
{
match = true;
break;
}
}
}
else if (tuple->tuple.nat == 0)
{
if ( tuple->tuple.in_pkt == 0)
{
if (ctx->ipv4info && (unsigned)ctx->ipv4info->IPAddr == tuple->tuple.dst_ip)
{
match = true;
break;
}
}
else if ( tuple->tuple.out_pkt == 0)
{
if (ctx->ipv4info && (unsigned)ctx->ipv4info->IPAddr == tuple->tuple.src_ip)
{
match = true;
break;
}
}
}
}
else if (tuple->type == IPV6)
{
if (ctx->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR)
{
char interface_name[32];
char ipaddress[INET6_ADDRSTRLEN];
snprintf(interface_name, sizeof(interface_name), "ccinet%d", cid);
if (ctx->ipv6info && getInterfaceAddr6(interface_name, ipaddress, sizeof(ipaddress)) == 0)
{
inet_pton(AF_INET6, ipaddress, ctx->ipv6info->IPV6Addr);
CM_Log(cm_ctx_toe_tuple_match6684, "cm_ctx_toe_tuple_match: get global ip successfully for %s", interface_name);
}
else
goto next;
}
CM_Log(cm_ctx_toe_tuple_match5585, "cm_ctx_toe_tuple_match: V6 in %d, out %d, src_ip %x.%x.%x.%x\n, dst_ip %x.%x.%x.%x",
tuple->tuple.in_pkt, tuple->tuple.out_pkt,
tuple->tuple.src_ip6[0], tuple->tuple.src_ip6[1], tuple->tuple.src_ip6[2], tuple->tuple.src_ip6[3],
tuple->tuple.dst_ip6[0], tuple->tuple.dst_ip6[1], tuple->tuple.dst_ip6[2], tuple->tuple.dst_ip6[3]);
if (ctx->ipv6info)
{
CM_Log(cm_ctx_toe_tuple_match6679, "cm_ctx_toe_tuple_match: cm.ipv6 %x.%x.%x.%x\n",
ctx->ipv6info->IPV6Addr[0], ctx->ipv6info->IPV6Addr[1], ctx->ipv6info->IPV6Addr[2], ctx->ipv6info->IPV6Addr[3]);
}
/* inpkt from pdu, downlink */
if ( tuple->tuple.in_pkt == 0)
{
if (ctx->ipv6info && memcmp(ctx->ipv6info->IPV6Addr, tuple->tuple.dst_ip6, 8) == 0)
{
match = true;
break;
}
}
else if ( tuple->tuple.out_pkt == 0)
{
if (ctx->ipv6info && memcmp(ctx->ipv6info->IPV6Addr, tuple->tuple.src_ip6, 8) == 0)
{
match = true;
break;
}
}
}
else
break;
}
}
next:
ctx = ctx->next;
}
CM_Log(cm_ctx_toe_tuple_match6104, "cm_ctx_toe_tuple_match: cid %d, match %d", cid, match);
return match;
}
void cm_toe_tuple_send(void)
{
struct list_head *head = cm_get_toe_tuple_list_head();
struct toe_tuple_list *tuple = NULL;
struct toe_tuple_list *n_tuple = NULL;
unsigned int i = 0;
int ret = 0;
struct toe_tft_param toe_param;
bool param_updated = false;
list_for_each_entry_safe(tuple, n_tuple, head, list) {
if (tuple)
{
param_updated = false;
CM_Log(cm_toe_tuple_send5669, "cm_toe_tuple_send: current tuple %x, in_pkt %d, mcid %d, qri %d, pdu %d, update_tuple %d",
tuple, tuple->tuple.in_pkt, tuple->tuple.mcid, tuple->tuple.qfi, tuple->tuple.pdu, tuple->tuple.update_tuple);
for (i = 0; i < MAX_CID_LIMITATION; i++)
if (cm_ctx_toe_tuple_qos_match(i, tuple, &toe_param) == TRUE)
break;
if (i < MAX_CID_LIMITATION) {
if (tuple->type == IPV4) {
#if 0
if (g_toe_tft_param[i].mcid - 1 == i) {
tuple->tuple.mcid = i;
tuple->tuple.qfi = g_toe_tft_param[i].qfi;
tuple->tuple.pdu = g_toe_tft_param[i].pdu;
}
else {
tuple->tuple.mcid = 0xFF;
tuple->tuple.qfi = 0;
tuple->tuple.pdu = 0;
}
#endif
if (tuple->tuple.mcid != toe_param.mcid) {
tuple->tuple.mcid = toe_param.mcid;
param_updated = true;
}
if (tuple->tuple.qfi != toe_param.qfi) {
tuple->tuple.qfi = toe_param.qfi;
param_updated = true;
}
if (tuple->tuple.pdu != toe_param.pdu) {
tuple->tuple.pdu = toe_param.pdu;
param_updated = true;
}
if (param_updated) {
CM_Log(cm_toe_tuple_send6133, "cm_toe_tuple_send: send v4 tuple %x to kernel with socket fd %d, cid %d, qfi %d, pdu %d", tuple, cm_genl_fd.fd, tuple->tuple.mcid, tuple->tuple.qfi, tuple->tuple.pdu);
ret = genl_set_tuplev4_to_kernel(cm_genl_fd.fd, &tuple->tuple, tuple->src_mac, tuple->dst_mac, tuple->dev_name);
if (ret < 0){
CM_Log_E(cm_toe_tuple_send5631, "cm_toe_tuple_send: send v4 tuple to kernel failed %d", ret);
}
else {
if (tuple->tuple.update_tuple == 0)
tuple->tuple.update_tuple = 1;
}
}
}
else if (tuple->type == IPV6) {
#if 0
if (g_toe_tft_param[i].mcid - 1 == i) {
tuple->tuple.mcid = i;
tuple->tuple.qfi = g_toe_tft_param[i].qfi;
tuple->tuple.pdu = g_toe_tft_param[i].pdu;
}
else {
tuple->tuple.mcid = 0xFF;
tuple->tuple.qfi = 0;
tuple->tuple.pdu = 0;
}
#endif
if (tuple->tuple.mcid != toe_param.mcid) {
tuple->tuple.mcid = toe_param.mcid;
param_updated = true;
}
if (tuple->tuple.qfi != toe_param.qfi) {
tuple->tuple.qfi = toe_param.qfi;
param_updated = true;
}
if (tuple->tuple.pdu != toe_param.pdu) {
tuple->tuple.pdu = toe_param.pdu;
param_updated = true;
}
if (param_updated) {
if (tuple->tuple.xlat_en)
{
CM_Log(cm_toe_tuple_send6149, "cm_toe_tuple_send: xlat enabled, send v4 tuple %x to kernel with socket fd %d, cid %d, qfi %d, pdu %d", tuple, cm_genl_fd.fd, tuple->tuple.mcid, tuple->tuple.qfi, tuple->tuple.pdu);
ret = genl_set_tuplev4_to_kernel(cm_genl_fd.fd, &tuple->tuple, tuple->src_mac, tuple->dst_mac, tuple->dev_name);
}
else
{
CM_Log(cm_toe_tuple_send6149, "cm_toe_tuple_send: send v6 tuple %x to kernel with socket fd %d, cid %d, qfi %d, pdu %d", tuple, cm_genl_fd.fd, tuple->tuple.mcid, tuple->tuple.qfi, tuple->tuple.pdu);
ret = genl_set_tuplev6_to_kernel(cm_genl_fd.fd, &tuple->tuple, tuple->src_mac, tuple->dst_mac, tuple->dev_name);
}
if (ret < 0){
CM_Log_E(cm_toe_tuple_send5639, "cm_toe_tuple_send: send v6 tuple to kernel failed %d", ret);
}
else {
if (tuple->tuple.update_tuple == 0)
tuple->tuple.update_tuple = 1;
}
}
}
}
if (tuple->tuple.in_pkt == PDU_PKT) {
list_del(&tuple->list);
free(tuple);
}
}
}
#if 0
while (!list_empty(head)) {
tuple = list_for_each(head, struct toe_tuple_list, list);
list_del(&tuple->list);
free(tuple);
}
#endif
CM_Log(cm_toe_tuple_send6162, "cm_toe_tuple_send: done");
}
static int cm_gnel_init(void)
{
cm_toe_tft_param_init();
cm_genl_fd.fd = genl_prepare();
if (cm_genl_fd.fd < 0) {
CM_Log_E(cm_start_gnel, "genl_prepare failed\n");
return -1;
}
cm_genl_fd.cb = genl_receive_cb;
uloop_fd_add(&cm_genl_fd, ULOOP_READ | ULOOP_EDGE_TRIGGER);
return 0;
}
#endif
int g_kernel_version_code = 0;
static int get_linux_kernel_version(void)
{
FILE *file = NULL;
char line[300] = { 0 };
char major_verison[50];
char minor_verison[50];
int ret = 0;
file = fopen("/proc/version", "r");
if (!file)
return -1;
if (fgets(line, sizeof(line), file) != NULL) {
CM_Log(get_linux_kernel_version80, "%s: line %s", __func__, line);
memset(major_verison, 0, sizeof(major_verison));
memset(minor_verison, 0, sizeof(minor_verison));
if (sscanf(line, "%[^.].%[^.].%*s", major_verison, minor_verison) != 2) {
ret = -1;
CM_Log(get_linux_kernel_version85,"%s: parse line failed\n", __func__);
goto end;
}
CM_Log(get_linux_kernel_version88, "%s: major_verison %s\n", __func__, major_verison);
CM_Log(get_linux_kernel_version89, "%s: minor_verison %s\n", __func__, minor_verison);
g_kernel_version_code = major_verison[strlen(major_verison) - 1] - '0';
g_kernel_version_code = g_kernel_version_code << 16;
g_kernel_version_code += (atoi(minor_verison) << 8);
CM_Log(get_linux_kernel_version93, "%s: g_kernel_version_code 0x%x\n", __func__, g_kernel_version_code);
}
end:
fclose(file);
return ret;
}
int main(int argc, char **argv)
{
const char *ubus_socket = NULL;
int ch, ret, retries = 0;
//set tag name
set_service_log_tag("cm");
while ((ch = getopt(argc, argv, "pcs:")) != -1) {
switch (ch) {
case 's':
ubus_socket = optarg;
break;
case 'p':
pipe_mode = TRUE;
break;
default:
break;
}
}
argc -= optind;
argv += optind;
CM_Log(main, "Start CM task,time:%s, date:%s\n",__TIME__,__DATE__);
get_linux_kernel_version();
uloop_init();
cm_ctx = ubus_connect(ubus_socket);
if (!cm_ctx) {
goto out;
}
do {
if (RilIdReady())
break;
sleep(1);
} while (retries++ < RIL_MAX_RETRIES);
if (retries >= RIL_MAX_RETRIES) {
goto out1;
}
ubus_add_uloop(cm_ctx);
ret = ubus_add_object(cm_ctx, &cm_object);
if (ret) {
goto out1;
}
ret = ubus_add_object(cm_ctx, &network_activity_obj);
if (ret) {
goto out1;
}
ret = ubus_add_object(cm_ctx, &cm_fail_cause_obj);
if (ret) {
goto out1;
}
ret = WaitForSimReady();
if (ret < 0) {
goto out2;
}
CM_UpdateActivedProfile();
cm_ursp_init();
#ifdef CM_CONFIG_TOE
cm_tftinfo_init();
ret = cm_gnel_init();
#endif
cm_query_reject_cause();
nwactivity_arrary_init();
cm_fifo_init();
//start redial thread
ret = cm_start_thread();
ret = dialer_init();
ret = set_default_data_call();
eng_mode_init();
uloop_run();
out2:
ubus_remove_object(cm_ctx, &cm_object);
out1:
ubus_free(cm_ctx);
out:
uloop_done();
CM_Log_E(main11, "main: exitl\n");
return 0;
}