| ////////////////////////////////////////////////////////////////////// |
| // INCLUDE FILES FOR MODULE |
| ////////////////////////////////////////////////////////////////////// |
| |
| #include "cm_func.h" |
| #include "dialer_task.h" |
| |
| #include <regex.h> |
| |
| ////////////////////////////////////////////////////////////////////// |
| // local Prototypes |
| ////////////////////////////////////////////////////////////////////// |
| |
| CM_Connection_Context *get_match_pdp(Apn_Info * apninfo); |
| bool redial_sleep(int count); |
| void CM_Handle_RoamChange(void); |
| void CM_Handle_NWChange(void); |
| void CM_Handle_Redial(int connectionNum); |
| void CM_Handle_Reject(void); |
| void CM_Handle_DefaultDataCall(void); |
| |
| |
| Apn_Info *get_inital_attach_apn(Mnc_Apn * apn_list, char *cur_apn); |
| Apn_Info *get_fota_apninfo(Mnc_Apn * apn_list); |
| |
| void ClearETIFlag_data_cb(struct ubus_request *req, int type, struct blob_attr *msg); |
| ////////////////////////////////////////////////////////////////////// |
| // Global Variables |
| ////////////////////////////////////////////////////////////////////// |
| pthread_mutex_t cm_mutex = PTHREAD_MUTEX_INITIALIZER; |
| pthread_cond_t cm_cond; |
| |
| //global pdp context list |
| CM_Connection_Context *g_CM_Context = NULL; |
| //-1 -- initial value, 0 -- 2/3G, 1 -- LTE, 3 -- not registered |
| |
| extern bool IsRoaming; |
| extern int NW_status; |
| #define MAX_ESM_TRY_NUM 2 |
| |
| char g_cid = 0; |
| extern Mnc_Apn *g_work_apn; |
| AttachApn_Info * g_attachapn = NULL; |
| |
| //global redial interval |
| redial_interval *g_redial_interval = NULL; |
| |
| extern struct ubus_context *cm_ctx; |
| extern cm_ubus_ctx_id cm_ubus_id; |
| extern struct blob_buf cm_b; |
| extern bool pipe_mode; |
| extern bool NWReady; |
| extern UINT8 g_last_default_cid; |
| |
| ////////////////////////////////////////////////////////////////////// |
| // functions definitions |
| ////////////////////////////////////////////////////////////////////// |
| |
| unsigned char check_roamStatus(void) |
| { |
| return IsRoaming; |
| } |
| |
| CM_Connection_Context *CM_GetCtxListHead(void) |
| { |
| return g_CM_Context; |
| } |
| |
| bool CM_IsDefaultCtxExist() |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| bool exist = false; |
| |
| if (ctx == NULL) |
| return exist; |
| |
| while(ctx) { |
| if (ctx->pdpinfo && ctx->pdpinfo->is_default) { |
| exist = true; |
| break; |
| } |
| ctx = ctx->next; |
| } |
| |
| return exist; |
| } |
| |
| int PrimaryCid_Get(int connectionNum) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| int pri_con; |
| pri_con = connectionNum & SECONDARYPDP_CONNECTNUM_RANGE; |
| |
| tmp_CM_Context = g_CM_Context; |
| |
| while (tmp_CM_Context) { |
| if (tmp_CM_Context->pdpinfo->connectionNum == pri_con) |
| return tmp_CM_Context->pdpinfo->primaryCid; |
| |
| tmp_CM_Context = tmp_CM_Context->next; |
| } |
| |
| CM_Log(PrimaryCid_Get, "PrimaryCid_Get, can't find out the primaryCid\n"); |
| return 0; |
| } |
| |
| //free PacketFilterInfo, called by CM module |
| void TFTinfo_free(PacketFilterInfo * src_pfinfo) |
| { |
| PacketFilterInfo *tmp_pfinfo; |
| |
| tmp_pfinfo = src_pfinfo; |
| while (tmp_pfinfo != NULL) { |
| tmp_pfinfo = tmp_pfinfo->next; |
| free(src_pfinfo); |
| src_pfinfo = tmp_pfinfo; |
| } |
| CM_Log(TFTinfo_free1, "TFTinfo_free done\n"); |
| } |
| |
| void LinkContext_free(Link_Context * linkcontext) |
| { |
| Link_Context *tmp_linkcontext; |
| tmp_linkcontext = linkcontext; |
| while (tmp_linkcontext != NULL) { |
| tmp_linkcontext = tmp_linkcontext->next; |
| free(linkcontext); |
| linkcontext = tmp_linkcontext; |
| } |
| } |
| |
| //disconnect all secondary pdp when the according primary pdp is disconnect receiving ATNOK |
| #if 0 |
| static void CM_Disconnect_SecondaryPDP(char con_num) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| |
| tmp_CM_Context = g_CM_Context; |
| CM_Log("enter %s\n", __func__); |
| while (tmp_CM_Context) { |
| if (((tmp_CM_Context->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == con_num) |
| && (tmp_CM_Context->pdpinfo->PDP_Type == 0)) { |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| } |
| |
| tmp_CM_Context = tmp_CM_Context->next; |
| } |
| CM_Log("leave %s\n", __func__); |
| } |
| #endif |
| /*=========================================================================== |
| FUNCTION CM_Delete_Cur_Context |
| |
| DESCRIPTION |
| Delete the current connection context from the list, called by CM module. |
| |
| INPUT |
| CM_Connection_Context |
| ===========================================================================*/ |
| void CM_Delete_Cur_Context(CM_Connection_Context * cur_CM_Context) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| CM_Connection_Context *tmp_next; |
| tmp_CM_Context = g_CM_Context; |
| |
| CM_Log(CM_Delete_Cur_Context, "enter CM_Delete_Cur_Context, delete context 0x%x, head context 0x%x\n", cur_CM_Context, tmp_CM_Context); |
| |
| if (tmp_CM_Context == NULL) { |
| return; |
| } |
| //the first context is the current delete context |
| if (tmp_CM_Context == cur_CM_Context) { |
| g_CM_Context = tmp_CM_Context->next; |
| CM_Context_free(tmp_CM_Context); |
| return; |
| } |
| |
| tmp_next = tmp_CM_Context->next; |
| |
| while (tmp_next) { |
| if (tmp_next == cur_CM_Context) { |
| tmp_CM_Context->next = tmp_next->next; |
| CM_Context_free(tmp_next); |
| return; |
| } |
| |
| tmp_CM_Context = tmp_next; |
| tmp_next = tmp_next->next; |
| } |
| } |
| |
| //free function for CM_Connection_Context, and release CID here, called by CM module |
| void CM_Context_free(CM_Connection_Context * CM_Context) |
| { |
| if (CM_Context == g_CM_Context) { |
| g_CM_Context = CM_Context->next; |
| } |
| if (CM_Context != NULL) { |
| if (CM_Context->pdpinfo != NULL) { |
| free(CM_Context->pdpinfo); |
| } |
| |
| if (CM_Context->ipv4info != NULL) |
| free(CM_Context->ipv4info); |
| |
| if (CM_Context->ipv6info != NULL) |
| free(CM_Context->ipv6info); |
| |
| //delete tft info list |
| if (CM_Context->tftinfo != NULL) |
| TFTinfo_free(CM_Context->tftinfo); |
| |
| free(CM_Context); |
| } |
| |
| CM_Log(CM_Context_free, "CM_Context_free, context addr:0x%x done\n", CM_Context); |
| } |
| |
| void CM_DeleteAllContext(void) |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| CM_Connection_Context *ctx_next = NULL; |
| |
| ctx_next = ctx; |
| while(ctx) |
| { |
| ctx_next = ctx->next; |
| CM_Delete_Cur_Context(ctx); |
| ctx = ctx_next; |
| } |
| CM_Log(CM_DeleteAllContext, "CM_DeleteAllContext: done, g_CM_Context 0x%x\n", g_CM_Context); |
| } |
| |
| #if 0 |
| static CM_Connection_Context *CM_Exist_DefaultPdp(void) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| tmp_CM_Context = g_CM_Context; |
| |
| if (tmp_CM_Context == NULL) |
| return NULL; |
| |
| while (tmp_CM_Context) { |
| if (tmp_CM_Context->pdpinfo->connectionNum == 0) |
| return tmp_CM_Context; |
| |
| tmp_CM_Context = tmp_CM_Context->next; |
| } |
| |
| return NULL; |
| } |
| #endif |
| |
| bool CM_CheckContextValid(CM_Connection_Context * ConInfo) |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| bool is_valid = false; |
| |
| while (ctx) |
| { |
| if (ctx == ConInfo) |
| { |
| is_valid = true; |
| break; |
| } |
| ctx = ctx->next; |
| } |
| |
| CM_Log(CM_CheckContextValid, "CM_CheckContextValid: context 0x%x validation %d", ConInfo, is_valid); |
| return is_valid; |
| } |
| |
| void CM_StartDialer(CM_Connection_Context * ConInfo) |
| { |
| Data_Call_Response *p_response = NULL; |
| |
| system("echo cm.lock > /sys/power/wake_lock"); |
| |
| if (ConInfo->first_dial == 0) { |
| #ifdef PIPE_MANUAL_CONNECT |
| if (pipe_mode) |
| { |
| int retry_times = 0; |
| CheckDataCallRegisterStatus(); |
| while(NW_status == CM_NW_STATUS_NOT_REGISTERED && retry_times++ < RETRY_NW_REGISTER_TIMES) |
| { |
| sleep(1); |
| CheckDataCallRegisterStatus(); |
| } |
| |
| if (retry_times == RETRY_NW_REGISTER_TIMES) |
| { |
| /*reach max retry times*/ |
| CM_Log(CM_StartDialer, "CM_StartDialer, [PIPE MANUAL MODE] network not registered"); |
| if (CM_CheckContextValid(ConInfo)) |
| { |
| ConInfo->connectStatus = CM_CONNECT_DISCON; |
| ConInfo->dialFailureCode = PDP_FAIL_DATA_REGISTRATION_FAIL; |
| } |
| goto Exit; |
| } |
| } |
| #else |
| /* check the register status anyway*/ |
| CheckDataCallRegisterStatus(); |
| if (NW_status == CM_NW_STATUS_NOT_REGISTERED) { //network not ready if not first dial |
| CM_Log(CM_StartDialer, "CM_StartDialer, network not registered"); |
| if (CM_CheckContextValid(ConInfo)) |
| { |
| ConInfo->connectStatus = CM_CONNECT_WAIT_NWCHANGE; |
| ConInfo->dialFailureCode = 0; |
| } |
| goto Exit; |
| } |
| #endif |
| } |
| else { |
| CM_Log(CM_StartDialer1, "CM_StartDialer: first dial, check data call register status\n"); |
| CheckDataCallRegisterStatus(); |
| if (CM_CheckContextValid(ConInfo)) |
| ConInfo->first_dial = 0; |
| } |
| |
| /* Here check whether context is valid, cause CheckDataCallRegisterStatus is sync invoke, |
| * context may changed in some indication or async invoke data callback */ |
| if (!CM_CheckContextValid(ConInfo)) |
| goto Exit; |
| |
| if (check_roamStatus() && ConInfo->pdpinfo->data_on_roaming == 0) |
| { |
| CM_Log_E(CM_StartDialer333, "CM_StartDialer disable data on roaming, no need to start dialer"); |
| goto Exit; |
| } |
| |
| if (ConInfo->pdpinfo) |
| CM_Log_D(CM_StartDialer333, "CM_StartDialer: start dialer for apn %s, lteapn %s, ip type %d, cid %d", strlen(ConInfo->pdpinfo->APN) ? ConInfo->pdpinfo->APN : "NULL", |
| strlen(ConInfo->pdpinfo->LteAPN) ? ConInfo->pdpinfo->LteAPN : "NULL", ConInfo->pdpinfo->IP_Type, ConInfo->pdpinfo->primaryCid); |
| |
| ConInfo->dialFailureCode = -1; |
| p_response = StartDialer(ConInfo); |
| if (!p_response) { |
| CM_Log_E(CM_StartDialer2, "CM_StartDialer:[ERROR] no dialer response!"); |
| goto Exit; |
| } |
| |
| if (!CM_CheckContextValid(ConInfo)) |
| goto Exit; |
| |
| CM_Log(CM_StartDialer3, "CM_StartDialer: get dialer status %d, ip type %d, cid %d\n", p_response->status, p_response->IP_Type, p_response->cid); |
| |
| if (p_response->status == PDP_DIAL_STATUS_OK || p_response->status == PDP_FAIL_GET_GLOBALIP) { |
| |
| if (p_response->status == PDP_DIAL_STATUS_OK) { |
| ConInfo->connectStatus = CM_CONNECT_CONSUCCESS; |
| ConInfo->dialFailureCode = 0; |
| ConInfo->dial_cnt = 0; |
| } |
| else { |
| ConInfo->connectStatus = CM_CONNECT_GET_GLOBALIP_ERR; |
| ConInfo->dialFailureCode = p_response->status; |
| } |
| |
| /*here shoud use mtu in pdp context*/ |
| if (p_response->mtu <= 0) |
| p_response->mtu = ConInfo->pdpinfo->mtu; |
| |
| ConInfo->pdpinfo->IP_Type = p_response->IP_Type; |
| if (ConInfo->pdpinfo->PDP_Type == 1) |
| ConInfo->pdpinfo->primaryCid = p_response->cid; |
| else { |
| ConInfo->pdpinfo->secondaryCid = p_response->cid; |
| ConInfo->pdpinfo->primaryCid = PrimaryCid_Get(ConInfo->pdpinfo->connectionNum); |
| } |
| strcpy(ConInfo->pdpinfo->APN, p_response->apn); |
| |
| |
| if (p_response->ipv4info != NULL) { |
| if (ConInfo->ipv4info == NULL) { |
| ConInfo->ipv4info = (Ipv4Info *) malloc(sizeof(Ipv4Info)); |
| if (ConInfo->ipv4info == NULL) { |
| goto Exit; |
| } |
| } |
| memcpy(ConInfo->ipv4info, p_response->ipv4info, sizeof(Ipv4Info)); |
| } |
| |
| if (p_response->ipv6info != NULL) { |
| if (ConInfo->ipv6info == NULL) { |
| ConInfo->ipv6info = (Ipv6Info *) malloc(sizeof(Ipv6Info)); |
| if (ConInfo->ipv6info == NULL) { |
| goto Exit; |
| } |
| } |
| memcpy(ConInfo->ipv6info, p_response->ipv6info, sizeof(Ipv6Info)); |
| } |
| cm_record_nwactivity(ConInfo, true); |
| } else { |
| ConInfo->connectStatus = CM_CONNECT_DISCON; |
| ConInfo->dialFailureCode = p_response->status; |
| ConInfo->retryTime = p_response->suggestedRetryTime; |
| CM_Log(CM_StartDialer6, "CM_StartDialer: FailureCode is %d, retryTime is %d\n", ConInfo->dialFailureCode, |
| ConInfo->retryTime); |
| } |
| |
| Exit: |
| CM_Log(CM_StartDialer406, "CM_StartDialer: done\n"); |
| system("echo cm.lock > /sys/power/wake_unlock"); |
| } |
| |
| void CM_DestroyConnection(DisconnectInfo * p_info) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| CM_Connection_Context *tmp_next; |
| CM_Connection_Context *back_context; |
| |
| int match = 0; |
| tmp_CM_Context = g_CM_Context; |
| |
| if (tmp_CM_Context == NULL) { |
| CM_Log(CM_DestroyConnection1, "CM_DestroyConnection: the link context is null!!!\n"); |
| goto end; |
| } |
| pthread_mutex_lock(&cm_mutex); |
| CM_Log(CM_DestroyConnection11, "CM_DestroyConnection: deleteall %d with cm_mutex locked\n", p_info->deleteall); |
| if (p_info->deleteall) { |
| while (tmp_CM_Context) { |
| tmp_next = tmp_CM_Context->next; |
| CM_disable_pdplist_touci(tmp_CM_Context); |
| |
| //in lte mode, don't destroy default primary pdp |
| if ((NW_status == CM_NW_STATUS_LTE) && (tmp_CM_Context->pdpinfo->connectionNum == 0)) { |
| CM_Log(CM_DestroyConnection3, "CM_DestroyConnection: default primary pdp connect status %d, autoconnect %d", tmp_CM_Context->connectStatus, tmp_CM_Context->pdpinfo->autoconnect); |
| |
| if(tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| StopDialer(tmp_CM_Context->pdpinfo->primaryCid); |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_CM_Context, true); |
| } |
| } else { |
| if (tmp_CM_Context->pdpinfo->PDP_Type == 1) |
| StopDialer(tmp_CM_Context->pdpinfo->primaryCid); |
| else |
| StopDialer(tmp_CM_Context->pdpinfo->secondaryCid); |
| |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| |
| if(tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS) { |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_CM_Context, true); |
| } |
| } |
| CM_Context_free(tmp_CM_Context); |
| tmp_CM_Context = tmp_next; |
| } |
| |
| g_CM_Context = NULL; |
| } else if (p_info->connectionNum & (SECONDARYPDP_CONNECTNUM_RANGE - 1)) { |
| //secondary pdp |
| CM_Log(CM_DestroyConnection4, "CM_DestroyConnection: secondary pdp, connectionNum %d\n", p_info->connectionNum); |
| tmp_next = tmp_CM_Context->next; |
| //for the first link context |
| if (tmp_CM_Context->pdpinfo->connectionNum == p_info->connectionNum) { |
| CM_disable_pdplist_touci(tmp_CM_Context); |
| if (tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL){ |
| StopDialer(tmp_CM_Context->pdpinfo->secondaryCid); |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_CM_Context, true); |
| } |
| CM_Context_free(tmp_CM_Context); |
| g_CM_Context = tmp_next; |
| goto end; |
| } |
| //find the next link contexts whose connect num is dis_coninfo->ConnectNum, then free |
| while (tmp_next) { |
| if (tmp_next->pdpinfo->connectionNum == p_info->connectionNum) { |
| tmp_CM_Context->next = tmp_next->next; |
| |
| CM_disable_pdplist_touci(tmp_next); |
| if (tmp_next->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| StopDialer(tmp_next->pdpinfo->secondaryCid); |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| tmp_next->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_next, true); |
| } |
| |
| CM_Context_free(tmp_next); |
| goto end; |
| } else |
| tmp_CM_Context = tmp_next; |
| |
| tmp_next = tmp_next->next; |
| } |
| } else { |
| //primary pdp |
| CM_Log(CM_DestroyConnection5, "Primary pdp, set connectionNum %d, pdp context connectionNum\n", p_info->connectionNum, tmp_CM_Context->pdpinfo->connectionNum); |
| if ((tmp_CM_Context->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == p_info->connectionNum) { |
| match = 1; |
| tmp_next = tmp_CM_Context->next; |
| CM_disable_pdplist_touci(tmp_CM_Context); |
| if (tmp_CM_Context->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| if (tmp_CM_Context->pdpinfo->PDP_Type == 1) |
| StopDialer(tmp_CM_Context->pdpinfo->primaryCid); |
| else |
| StopDialer(tmp_CM_Context->pdpinfo->secondaryCid); |
| |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_CM_Context, true); |
| } |
| |
| CM_Context_free(tmp_CM_Context); |
| g_CM_Context = tmp_next; |
| tmp_CM_Context = g_CM_Context; |
| } else |
| tmp_next = tmp_CM_Context->next; |
| |
| //find the next link contexts whose primary CID is dis_coninfo->CID, then free |
| while (tmp_next) { |
| if ((tmp_next->pdpinfo->connectionNum & SECONDARYPDP_CONNECTNUM_RANGE) == p_info->connectionNum) { |
| match = 1; |
| CM_disable_pdplist_touci(tmp_next); |
| //tmp_CM_Context is not the first link context |
| if (tmp_CM_Context != tmp_next) |
| tmp_CM_Context->next = tmp_next->next; |
| |
| if (tmp_next->connectStatus == CM_CONNECT_CONSUCCESS || tmp_CM_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| if (tmp_CM_Context->pdpinfo->PDP_Type == 1) |
| StopDialer(tmp_CM_Context->pdpinfo->primaryCid); |
| else |
| StopDialer(tmp_CM_Context->pdpinfo->secondaryCid); |
| |
| if (!CM_CheckContextValid(tmp_CM_Context)) |
| goto end; |
| |
| tmp_CM_Context->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(tmp_CM_Context, true); |
| } |
| back_context = tmp_next; |
| //modify by qgwang, 20140304, memory leak checked by klocwork |
| //the current link is the firtst link, and delete the first link |
| if (tmp_CM_Context == tmp_next) { |
| tmp_CM_Context = tmp_next->next; |
| } |
| tmp_next = tmp_next->next; |
| CM_Context_free(back_context); |
| } else { |
| tmp_CM_Context = tmp_next; |
| tmp_next = tmp_next->next; |
| } |
| } |
| } |
| end: |
| pthread_mutex_unlock(&cm_mutex); |
| CM_Log(CM_DestroyConnection6, "CM_DestroyConnection: cm_mutex unlocked, %s\n", match ? "find match ctx to destroy done" : "done with out ctx match"); |
| } |
| |
| Link_Context *CM_GetLinkContext(void) |
| { |
| CM_Connection_Context *tmp_CM_Context; |
| //the head of link context |
| Link_Context *h_linkcontext; |
| Link_Context *p_linkcontext; |
| |
| tmp_CM_Context = g_CM_Context; |
| |
| //try to find the match connection_num |
| if (tmp_CM_Context == NULL) |
| { |
| return NULL; |
| } |
| |
| p_linkcontext = (Link_Context *) malloc(sizeof(Link_Context)); |
| if (!p_linkcontext) { |
| return NULL; |
| } |
| memset(p_linkcontext, 0, sizeof(Link_Context)); |
| h_linkcontext = p_linkcontext; |
| |
| p_linkcontext->connectionNum = tmp_CM_Context->pdpinfo->connectionNum; |
| |
| if (tmp_CM_Context->connectStatus == 3) |
| p_linkcontext->connectStatus = 2; |
| else |
| p_linkcontext->connectStatus = tmp_CM_Context->connectStatus; |
| |
| p_linkcontext->create_by = tmp_CM_Context->create_by; |
| CM_Log(CM_GetLinkContext1, "CM_GetLinkContext, connect status:%d, pdp type:%d, create_by %d(1: CM 0: WebUI)\n", tmp_CM_Context->connectStatus, |
| tmp_CM_Context->pdpinfo->PDP_Type, tmp_CM_Context->create_by); |
| |
| memcpy(&(p_linkcontext->pdpinfo), tmp_CM_Context->pdpinfo, sizeof(p_linkcontext->pdpinfo)); |
| |
| if (p_linkcontext->connectStatus == 1) { |
| if (tmp_CM_Context->ipv4info != NULL) |
| memcpy(&(p_linkcontext->ipv4info), tmp_CM_Context->ipv4info, sizeof(p_linkcontext->ipv4info)); |
| |
| if (tmp_CM_Context->ipv6info != NULL) |
| memcpy(&(p_linkcontext->ipv6info), tmp_CM_Context->ipv6info, sizeof(p_linkcontext->ipv6info)); |
| } |
| |
| tmp_CM_Context = tmp_CM_Context->next; |
| while (tmp_CM_Context) { |
| p_linkcontext->next = malloc(sizeof(Link_Context)); |
| if (!p_linkcontext->next) { |
| return h_linkcontext; |
| } |
| |
| p_linkcontext = p_linkcontext->next; |
| |
| memset(p_linkcontext, 0, sizeof(Link_Context)); |
| |
| p_linkcontext->connectionNum = tmp_CM_Context->pdpinfo->connectionNum; |
| if (tmp_CM_Context->connectStatus == 3) |
| p_linkcontext->connectStatus = 2; |
| else |
| p_linkcontext->connectStatus = tmp_CM_Context->connectStatus; |
| |
| memcpy(&(p_linkcontext->pdpinfo), tmp_CM_Context->pdpinfo, sizeof(p_linkcontext->pdpinfo)); |
| |
| if (p_linkcontext->connectStatus == 1) { |
| if (tmp_CM_Context->ipv4info != NULL) |
| memcpy(&(p_linkcontext->ipv4info), tmp_CM_Context->ipv4info, |
| sizeof(p_linkcontext->ipv4info)); |
| |
| if (tmp_CM_Context->ipv6info != NULL) |
| memcpy(&(p_linkcontext->ipv6info), tmp_CM_Context->ipv6info, |
| sizeof(p_linkcontext->ipv6info)); |
| } |
| |
| tmp_CM_Context = tmp_CM_Context->next; |
| } |
| |
| return h_linkcontext; |
| } |
| |
| Apn_Info *get_inital_attach_apn(Mnc_Apn * apn_list, char *cur_apn) |
| { |
| if (apn_list == NULL) |
| return NULL; |
| |
| Apn_Info *apninfo; |
| int index; |
| |
| if (cur_apn == NULL) { |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| if (strlen(apninfo->type) == 0) |
| continue; |
| if (apninfo->Extra_params.lte_default == 1) |
| return apninfo; |
| } |
| } else { |
| |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| |
| if (strlen(apninfo->type) == 0) |
| continue; |
| |
| if(strlen(apninfo->apn) == 0 && strlen(apninfo->lte_apn) == 0) |
| continue; |
| |
| if(strlen(apninfo->lte_apn) == 0) |
| strcpy(apninfo->lte_apn, apninfo->apn); |
| |
| if (apninfo->Extra_params.lte_default == 1 && strcmp(apninfo->lte_apn, cur_apn) != 0) |
| return apninfo; |
| } |
| |
| if (index == MAX_APN_NUM || strlen(apninfo->type) == 0) { |
| apn_list->all_try_fail = 1; |
| |
| CM_Log(get_inital_attach_apn, "leave get_inital_attach_apn, all try failed\n"); |
| return NULL; |
| } |
| } |
| return NULL; |
| } |
| |
| Apn_Info *get_default_apninfo(Mnc_Apn * apn_list, char *cur_apn) |
| { |
| if (apn_list == NULL) |
| return NULL; |
| |
| Apn_Info *apninfo; |
| int index; |
| |
| if (cur_apn == NULL) { |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| if (strlen(apninfo->type) == 0) |
| continue; |
| //match the "default" type |
| if (strcmp(apninfo->type, "default") == 0) |
| return apninfo; |
| } |
| } else { |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| |
| if (strlen(apninfo->type) == 0) |
| continue; |
| //match the "default" type |
| |
| if(strlen(apninfo->apn) == 0) |
| continue; |
| |
| if (strcmp(apninfo->type, "default") == 0 && strcmp(apninfo->apn, cur_apn) != 0) |
| return apninfo; |
| } |
| |
| if (index == MAX_APN_NUM || strlen(apninfo->type) == 0) { |
| apn_list->all_try_fail = 1; |
| CM_Log(get_default_apninfo, "leave get_default_apninfo, all try failed \n"); |
| return NULL; |
| } |
| } |
| return NULL; |
| } |
| |
| Apn_Info *get_apninfo_from_LteAPN(Mnc_Apn * apn_list, char *LteAPN) |
| { |
| if (apn_list == NULL || LteAPN == NULL) |
| return NULL; |
| |
| Apn_Info *apninfo; |
| int index; |
| |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| if (strlen(apninfo->type) == 0) |
| continue; |
| //match the "default" type |
| if (strcmp(apninfo->type, "default") == 0 && strcmp(apninfo->apn, LteAPN) == 0) |
| { |
| CM_Log(get_apninfo_from_LteAPN, " get_apninfo_from_LteAPN: apnInfp %p for lteApn [%s]\n", apninfo, strlen(LteAPN) ? LteAPN : "NULL"); |
| return apninfo; |
| } |
| } |
| |
| return NULL; |
| } |
| |
| Apn_Info *get_fota_apninfo(Mnc_Apn * apn_list) |
| { |
| if (apn_list == NULL) |
| return NULL; |
| |
| Apn_Info *apninfo; |
| int index; |
| |
| for (index = 0; index < MAX_APN_NUM; index++) { |
| apninfo = &(apn_list->apn_info_list[index]); |
| /*check enable option first*/ |
| if (apninfo->enable == 0) |
| continue; |
| if (strlen(apninfo->type) == 0) |
| continue; |
| //match the "default" type |
| if (strcmp(apninfo->type, "fota") == 0) |
| return apninfo; |
| } |
| return NULL; |
| } |
| |
| CM_Connection_Context *get_match_pdp(Apn_Info * apninfo) |
| { |
| if (apninfo == NULL) |
| return NULL; |
| |
| CM_Connection_Context *tmp_Context; |
| if (g_CM_Context == NULL) |
| return NULL; |
| |
| tmp_Context = g_CM_Context; |
| |
| while (tmp_Context) { |
| if(tmp_Context->pdpinfo->connectionNum == apninfo->connection_num) |
| return tmp_Context; |
| |
| tmp_Context = tmp_Context->next; |
| } |
| |
| return NULL; |
| } |
| |
| CM_Connection_Context *create_new_pdp_ctx(Apn_Info * apnInfo) |
| { |
| CM_Connection_Context *tmp_Context; |
| Apn_Info *default_apn = NULL; |
| Apn_Info *apninfo = apnInfo; |
| |
| //the first pdp context |
| if (g_CM_Context == NULL) { |
| CM_Log(create_new_pdp_ctx, "create_new_pdp_ctx: create the first pdp context\n"); |
| tmp_Context = (CM_Connection_Context *) malloc(sizeof(CM_Connection_Context)); |
| if (!tmp_Context) { |
| return NULL; |
| } |
| memset(tmp_Context, 0, sizeof(CM_Connection_Context)); |
| g_CM_Context = tmp_Context; |
| } |
| else { |
| tmp_Context = g_CM_Context; |
| while (tmp_Context->next) { |
| tmp_Context = tmp_Context->next; |
| } |
| CM_Log(create_new_pdp_ctx4, "create_new_pdp_ctx: create a new pdp context\n"); |
| |
| tmp_Context->next = (CM_Connection_Context *) malloc(sizeof(CM_Connection_Context)); |
| if (!tmp_Context->next) { |
| CM_Log_E(create_new_pdp_ctx5, "create_new_pdp_ctx: malloc size %d failed\n", sizeof(CM_Connection_Context)); |
| return NULL; |
| } |
| |
| tmp_Context = tmp_Context->next; |
| memset(tmp_Context, 0, sizeof(CM_Connection_Context)); |
| } |
| |
| tmp_Context->connectStatus = CM_CONNECT_DISCON; |
| tmp_Context->first_dial = 1; |
| tmp_Context->retryTime = -1; |
| |
| tmp_Context->pdpinfo = (PdpInfo *) malloc(sizeof(PdpInfo)); |
| if (!tmp_Context->pdpinfo) { |
| return NULL; |
| } |
| memset(tmp_Context->pdpinfo, 0, sizeof(PdpInfo)); |
| |
| tmp_Context->pdpinfo->connectionNum = apninfo->connection_num; |
| tmp_Context->pdpinfo->primaryCid = apninfo->cid; |
| tmp_Context->pdpinfo->PDP_Type = 1; |
| |
| if (apninfo->cid == CM_DEFAULT_ATTACH_CID && apninfo->auto_apn) |
| { |
| default_apn = get_default_apninfo(g_work_apn, NULL); |
| if (default_apn && default_apn->auto_apn) |
| { |
| apninfo = default_apn; |
| CM_Log(create_new_pdp_ctx827, "%s: get default apn for default attach cid with auto apn ", __func__); |
| } |
| } |
| |
| if (strlen(apninfo->apn) != 0) |
| strcpy(tmp_Context->pdpinfo->APN, apninfo->apn); |
| else if (strlen(apninfo->lte_apn) != 0) |
| strcpy(tmp_Context->pdpinfo->APN, apninfo->lte_apn); |
| |
| if (strlen(apninfo->lte_apn) != 0) |
| strcpy(tmp_Context->pdpinfo->LteAPN, apninfo->lte_apn); |
| else if (strlen(apninfo->apn) != 0) |
| strcpy(tmp_Context->pdpinfo->LteAPN, apninfo->apn); |
| |
| tmp_Context->pdpinfo->IP_Type = apninfo->iptype; |
| tmp_Context->pdpinfo->IP_Type_back = apninfo->iptype; |
| tmp_Context->pdpinfo->autoapn = apninfo->auto_apn; |
| tmp_Context->pdpinfo->autoconnect = apninfo->Extra_params.autoconnect; |
| tmp_Context->pdpinfo->data_on_roaming = apninfo->Extra_params.data_on_roaming; |
| tmp_Context->pdpinfo->is_default = apninfo->Extra_params.lte_default; |
| tmp_Context->pdpinfo->mtu = apninfo->mtu; |
| tmp_Context->pdpinfo->data_block = apninfo->data_block; |
| strncpy(tmp_Context->pdpinfo->PDP_name, apninfo->pdp_name, sizeof(tmp_Context->pdpinfo->PDP_name) - 1); |
| |
| CM_Log(create_new_pdp_ctx3, "create_new_pdp_ctx: ctx [0x%x], auto_apn %d, autoconnect %d, data_on_roaming %d, mtu %d, cid %d, is_default %d, data_block %d, ip_type %d \n", tmp_Context, apninfo->auto_apn, |
| apninfo->Extra_params.autoconnect, apninfo->Extra_params.data_on_roaming, apninfo->mtu, apninfo->cid, apninfo->Extra_params.lte_default, apninfo->data_block, apninfo->iptype); |
| |
| if (strlen(apninfo->authtype) != 0) |
| strcpy(tmp_Context->pdpinfo->Authtype2G3G, apninfo->authtype); |
| else |
| strcpy(tmp_Context->pdpinfo->Authtype2G3G, "NONE"); |
| |
| if (strlen(apninfo->usrname) != 0) |
| strcpy(tmp_Context->pdpinfo->Usr2G3G, apninfo->usrname); |
| else |
| strcpy(tmp_Context->pdpinfo->Usr2G3G, "any"); |
| |
| if (strlen(apninfo->paswd) != 0) |
| strcpy(tmp_Context->pdpinfo->PASWD2G3G, apninfo->paswd); |
| else |
| strcpy(tmp_Context->pdpinfo->PASWD2G3G, "any"); |
| |
| if (strlen(apninfo->lte_authtype) != 0) |
| strcpy(tmp_Context->pdpinfo->Authtype4G, apninfo->lte_authtype); |
| else |
| strcpy(tmp_Context->pdpinfo->Authtype4G, "NONE"); |
| |
| if (strlen(apninfo->lte_usrname) != 0) |
| strcpy(tmp_Context->pdpinfo->Usr4G, apninfo->lte_usrname); |
| else |
| strcpy(tmp_Context->pdpinfo->Usr4G, "any"); |
| |
| if (strlen(apninfo->lte_paswd) != 0) |
| strcpy(tmp_Context->pdpinfo->PASWD4G, apninfo->lte_paswd); |
| else |
| strcpy(tmp_Context->pdpinfo->PASWD4G, "any"); |
| |
| if(strlen(apninfo->mmsc) != 0) |
| strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsc); |
| |
| if(strlen(apninfo->mmsproxy) != 0) |
| strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsproxy); |
| |
| if(strlen(apninfo->mmsport) != 0) |
| strcpy(tmp_Context->pdpinfo->mmsc, apninfo->mmsport); |
| |
| if (apninfo->netif[0] != '\0') |
| strcpy(tmp_Context->pdpinfo->netif, apninfo->netif); |
| |
| #ifdef CONFIG_CM_URSP |
| tmp_Context->pdpinfo->rsd_index = -1; |
| memcpy(&(tmp_Context->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(tmp_Context->pdpinfo->config_rsd)); |
| #endif |
| |
| return tmp_Context; |
| } |
| |
| void ClearETIFlag_data_cb(struct ubus_request *req, int type, struct blob_attr *msg) |
| { |
| UNUSED(req); |
| UNUSED(type); |
| UNUSED(msg); |
| |
| CM_Log(ClearETIFlag_data_cb, "enter ClearETIFlag_data_cb"); |
| } |
| |
| static void complete_clear_eitf_async_cb(struct ubus_request *req, int ret) |
| { |
| UNUSED(ret); |
| if (req) { |
| free(req); |
| } |
| CM_Log(complete_clear_eitf_async_cb, "complete_clear_eitf_async_cb(%d)\n", ret); |
| } |
| |
| int CM_Clear_ETIFlag(int sync) |
| { |
| struct ubus_request *req = NULL; |
| int ret_val; |
| |
| CM_Log(CM_Clear_ETIFlag, "CM_Clear_ETIFlag sync mode %d", sync); |
| |
| blob_buf_init(&cm_b, 0); |
| rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_CLEAR_ETIFLAG, NULL, 0); |
| |
| if (sync) { |
| if ((ret_val = |
| ubus_invoke(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, ClearETIFlag_data_cb, 0, |
| 0)) != UBUS_STATUS_OK) { |
| goto end; |
| } |
| } else { |
| req = malloc(sizeof(struct ubus_request)); |
| if (!req) { |
| ret_val = UBUS_STATUS_INVALID_ARGUMENT; |
| goto end; |
| } |
| |
| if ((ret_val = ubus_invoke_async(cm_ctx, cm_ubus_id.ril_id, "ril_request", cm_b.head, req)) != UBUS_STATUS_OK) { |
| free(req); |
| goto end; |
| } else { |
| req->complete_cb = complete_clear_eitf_async_cb; |
| ubus_complete_request_async(cm_ctx, req); |
| } |
| } |
| |
| end: |
| CM_Log(CM_Clear_ETIFlag2, "CM_Clear_ETIFlag done with ret %d", ret_val); |
| return ret_val; |
| } |
| |
| // Workaround: Some NW returns .mcc<MCC>.mnc<MNC> |
| static int isValidOI(const char *oi) |
| { |
| int ret = 0; |
| if (oi != NULL) { |
| int i; |
| int len = strlen(oi); |
| |
| char * new_oi = (char *)malloc(len + 1); |
| if (new_oi != NULL) { |
| for (i = 0; i < len; i++) |
| new_oi[i] = tolower(oi[i]); |
| new_oi[len] = 0; |
| regex_t re; |
| int regerr = regcomp(&re, ".(mnc[0-9]+.mcc[0-9]+|mcc[0-9]+.mnc[0-9]+).(gprs|(pub.|ipxuni.)?3gppnetwork.org)", REG_EXTENDED); |
| if (regerr == 0) { |
| ret = 0 == regexec(&re, new_oi, 0, NULL, 0); |
| } |
| regfree(&re); |
| free(new_oi); |
| } |
| } |
| if (!ret) |
| { |
| CM_Log(isValidOI, "'%s' is not a valid Operator Identifier", oi); |
| } |
| return ret; |
| } |
| |
| /** |
| * TS 23.003 section 9 definition of Access Point Name |
| * The APN is composed of two parts Network Identifier + Operator Identifier |
| * The APN Operator Identifier is composed of three labels. the last labet shall be "gprs". |
| */ |
| int matchApnNetworkIdentifier(const char *eps_apn, const char *apn) |
| { |
| bool eps_apn_null = false, apn_null= false; |
| |
| if ((eps_apn && strlen(eps_apn) == 0) || eps_apn == NULL) |
| eps_apn_null = true; |
| |
| if ((apn && strlen(apn) == 0) || apn == NULL) |
| apn_null = true; |
| |
| if (eps_apn_null && apn_null) |
| return 1; |
| else if (eps_apn_null) |
| return 0; |
| else if (apn_null) |
| return 0; |
| |
| if (eps_apn == NULL ||apn == NULL) |
| return 0; |
| |
| size_t len = (strlen(apn) > strlen(eps_apn)) ? strlen(eps_apn) : strlen(apn); |
| |
| CM_Log(matchApnNetworkIdentifier, "enter matchApnNetworkIdentifier, eps_apn %s: current apn:%s, len %d", eps_apn, apn, len); |
| |
| if (len > 0) |
| { |
| if (strncasecmp(eps_apn, apn, len) == 0) { |
| const char *oi = eps_apn + len; |
| return *oi == '\0' || isValidOI(oi); |
| } |
| else if (strncasecmp(eps_apn, "3gnet", len) == 0) { |
| if (strncasecmp(apn, "wonet", len) == 0) |
| return 1; |
| } |
| else if (strncasecmp(eps_apn, "wonet", len) == 0) { |
| if (strncasecmp(apn, "3gnet", len) == 0) |
| return 1; |
| } |
| } |
| return 0; |
| } |
| |
| CM_Connection_Context *cm_get_partner_ctx(int cid) |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| if (cid <= 0) |
| return NULL; |
| |
| while (ctx) |
| { |
| if (ctx->pdpinfo && ctx->pdpinfo->parent_cid == cid) |
| { |
| if (ctx->pdpinfo->primaryCid != cid) |
| { |
| CM_Log(cm_get_partner_ctx, "cm_get_partner_ctx: cid %d, parent cid %d\n", ctx->pdpinfo->primaryCid, ctx->pdpinfo->parent_cid); |
| break; |
| } |
| } |
| |
| ctx = ctx->next; |
| } |
| |
| return ctx; |
| } |
| |
| extern unsigned char UnknownPdpCause; |
| //if need to redial, return TRUE; otherwise, return FALSE |
| bool check_merger_pdpcontext(Apn_Info * apninfo, CM_Connection_Context * coninfo, int apn_info_flag) |
| { |
| bool ret; |
| ret = FALSE; |
| int roam_iptype = 0; |
| bool skip_merge = false; |
| |
| if (apninfo->cid == CM_DEFAULT_ATTACH_CID && apn_info_flag == PDP_CONFIG_ZGDCONT) |
| { |
| #ifdef CONFIG_ZGDCONT_MULTI_PDP |
| if (is_pdp_auto_apn(g_work_apn, apninfo->type)) |
| skip_merge = true; |
| #endif |
| } |
| |
| if (skip_merge) { |
| CM_Log(check_merger_pdpcontext1080, "check_merger_pdpcontext, skip merge for cid [%d] in auto apn mode", apninfo->cid); |
| return ret; |
| } |
| |
| if (coninfo->create_by == 1) { |
| CM_Log(check_merger_pdpcontext, "check_merger_pdpcontext, the context created by CM self"); |
| } |
| |
| roam_iptype = cm_get_zroam_iptype(); |
| if (roam_iptype > 0) |
| { |
| if (roam_iptype == 3) |
| roam_iptype = 0; |
| |
| if (roam_iptype != coninfo->pdpinfo->IP_Type) { |
| if (get_ipv4_only_allowed() && coninfo->pdpinfo->IP_Type == IPV4 |
| && (roam_iptype == IPV4 || roam_iptype == IPV4V6)) |
| { |
| CM_Log(check_merger_pdpcontext1050, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv4_only_allowed, consider same", coninfo->pdpinfo->IP_Type, roam_iptype); |
| } |
| else if (get_ipv6_only_allowed() && coninfo->pdpinfo->IP_Type == IPV6 |
| && (roam_iptype == IPV6 || roam_iptype == IPV4V6)) |
| { |
| CM_Log(check_merger_pdpcontext1064, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv6_only_allowed, consider same", coninfo->pdpinfo->IP_Type, roam_iptype); |
| } |
| else |
| { |
| CM_Log(check_merger_pdpcontext999, "check_merger_pdpcontext, IP type changed, %d->%d", coninfo->pdpinfo->IP_Type, roam_iptype); |
| coninfo->pdpinfo->IP_Type = roam_iptype; |
| ret = TRUE; |
| } |
| } |
| } |
| else |
| { |
| if (apninfo->iptype != coninfo->pdpinfo->IP_Type) { |
| if (get_ipv4_only_allowed() && coninfo->pdpinfo->IP_Type == IPV4 |
| && (apninfo->iptype == IPV4 || apninfo->iptype == IPV4V6)) |
| { |
| CM_Log(check_merger_pdpcontext1060, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv4_only_allowed, consider same", coninfo->pdpinfo->IP_Type, apninfo->iptype); |
| } |
| else if (get_ipv6_only_allowed() && coninfo->pdpinfo->IP_Type == IPV6 |
| && (apninfo->iptype == IPV6 || apninfo->iptype == IPV4V6)) |
| { |
| CM_Log(check_merger_pdpcontext1064, "check_merger_pdpcontext, IP type %d->%d, but attach_ipv6_only_allowed, consider same", coninfo->pdpinfo->IP_Type, apninfo->iptype); |
| } |
| else |
| { |
| if (UnknownPdpCause == 52) |
| { |
| if (apninfo->iptype == IPV4V6) |
| { |
| if (coninfo->pdpinfo->IP_Type != IPV4V6) |
| { |
| CM_Connection_Context *parnter_ctx = NULL; |
| parnter_ctx = cm_get_partner_ctx(coninfo->pdpinfo->primaryCid); |
| if (parnter_ctx && parnter_ctx->pdpinfo && parnter_ctx->pdpinfo->IP_Type != coninfo->pdpinfo->IP_Type) |
| { |
| CM_Log(check_merger_pdpcontext1202, "check_merger_pdpcontext, UnknownPdpCause 52, iptype exist %d, %d -> %d", |
| coninfo->pdpinfo->IP_Type, parnter_ctx->pdpinfo->IP_Type, apninfo->iptype); |
| } |
| else |
| { |
| CM_Log(check_merger_pdpcontext1207, "check_merger_pdpcontext, UnknownPdpCause 52, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype); |
| coninfo->pdpinfo->IP_Type = apninfo->iptype; |
| ret = TRUE; |
| } |
| } |
| } |
| |
| if (apninfo->iptype != IPV4V6 && coninfo->pdpinfo->IP_Type != IPV4V6) |
| { |
| CM_Log(check_merger_pdpcontext1216, "check_merger_pdpcontext, UnknownPdpCause 52, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype); |
| coninfo->pdpinfo->IP_Type = apninfo->iptype; |
| ret = TRUE; |
| } |
| } |
| else |
| { |
| CM_Log(check_merger_pdpcontext1, "check_merger_pdpcontext, IP type changed, %d->%d", coninfo->pdpinfo->IP_Type, apninfo->iptype); |
| coninfo->pdpinfo->IP_Type = apninfo->iptype; |
| ret = TRUE; |
| } |
| } |
| } |
| } |
| coninfo->pdpinfo->IP_Type_back = apninfo->iptype; |
| |
| if(matchApnNetworkIdentifier( coninfo->pdpinfo->APN, apninfo->apn) == 0) { |
| CM_Log(check_merger_pdpcontext2, "check_merger_pdpcontext, APN changed, %s->%s",coninfo->pdpinfo->APN, apninfo->apn); |
| strcpy(coninfo->pdpinfo->APN, apninfo->apn); |
| ret = TRUE; |
| } |
| |
| if((strlen(apninfo->lte_apn) != 0) ||(strlen(coninfo->pdpinfo->LteAPN) != 0)) { |
| if(matchApnNetworkIdentifier(coninfo->pdpinfo->LteAPN, apninfo->lte_apn) == 0) { |
| CM_Log(check_merger_pdpcontext3, "check_merger_pdpcontext, LTE APN changed, %s->%s",coninfo->pdpinfo->LteAPN, apninfo->lte_apn); |
| strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn); |
| ret = TRUE; |
| } |
| strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn); |
| } |
| |
| if (coninfo->pdpinfo->autoconnect == CM_CONTYPE_MANUAL && apninfo->Extra_params.autoconnect == CM_CONTYPE_AUTO) { |
| CM_Log(check_merger_pdpcontext4, "check_merger_pdpcontext, autoconnect changed, manual->auto"); |
| coninfo->pdpinfo->autoconnect = CM_CONTYPE_AUTO; |
| //ret = TRUE; |
| } else if (coninfo->pdpinfo->autoconnect == CM_CONTYPE_AUTO && apninfo->Extra_params.autoconnect == CM_CONTYPE_MANUAL) { |
| CM_Log(check_merger_pdpcontext5, "check_merger_pdpcontext, autoconnect changed, auto->manual"); |
| coninfo->pdpinfo->autoconnect = CM_CONTYPE_MANUAL; |
| //ret = TRUE; |
| } |
| |
| if (coninfo->pdpinfo->data_on_roaming == 0 && apninfo->Extra_params.data_on_roaming == 1) { |
| CM_Log(check_merger_pdpcontext6, "check_merger_pdpcontext, data_on_roaming changed, 0->1"); |
| coninfo->pdpinfo->data_on_roaming = 1; |
| //ret = TRUE; |
| } else if (coninfo->pdpinfo->data_on_roaming == 1 && apninfo->Extra_params.data_on_roaming == 0) { |
| CM_Log(check_merger_pdpcontext7, "check_merger_pdpcontext, data_on_roaming changed, 1->0"); |
| coninfo->pdpinfo->data_on_roaming = 0; |
| //ret = TRUE; |
| } |
| |
| if (coninfo->pdpinfo->always_on == 0 && apninfo->Extra_params.always_on == 1) { |
| CM_Log(check_merger_pdpcontext1145, "check_merger_pdpcontext, always_on(data_on_boot) changed, 0->1"); |
| coninfo->pdpinfo->always_on = 1; |
| //ret = TRUE; |
| } else if (coninfo->pdpinfo->always_on == 1 && apninfo->Extra_params.always_on == 0) { |
| CM_Log(check_merger_pdpcontext1149, "check_merger_pdpcontext, always_on(data_on_boot) changed, 1->0"); |
| coninfo->pdpinfo->always_on = 0; |
| //ret = TRUE; |
| } |
| |
| #ifndef CONFIG_ZGDCONT_MULTI_PDP |
| if (apninfo->cid && coninfo->pdpinfo->primaryCid != apninfo->cid) { |
| CM_Log(check_merger_pdpcontext8, "check_merger_pdpcontext, cid changed, %d->%d", coninfo->pdpinfo->primaryCid, apninfo->cid); |
| ret = TRUE; |
| } |
| #endif |
| if ((strlen(apninfo->authtype) && strlen(coninfo->pdpinfo->Authtype2G3G) && strcasecmp (apninfo->authtype, coninfo->pdpinfo->Authtype2G3G)) || |
| (strlen(apninfo->usrname) && strlen(coninfo->pdpinfo->Usr2G3G) && strcasecmp (apninfo->usrname, coninfo->pdpinfo->Usr2G3G)) || |
| (strlen(apninfo->paswd) && strlen(coninfo->pdpinfo->PASWD2G3G) && strcasecmp (apninfo->paswd, coninfo->pdpinfo->PASWD2G3G))) |
| { |
| CM_Log(check_merger_pdpcontext9, "check_merger_pdpcontext, 23G auth changed, type %s->%s, user %s->%s, password %s->%s", |
| strlen(coninfo->pdpinfo->Authtype2G3G)? coninfo->pdpinfo->Authtype2G3G: "NULL", strlen(apninfo->authtype)?apninfo->authtype:"NULL", |
| strlen(coninfo->pdpinfo->Usr2G3G)? coninfo->pdpinfo->Usr2G3G: "NULL", strlen(apninfo->usrname)?apninfo->usrname:"NULL", |
| strlen(coninfo->pdpinfo->PASWD2G3G)? coninfo->pdpinfo->PASWD2G3G: "NULL", strlen(apninfo->paswd)?apninfo->paswd:"NULL" ); |
| |
| strncpy(coninfo->pdpinfo->Authtype2G3G, apninfo->authtype, sizeof(coninfo->pdpinfo->Authtype2G3G) - 1); |
| strncpy(coninfo->pdpinfo->Usr2G3G, apninfo->usrname, sizeof(coninfo->pdpinfo->Usr2G3G) - 1); |
| strncpy(coninfo->pdpinfo->PASWD2G3G, apninfo->paswd, sizeof(coninfo->pdpinfo->PASWD2G3G) - 1); |
| // ret = TRUE; |
| } |
| else if ((strlen(apninfo->authtype) == 0 ||strcasecmp (apninfo->authtype, "NONE")) && |
| strlen(coninfo->pdpinfo->Authtype2G3G) && strcasecmp (coninfo->pdpinfo->Authtype2G3G, "NONE")) |
| { |
| CM_Log(check_merger_pdpcontext1200, "check_merger_pdpcontext, Authtype2G3G changed, %s->NONE", coninfo->pdpinfo->Authtype2G3G); |
| strcpy(coninfo->pdpinfo->Authtype2G3G, "NONE"); |
| //ret = TRUE; |
| } |
| else if ((strlen(apninfo->usrname) == 0 ||strcasecmp (apninfo->usrname, "any")) && |
| strlen(coninfo->pdpinfo->Usr2G3G) && strcasecmp (coninfo->pdpinfo->Usr2G3G, "any")) |
| { |
| strcpy(coninfo->pdpinfo->Authtype2G3G, "any"); |
| // ret = TRUE; |
| } |
| else if ((strlen(apninfo->paswd) == 0 || strcasecmp (apninfo->paswd, "any")) && |
| strlen(coninfo->pdpinfo->PASWD2G3G) && strcasecmp (coninfo->pdpinfo->PASWD2G3G, "any")) |
| { |
| strcpy(coninfo->pdpinfo->PASWD2G3G, "any"); |
| // ret = TRUE; |
| } |
| |
| if ((strlen(apninfo->lte_authtype) && strcasecmp (apninfo->lte_authtype, coninfo->pdpinfo->Authtype4G) ) || |
| (strlen(apninfo->lte_usrname) && strcasecmp (apninfo->lte_usrname, coninfo->pdpinfo->Usr4G)) || |
| (strlen(apninfo->lte_paswd) && strcasecmp (apninfo->lte_paswd, coninfo->pdpinfo->PASWD4G))) |
| { |
| CM_Log(check_merger_pdpcontext9, "check_merger_pdpcontext, 4G auth changed, type %s->%s, user %s->%s, password %s->%s", |
| strlen(coninfo->pdpinfo->Authtype4G)? coninfo->pdpinfo->Authtype4G: "NULL", strlen(apninfo->lte_authtype)?apninfo->lte_authtype:"NULL", |
| strlen(coninfo->pdpinfo->Usr4G)? coninfo->pdpinfo->Usr4G: "NULL", strlen(apninfo->lte_usrname)?apninfo->lte_usrname:"NULL", |
| strlen(coninfo->pdpinfo->PASWD4G)? coninfo->pdpinfo->PASWD4G: "NULL", strlen(apninfo->lte_paswd)?apninfo->lte_paswd:"NULL" ); |
| |
| strncpy(coninfo->pdpinfo->Authtype4G, apninfo->lte_authtype, sizeof(coninfo->pdpinfo->Authtype4G) - 1); |
| strncpy(coninfo->pdpinfo->Usr4G, apninfo->lte_usrname, sizeof(coninfo->pdpinfo->Usr4G) - 1); |
| strncpy(coninfo->pdpinfo->PASWD4G, apninfo->lte_paswd, sizeof(coninfo->pdpinfo->PASWD4G) - 1); |
| // ret = TRUE; |
| } |
| else if ((strlen(apninfo->lte_authtype) == 0 ||strcasecmp (apninfo->lte_authtype, "NONE")) && |
| strlen(coninfo->pdpinfo->Authtype4G) && strcasecmp (coninfo->pdpinfo->Authtype4G, "NONE")) |
| { |
| CM_Log(check_merger_pdpcontext1235, "check_merger_pdpcontext, Authtype4G changed, %s->NONE", coninfo->pdpinfo->Authtype2G3G); |
| strcpy(coninfo->pdpinfo->Authtype4G, "NONE"); |
| // ret = TRUE; |
| } |
| else if ((strlen(apninfo->lte_usrname) == 0 ||strcasecmp (apninfo->lte_usrname, "any")) && |
| strlen(coninfo->pdpinfo->Usr4G) && strcasecmp (coninfo->pdpinfo->Usr4G, "any")) |
| { |
| strcpy(coninfo->pdpinfo->Usr4G, "any"); |
| //ret = TRUE; |
| } |
| else if ((strlen(apninfo->lte_paswd) == 0 ||strcasecmp (apninfo->lte_paswd, "any")) && |
| strlen(coninfo->pdpinfo->PASWD4G) && strcasecmp (coninfo->pdpinfo->PASWD4G, "any")) |
| { |
| strcpy(coninfo->pdpinfo->PASWD4G, "any"); |
| // ret = TRUE; |
| } |
| |
| memcpy(coninfo->pdpinfo->netif, apninfo->netif, MAX_STR_LEN); |
| |
| #ifdef CONFIG_CM_URSP |
| if (memcmp(&(coninfo->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(coninfo->pdpinfo->config_rsd)) ) |
| { |
| memcpy(&(coninfo->pdpinfo->config_rsd), &(apninfo->config_rsd), sizeof(coninfo->pdpinfo->config_rsd)); |
| ret = TRUE; |
| } |
| #endif |
| CM_Log(check_merger_pdpcontext1282, "check_merger_pdpcontext, ret %d", ret); |
| return ret; |
| } |
| |
| //return TRUE, need to sleep and redial |
| //return FALSE, don't need to sleep and redial |
| bool redial_sleep(int count) |
| { |
| int sleep_interval = 0; |
| |
| if (!g_redial_interval) |
| return FALSE; |
| |
| if (count >= g_redial_interval->total_retry_times) |
| { |
| CM_Log(redial_sleep1, "redial_sleep: redial count %d reach max %d", count, g_redial_interval->total_retry_times); |
| return FALSE; |
| } |
| |
| if (count < g_redial_interval->repeat0_times) |
| sleep_interval = g_redial_interval->interval0; |
| else if (count < (g_redial_interval->repeat1_times + g_redial_interval->repeat0_times)) |
| sleep_interval = g_redial_interval->interval1; |
| else if (count < |
| (g_redial_interval->repeat2_times + g_redial_interval->repeat1_times + |
| g_redial_interval->repeat0_times)) |
| sleep_interval = g_redial_interval->interval2; |
| else |
| sleep_interval = g_redial_interval->interval3; |
| |
| if (sleep_interval > 0) |
| { |
| CM_Log(redial_sleep2, "redial_sleep: will sleep %d seconds", sleep_interval); |
| sleep(sleep_interval); |
| } |
| |
| return TRUE; |
| } |
| |
| /*********************************************************************** |
| package name redial_interval |
| |
| config operation_type CMCC |
| option connection_num 0 |
| option mcc |
| option mnc |
| option interval0 5 |
| option repeat0_times 20 |
| option interval1 0 |
| option repeat1_times 0 |
| option interval2 0 |
| option repeat2_times 0 |
| option interval3 0 |
| option repeat3_times 0 |
| option total_retry_times 20 |
| ************************************************************************/ |
| int CM_update_redialinterval(char *imsi) |
| { |
| struct uci_context *local_ctx = NULL; |
| struct uci_package *p = NULL; |
| struct uci_section *s = NULL; |
| struct uci_element *e = NULL; |
| char *mcc_str = NULL; |
| char *mnc_str = NULL; |
| char *str = NULL; |
| int mnc_len = 2; |
| |
| //get interval from uci according to the g_work_apn.mcc |
| //default value |
| if (g_redial_interval == NULL) |
| g_redial_interval = malloc(sizeof(redial_interval)); |
| |
| if (g_redial_interval == NULL) { |
| CM_Log(CM_update_redialinterval, "CM_update_redialinterval, malloc failed here"); |
| return CM_ERR_MEM; |
| } |
| |
| memset(g_redial_interval, 0, sizeof(redial_interval)); |
| |
| if (imsi == NULL) { |
| CM_Log(CM_update_redialinterval1, "CM_update_redialinterval, imsi is NULL"); |
| goto end; |
| } |
| |
| //find match redial interval from uci file |
| /*load /etc/config/wan */ |
| local_ctx = uci_wan_ctx_get(); |
| if (!local_ctx) { |
| CM_Log_E(CM_update_redialinterval3, "CM_update_redialinterval: FATAL ERROR!\n"); |
| goto end; |
| } |
| memcpy(g_redial_interval->mcc, imsi, 3); |
| change_mnc: |
| memcpy(g_redial_interval->mnc, imsi + 3, mnc_len); |
| CM_Log(CM_update_redialinterval2, "CM_update_redialinterval, mcc:%s,mnc:%s", g_redial_interval->mcc, g_redial_interval->mnc); |
| |
| p = get_uci_package(local_ctx, REDIAL_INTERVAL_PACKAGE, false); |
| if (!p) { |
| CM_Log_E(CM_update_redialinterval4, "CM_update_redialinterval: get package failed \n"); |
| goto end; |
| } |
| |
| uci_foreach_element(&p->sections, e) { |
| s = uci_to_section(e); |
| if (strcmp(s->type, OPERATION_TYPE_STR)) { |
| continue; |
| } |
| |
| mcc_str = (char *)uci_lookup_option_string(local_ctx, s, MCC_TYPE_STR); |
| mnc_str = (char *)uci_lookup_option_string(local_ctx, s, MNC_TYPE_STR); |
| if(mcc_str == NULL || mnc_str == NULL) |
| goto end; |
| CM_Log(CM_update_redialinterval5, "mcc:%s, mnc:%s", mcc_str, mnc_str); |
| |
| if((strcmp(mcc_str, g_redial_interval->mcc) == 0) &&(strcmp(mnc_str, g_redial_interval->mnc) == 0)) { |
| str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL0_STR); |
| if(str != NULL) |
| g_redial_interval->interval0 = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR); |
| if(str != NULL) |
| g_redial_interval->repeat0_times = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL1_STR); |
| if(str != NULL) |
| g_redial_interval->interval1 = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR); |
| if(str != NULL) |
| g_redial_interval->repeat1_times = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL2_STR); |
| if(str != NULL) |
| g_redial_interval->interval2 = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR); |
| if(str != NULL) |
| g_redial_interval->repeat2_times = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, INTERVAL3_STR); |
| if(str != NULL) |
| g_redial_interval->interval3 = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, REPEAT0_TIMERS_STR); |
| if(str != NULL) |
| g_redial_interval->repeat3_times = atoi(str); |
| |
| str = (char *)uci_lookup_option_string(local_ctx, s, TOTAL_RETRY_TIMES_STR); |
| if(str != NULL) |
| g_redial_interval->total_retry_times = atoi(str); |
| |
| CM_Log(CM_update_redialinterval6, "total retry times:%d", g_redial_interval->total_retry_times); |
| return CM_OK; |
| } |
| } |
| |
| if (mnc_len == 2) |
| { |
| mnc_len = 3; |
| goto change_mnc; |
| } |
| |
| end: |
| //the unit is second |
| g_redial_interval->interval0 = 5; |
| g_redial_interval->repeat0_times = 20; |
| |
| g_redial_interval->total_retry_times = 20; |
| |
| return CM_OK; |
| } |
| |
| static void CM_Try_newAPN(Mnc_Apn * apn_list, CM_Connection_Context * coninfo) |
| { |
| Apn_Info *apninfo; |
| |
| if (apn_list == NULL) |
| return; |
| |
| CM_Log(CM_Try_newAPN, "enter CM_Try_newAPN, NW_status:%d, all_try_fail %d\n", NW_status, apn_list->all_try_fail); |
| |
| if (NW_status == CM_NW_STATUS_23G ||NW_status == CM_NW_STATUS_5G ) |
| { |
| if (apn_list->all_try_fail == 1) { |
| apn_list->all_try_fail = 0; |
| apninfo = get_default_apninfo(apn_list, NULL); |
| } |
| else |
| apninfo = get_default_apninfo(apn_list, coninfo->pdpinfo->APN); |
| |
| if (apninfo == NULL && apn_list->all_try_fail == 1) { |
| if (coninfo->pdpinfo->try_num_ESM_false <= MAX_ESM_TRY_NUM) { |
| CM_Log(CM_Try_newAPN1542, "CM_Try_newAPN [23G case], try_num_ESM_false %d\n", coninfo->pdpinfo->try_num_ESM_false); |
| send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN); |
| coninfo->pdpinfo->try_num_ESM_false++; |
| } |
| } |
| else |
| { |
| if (apninfo != NULL) { |
| strcpy(coninfo->pdpinfo->APN, apninfo->apn); |
| coninfo->pdpinfo->IP_Type = apninfo->iptype; |
| coninfo->pdpinfo->IP_Type_back = apninfo->iptype; |
| //setup data call |
| send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| } |
| } else if (NW_status == CM_NW_STATUS_LTE || NW_status == CM_NW_STATUS_NOT_REGISTERED) { |
| if (apn_list->all_try_fail == 1) { |
| apn_list->all_try_fail = 0; |
| apninfo = get_inital_attach_apn(apn_list, NULL); |
| } else |
| apninfo = get_inital_attach_apn(apn_list, coninfo->pdpinfo->LteAPN); |
| if (apninfo == NULL && apn_list->all_try_fail == 1) { |
| //clear the eti flag |
| send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN_CLEARETIF); |
| if (coninfo->pdpinfo->try_num_ESM_false <= MAX_ESM_TRY_NUM) { |
| CM_Log(CM_Try_newAPN1340, "CM_Try_newAPN, try_num_ESM_false %d\n", coninfo->pdpinfo->try_num_ESM_false); |
| send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN); |
| coninfo->pdpinfo->try_num_ESM_false++; |
| } |
| } else { |
| if (apninfo != NULL) { |
| strcpy(coninfo->pdpinfo->LteAPN, apninfo->lte_apn); |
| CM_Log(CM_Try_newAPN1, "CM_Try_newAPN, current use APN:%s\n", apninfo->lte_apn); |
| send_dialmsg_to_mainthread(coninfo->pdpinfo->connectionNum, REDIAL_NEWAPN); |
| } |
| } |
| } |
| CM_Log(CM_Try_newAPN2, "leave CM_Try_newAPN\n"); |
| } |
| |
| //roam status change from non-roaming to roaming |
| void CM_Handle_ChangetoRoam(void) |
| { |
| CM_Connection_Context *tmp_Context; |
| tmp_Context = g_CM_Context; |
| int cid; |
| |
| CM_Log(CM_Handle_ChangetoRoam, "enter CM_Handle_ChangetoRoam"); |
| while (tmp_Context) { |
| CM_Log(CM_Handle_ChangetoRoam1, "CM_Handle_ChangetoRoam: pdp_type %d connect_status %d data_on_roaming %d", tmp_Context->pdpinfo->PDP_Type,\ |
| tmp_Context->connectStatus, tmp_Context->pdpinfo->data_on_roaming); |
| if (tmp_Context->pdpinfo->PDP_Type == 1 && tmp_Context->connectStatus == CM_CONNECT_CONSUCCESS |
| && tmp_Context->pdpinfo->data_on_roaming == 0) { |
| cid = tmp_Context->pdpinfo->primaryCid; |
| |
| if (tmp_Context->pdpinfo->IP_Type == IPV4) //IPV4 |
| DeleteIPInfo(cid - 1, IPV4); |
| else { //IPV4V6 or IPV6 |
| DeleteIPInfo(cid - 1, IPV4); |
| DeleteIPInfo(cid - 1, IPV6); |
| } |
| send_disconnect_2host(cid - 1, tmp_Context->pdpinfo->IP_Type); |
| |
| tmp_Context->connectStatus = CM_CONNECT_ROAM; |
| } |
| else if (tmp_Context->pdpinfo->PDP_Type == 1 |
| && ( tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY ||tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE || |
| tmp_Context->connectStatus== CM_CONNECT_REDIAL || tmp_Context->connectStatus == CM_CONNECT_WAIT_PS_ATTACH ) |
| && tmp_Context->pdpinfo->data_on_roaming == 1) |
| { |
| if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_AUTO && pipe_mode == FALSE) |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| |
| tmp_Context = tmp_Context->next; |
| } |
| |
| CM_Log(CM_Handle_ChangetoRoam2, "leave CM_Handle_ChangetoRoam"); |
| } |
| |
| //roam status change from roaming to non-roaming |
| void CM_Handle_RoamChange(void) |
| { |
| CM_Connection_Context *tmp_Context; |
| CM_Connection_Context *next_Context; |
| tmp_Context = g_CM_Context; |
| |
| CM_Log(CM_Handle_RoamChange, "enter CM_Handle_RoamChange"); |
| while (tmp_Context) { |
| next_Context = tmp_Context->next; |
| if (tmp_Context->connectStatus == CM_CONNECT_ROAM) { |
| if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { //manual |
| CM_Delete_Cur_Context(tmp_Context); |
| tmp_Context = NULL; |
| } |
| else if (check_roamStatus() == FALSE) { |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| } |
| |
| tmp_Context = next_Context; |
| } |
| |
| CM_Log(CM_Handle_RoamChange1, "leave CM_Handle_RoamChange"); |
| } |
| |
| void CM_Handle_NWChange() |
| { |
| CM_Connection_Context *tmp_Context; |
| CM_Connection_Context *cur_Context; |
| tmp_Context = g_CM_Context; |
| |
| CM_Log(CM_Handle_NWChange, "enter CM_Handle_NWChange: tmp_Context=%x", tmp_Context); |
| while (tmp_Context) { |
| cur_Context = tmp_Context; |
| CM_Log(CM_Handle_NWChange1, "CM_Handle_NWChange:connectStatus %d, NWReady %d", tmp_Context->connectStatus, NWReady); |
| if (tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE || NWReady) { |
| |
| #ifdef PIPE_MANUAL_CONNECT |
| if (pipe_mode) |
| return; |
| #endif |
| |
| if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| //need to check the network enviroment |
| if (tmp_Context->connectStatus != CM_CONNECT_CONSUCCESS && |
| tmp_Context->connectStatus != CM_CONNECT_GET_GLOBALIP_ERR && |
| tmp_Context->connectStatus != CM_CONNECT_CONNING) { |
| tmp_Context->connectStatus = CM_CONNECT_DISCON; |
| CM_Delete_Cur_Context(tmp_Context); |
| } |
| } else if (check_roamStatus() == TRUE && tmp_Context->pdpinfo->data_on_roaming == 0) { |
| tmp_Context->connectStatus = CM_CONNECT_ROAM; |
| } else { |
| if (NWReady == 0) |
| { |
| CM_Log(CM_Handle_NWChange10, "CM_Handle_NWChange: nw not ready, wait 5 seconds to redial"); |
| sleep(5); |
| } |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| } |
| tmp_Context = cur_Context->next; |
| } |
| |
| CM_Log(CM_Handle_NWChange2, "leave CM_Handle_NWChange"); |
| |
| } |
| |
| void CM_Handle_Reject() |
| { |
| CM_Connection_Context *tmp_Context; |
| CM_Connection_Context *cur_Context; |
| tmp_Context = g_CM_Context; |
| |
| CM_Log(CM_Handle_Reject, "enter CM_Handle_Reject"); |
| while (tmp_Context) { |
| cur_Context = tmp_Context; |
| CM_Log(CM_Handle_Reject1, "connectStatus %d, connectNum %d", tmp_Context->connectStatus, tmp_Context->pdpinfo->connectionNum); |
| if (tmp_Context->connectStatus == CM_CONNECT_DISCON) { |
| if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) //manual |
| CM_Delete_Cur_Context(tmp_Context); |
| else { |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| } |
| else if (tmp_Context->connectStatus == CM_CONNECT_WAIT_NWCHANGE) { |
| if (getErrorIndFlag()) { |
| if (dialer_pdp_cause_new_apn()) |
| CM_Try_newAPN(g_work_apn, tmp_Context); |
| } |
| } |
| |
| tmp_Context = cur_Context->next; |
| } |
| |
| CM_Log(CM_Handle_Reject3, "leave CM_Handle_Reject"); |
| } |
| |
| void CM_Handle_Redial(int connectionNum) |
| { |
| CM_Connection_Context *tmp_Context; |
| tmp_Context = g_CM_Context; |
| CM_Log(CM_Handle_Redial_1305, "Enter CM_Handle_Redial, ctx 0x%x", tmp_Context); |
| while (tmp_Context) { |
| CM_Log(CM_Handle_Redial_1307, "CM_Handle_Redial, num=%d, Status=%d, retrytime=%d, dialFailureCode=%d", |
| tmp_Context->pdpinfo->connectionNum, tmp_Context->connectStatus, tmp_Context->retryTime, tmp_Context->dialFailureCode); |
| if (tmp_Context->pdpinfo->connectionNum == connectionNum && |
| (tmp_Context->connectStatus == CM_CONNECT_REDIAL |
| || tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY)) { |
| if (tmp_Context->pdpinfo->autoconnect == CM_CONTYPE_MANUAL) { |
| //need to check the network enviroment |
| tmp_Context->connectStatus = CM_CONNECT_DISCON; |
| goto redial_continue; |
| } |
| |
| if (check_roamStatus() == TRUE && tmp_Context->pdpinfo->data_on_roaming == 0) { |
| tmp_Context->connectStatus = CM_CONNECT_ROAM; |
| goto redial_continue; |
| } |
| |
| if (tmp_Context->dialFailureCode == 33 || tmp_Context->dialFailureCode == 34 |
| || tmp_Context->dialFailureCode == 27 || tmp_Context->dialFailureCode == 29) { |
| CM_Try_newAPN(g_work_apn, tmp_Context); |
| goto redial_continue; |
| } |
| |
| if (tmp_Context->connectStatus == CM_CONNECT_REDIAL) { |
| if (getUnknownPpdCause() == 0xFF) { |
| sleep(2); |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| goto redial_continue; |
| } |
| } |
| |
| if (tmp_Context->retryTime >= 0 && tmp_Context->retryTime < CM_INT_MAX) { |
| if ( tmp_Context->connectStatus != CM_CONNECT_DIAL_IMMEDIATELY) { |
| CM_Log(CM_Handle_Redial_1334, "CM_Handle_Redial, wait %d ms, then start dial", tmp_Context->retryTime); |
| usleep(tmp_Context->retryTime * 1000); |
| } |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| goto redial_continue; |
| } |
| |
| if (tmp_Context->connectStatus == CM_CONNECT_DIAL_IMMEDIATELY) { |
| CM_Log(CM_Handle_Redial, "CM_Handle_Redial, start dial immediately"); |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| else if (tmp_Context->dialFailureCode == PDP_FAIL_ERROR_UNSPECIFIED) { |
| CM_Log(CM_Handle_Redial1, "CM_Handle_Redial, FailureCode is ERROR_UNSPECIFIED"); |
| if (NW_status == CM_NW_STATUS_NOT_REGISTERED) { |
| CM_Log(CM_Handle_Redial2, "CM_Handle_Redial, network not registered\n"); |
| //need to dial when nw registered |
| tmp_Context->connectStatus = CM_CONNECT_WAIT_NWCHANGE; |
| } else { |
| //need to check network interval array |
| if (redial_sleep(tmp_Context->dial_cnt)) { |
| tmp_Context->dial_cnt++; |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| else if (!g_redial_interval) |
| { |
| sleep(2); |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| else { |
| CM_Log(CM_Handle_Redial3, "CM_Handle_Redial, dial count exceeds the max number"); |
| } |
| } |
| }//end PDP_FAIL_ERROR_UNSPECIFIED |
| else { |
| CM_Log(CM_Handle_Redial4, "CM_Handle_Redial, FailureCode is %d, connect status %d, NW_status %d, dial_cnt %d", |
| tmp_Context->dialFailureCode, tmp_Context->connectStatus, NW_status, tmp_Context->dial_cnt); |
| if(NW_status == CM_NW_STATUS_NOT_REGISTERED) |
| tmp_Context->connectStatus = CM_CONNECT_WAIT_NWCHANGE; |
| else { |
| if(redial_sleep(tmp_Context->dial_cnt)) { |
| tmp_Context->dial_cnt++; |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| else if (!g_redial_interval) |
| { |
| sleep(2); |
| send_dialmsg_to_mainthread(tmp_Context->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| else |
| { |
| CM_Log(CM_Handle_Redial1798, "CM_Handle_Redial, redial count exceeds the max number"); |
| } |
| } |
| } |
| }//end if |
| redial_continue: |
| tmp_Context = tmp_Context->next; |
| }//end while |
| |
| CM_Log(CM_Handle_Redial5, "CM_Handle_Redial done "); |
| } |
| |
| void CM_Handle_DefaultDataCall() |
| { |
| #ifdef PIPE_MANUAL_CONNECT |
| if (pipe_mode) |
| return; |
| #endif |
| |
| CM_Log(CM_Handle_DefaultDataCall, "CM_Handle_DefaultDataCall: wait some seconds and set default data call again"); |
| sleep(4); |
| send_dialmsg_to_mainthread(-1, REDIAL_DEFAULT_DATACALL); |
| CM_Log(CM_Handle_DefaultDataCall1, "CM_Handle_DefaultDataCall: send msg REDIAL_DEFAULT_DATACALL done"); |
| } |
| |
| static void CM_Handle_SingleStack() |
| { |
| send_dialmsg_to_mainthread(-1, REDIAL_SINGLE_STACK); |
| CM_Log(CM_Handle_SingleStack, "CM_Handle_SingleStack: send REDIAL_SINGLE_STACK to mainthread"); |
| } |
| |
| CM_Connection_Context *findContextByConnum(int connectionNum) |
| { |
| CM_Connection_Context *tmp_Context; |
| tmp_Context = g_CM_Context; |
| |
| while (tmp_Context) { |
| if (tmp_Context->pdpinfo->connectionNum == connectionNum) |
| return tmp_Context; |
| |
| tmp_Context = tmp_Context->next; |
| } |
| |
| return NULL; |
| } |
| |
| CM_Connection_Context *cm_get_ctx_by_cid(int cid) |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| |
| while (ctx) { |
| if (ctx->pdpinfo->primaryCid == cid) |
| return ctx; |
| |
| ctx = ctx->next; |
| } |
| return NULL; |
| } |
| |
| int cm_get_conn_num_by_cid(int cid) |
| { |
| int conn_num = CM_INT_MAX; |
| |
| CM_Connection_Context *ctx = cm_get_ctx_by_cid(cid); |
| if (ctx && ctx->pdpinfo) { |
| conn_num = ctx->pdpinfo->connectionNum; |
| } |
| |
| return conn_num; |
| } |
| |
| void CM_Redial_Function(msg_hdr * msg) |
| { |
| #ifdef PIPE_MANUAL_CONNECT |
| if (pipe_mode) |
| return; |
| #endif |
| |
| pthread_mutex_lock(&cm_mutex); |
| CM_Log(CM_Redial_Function1887, "[redial] CM_Redial_Function, msgtype %d, cm_mutex locked\n", msg->msgtype); |
| switch (msg->msgtype) { |
| case REDIAL_ROAMCHANGE: |
| CM_Handle_RoamChange(); |
| break; |
| case REDIAL_NWCHANGE: |
| CM_Handle_NWChange(); |
| break; |
| case REDIAL_IMMED: |
| case REDIAL_NEWAPN: |
| CM_Handle_Redial(msg->connectionNum); |
| break; |
| case REDIAL_REJECT: |
| CM_Handle_Reject(); |
| break; |
| case REDIAL_DEFAULT_DATACALL: |
| CM_Handle_DefaultDataCall(); |
| break; |
| case REDIAL_SINGLE_STACK: |
| CM_Handle_SingleStack(); |
| break; |
| default: |
| CM_Log(CM_Redial_Function1, "CM_Redial_Function, invalid msg type"); |
| break; |
| } |
| pthread_mutex_unlock(&cm_mutex); |
| CM_Log(CM_Redial_Function2, "[redial] CM_Redial_Function done, cm_mutex unlocked\n"); |
| } |
| |
| static bool check_merger_attachapn(AttachApn_Info * attachapn, Apn_Info * apninfo) |
| { |
| bool ret = FALSE; |
| |
| if(matchApnNetworkIdentifier(attachapn->apn, apninfo->lte_apn) == 0 && matchApnNetworkIdentifier(apninfo->lte_apn,attachapn->apn) == 0) { |
| CM_Log(check_merger_attachapn, "check_merger_attachapn, attach apn change"); |
| strcpy(attachapn->apn, apninfo->lte_apn); |
| ret = TRUE; |
| } |
| |
| if(attachapn->iptype != apninfo->iptype) { |
| CM_Log(check_merger_attachapn1, "check_merger_attachapn, ip type change"); |
| attachapn->iptype = apninfo->iptype; |
| ret = TRUE; |
| } |
| |
| if(strcmp(attachapn->authtype, apninfo->lte_authtype)) { |
| CM_Log(check_merger_attachapn2, "check_merger_attachapn, authtype change"); |
| strcpy(attachapn->authtype, apninfo->lte_authtype); |
| ret = TRUE; |
| } |
| |
| if(strcmp(attachapn->username, apninfo->lte_usrname)) { |
| CM_Log(check_merger_attachapn3, "check_merger_attachapn, username change"); |
| strcpy(attachapn->username, apninfo->lte_usrname); |
| ret = TRUE; |
| } |
| |
| if(strcmp(attachapn->passwd, apninfo->lte_paswd)) { |
| CM_Log(check_merger_attachapn4, "check_merger_attachapn, authtype change"); |
| strcpy(attachapn->passwd, apninfo->lte_paswd); |
| ret = TRUE; |
| } |
| |
| return ret; |
| } |
| |
| static bool cm_need_reattach_for_ipv6(int iptype) |
| { |
| char *imsi = cm_get_cellular_imsi(); |
| bool need_reattach = false; |
| |
| if (iptype != IPV4V6 && iptype != IPV6) |
| return need_reattach; |
| |
| if (get_ipv4_only_allowed()) |
| return need_reattach; |
| |
| if (imsi) |
| { |
| if (strncmp(imsi, "46605", sizeof("46605")) == 0) |
| need_reattach = true; |
| } |
| |
| return need_reattach; |
| } |
| |
| int cm_set_cfun(int value) |
| { |
| char at_str[MAX_STR_LEN] = { 0 }; |
| int ret = 0, size = 0; |
| int power_state = 1; |
| |
| if (value != 1) |
| { |
| memset(at_str, 0, MAX_STR_LEN); |
| snprintf(at_str, MAX_STR_LEN - 1, "AT+CFUN=%d", value); |
| size = strlen(at_str) + 1; |
| blob_buf_init(&cm_b, 0); |
| rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_SEND_ATCMD, (void *)at_str, size); |
| } |
| else |
| { |
| blob_buf_init(&cm_b, 0); |
| rilutil_makeRequestBlobDSMaster(&cm_b, RIL_REQUEST_RADIO_POWER, &power_state, 1); |
| } |
| |
| 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(cm_set_cfun1838, "cm_set_cfun, ubus_invoke failed %s\n", ubus_strerror(ret)); |
| } |
| |
| return ret; |
| } |
| |
| int cm_set_psdc(int enable) |
| { |
| char at_str[MAX_STR_LEN] = { 0 }; |
| int ret = 0, size = 0; |
| |
| memset(at_str, 0, MAX_STR_LEN); |
| snprintf(at_str, MAX_STR_LEN - 1, "AT*PSDC=%d", enable); |
| size = strlen(at_str) + 1; |
| 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(cm_set_cfun1838, "%s: ubus_invoke failed %s\n", __func__, ubus_strerror(ret)); |
| } |
| |
| return ret; |
| } |
| |
| static int cm_data_call_list_exist(int cid) |
| { |
| Data_Call_Response_List *list = NULL; |
| bool exist = false; |
| int num = 0; |
| |
| QueryDataCall(NULL); |
| |
| if (get_data_call_response_list()) |
| { |
| list = get_data_call_response_list(); |
| while(list) |
| { |
| if (list->PDP.cid == cid) |
| exist = true; |
| |
| num++; |
| list = list->next; |
| } |
| } |
| |
| if (num > 0) |
| { |
| if (exist) |
| return num; |
| else |
| return -1; |
| } |
| else |
| return -1; |
| } |
| |
| void cm_set_atcmd_data_call(Apn_Info *apn_info) |
| { |
| CM_Connection_Context *ctx = NULL; |
| int ip_type = -1, connect_status, changed, just_stop = 0; |
| char value_buf[PROPERTY_VALUE_MAX] = { 0 }; |
| int need_reattach = false; |
| int exist_type = 0; |
| |
| ctx = get_match_pdp(apn_info); |
| |
| CM_Log(cm_set_atcmd_data_call1,"[AT DIAL]: %s , connection num %d, match ctx %x", __func__, apn_info->connection_num,ctx); |
| if (!ctx) { |
| if (apn_info->enable == 0) { |
| CM_Log(cm_set_atcmd_data_call1749,"[AT DIAL]: current cid [%d] in disconnected status, not allow to deactive", apn_info->cid); |
| return; |
| } |
| ctx = create_new_pdp_ctx(apn_info); |
| /*do NOT set first dial flag, then dialer will check network register status for some seconds*/ |
| ctx->first_dial = 0; |
| |
| if (cm_need_reattach_for_ipv6(apn_info->iptype)) { |
| if (ccinet_ipv6_global_ready(apn_info->cid, 0) == false) { |
| need_reattach = true; |
| goto stopdial; |
| } |
| } |
| goto startdial; |
| } else { |
| ip_type = ctx->pdpinfo->IP_Type; |
| if (apn_info->enable == 0) { |
| just_stop = 1; |
| goto stopdial; |
| } |
| #ifdef CONFIG_ZGDCONT_MULTI_PDP |
| if (cm_get_atcmd_apn_state(apn_info->cid) == CM_CONNECT_CONNING) { |
| CM_Log(cm_set_atcmd_data_call1764,"[AT DIAL]: current cid [%d] in connecting status, not allow to active in the state", apn_info->cid); |
| return; |
| } |
| #endif |
| |
| if (cm_need_reattach_for_ipv6(apn_info->iptype)) { |
| if (ccinet_ipv6_global_ready(apn_info->cid, 0) == false) { |
| need_reattach = true; |
| goto stopdial; |
| } |
| } |
| |
| changed = check_merger_pdpcontext(apn_info, ctx, PDP_CONFIG_ZGDCONT); |
| if (!changed) |
| { |
| #ifdef CONFIG_ZGDCONT_MULTI_PDP |
| /* nothing changed, for connected status no need to trigger dialer again */ |
| if (cm_get_atcmd_apn_state(apn_info->cid) == CM_CONNECT_CONSUCCESS) { |
| CM_Log(cm_set_atcmd_data_call1769,"[AT DIAL]: nothing changed, no need to redail again in connected status"); |
| return; |
| } |
| #endif |
| |
| goto startdial; |
| } |
| |
| CM_Log(cm_set_atcmd_data_call1927,"[AT DIAL]:destroy current PDP, cid [%d], ip_type [%d]", ctx->pdpinfo->primaryCid, ip_type); |
| } |
| |
| stopdial: |
| if (need_reattach) { |
| exist_type = cm_data_call_list_exist(apn_info->cid); |
| CM_Log(cm_set_atcmd_data_call1934,"[AT DIAL]: data call list exist type [%d] for cid [%d]", exist_type, apn_info->cid); |
| if (exist_type == -1) { |
| /* cid not exist, no need deactive */ |
| goto startdial; |
| } |
| } |
| |
| if (ip_type != -1) |
| DeleteIPInfo(ctx->pdpinfo->primaryCid - 1, ip_type); |
| |
| connect_status = ctx->connectStatus; |
| if (exist_type == 1) { |
| /* only cid exist, need CFUN4->CFUN1 */ |
| cm_set_cfun(4); |
| sleep(1); |
| cm_set_cfun(1); |
| sleep(2); |
| |
| /* wait register status */ |
| ctx->first_dial = 1; |
| goto startdial; |
| } else { |
| if(ctx->pdpinfo->PDP_Type == 1) |
| StopDialer(ctx->pdpinfo->primaryCid); |
| else |
| StopDialer(ctx->pdpinfo->secondaryCid); |
| } |
| |
| if (connect_status == CM_CONNECT_CONSUCCESS) |
| { |
| if (ip_type != -1) |
| send_disconnect_2host(ctx->pdpinfo->primaryCid - 1, ip_type); |
| ctx->connectStatus = CM_CONNECT_DISCON; |
| cm_record_nwactivity(ctx, true); |
| } |
| |
| ctx->connectStatus = CM_CONNECT_DISCON; |
| ctx->pdpinfo->primaryCid = apn_info->cid; |
| ctx->pdpinfo->secondaryCid = 0; |
| |
| startdial: |
| if (!just_stop) { |
| |
| #ifdef PIPE_MANUAL_CONNECT |
| if (pipe_mode) |
| ctx->pdpinfo->autoconnect = CM_CONTYPE_MANUAL; |
| #endif |
| ctx->pdpinfo->primaryCid = apn_info->cid; |
| ctx->pdpinfo->is_default = apn_info->Extra_params.lte_default; |
| |
| CM_Log(cm_set_atcmd_data_call1,"[AT DIAL]: show dial context start"); |
| showConContext(ctx); |
| CM_Log(cm_set_atcmd_data_call2, "[AT DIAL]: show dial context end"); |
| |
| sprintf(value_buf, "%d", ctx->pdpinfo->primaryCid); |
| property_set(PROP_DEFINED_CID, value_buf); |
| CM_Log(cm_set_atcmd_data_call3, "[AT DIAL]: set sys.defined.cid value to %s", value_buf); |
| if (pipe_mode && g_last_default_cid != 0xFF && ctx->pdpinfo->is_default) |
| { |
| send_if_command(g_last_default_cid, DOWN, IPV4); |
| send_if_command(g_last_default_cid, DOWN, IPV6); |
| } |
| |
| if (check_roamStatus() == TRUE && apn_info->Extra_params.data_on_roaming == 0) |
| { |
| ctx->connectStatus = CM_CONNECT_ROAM; |
| |
| CM_Log(cm_set_atcmd_data_call1842, "[AT DIAL]: disable data on roaming"); |
| if (CM_CheckContextValid(ctx)) |
| send_disconnect_2host( ctx->pdpinfo->primaryCid - 1, ctx->pdpinfo->IP_Type); |
| return; |
| } |
| |
| ctx->connectStatus = CM_CONNECT_CONNING; |
| cm_set_atcmd_apn_state(apn_info->cid, CM_CONNECT_CONNING); |
| CM_StartDialer(ctx); |
| |
| if (CM_CheckContextValid(ctx)) |
| { |
| CM_Log(cm_set_atcmd_data_call4, "[AT DIAL]:connect status %d, dialFailureCode %d, cid %d, auto connect %d, is default %d", |
| ctx->connectStatus, ctx->dialFailureCode, ctx->pdpinfo->primaryCid, ctx->pdpinfo->autoconnect, ctx->pdpinfo->is_default); |
| if ((ctx->dialFailureCode != 0) && (ctx->dialFailureCode != PDP_FAIL_GET_GLOBALIP)) { |
| #if 0 |
| if (ctx->retryTime != CM_INT_MAX) { |
| ctx->connectStatus = CM_CONNECT_REDIAL; |
| /*send redial msg*/ |
| send_redialmsg_to_redialthread(ctx->pdpinfo->connectionNum, REDIAL_IMMED); |
| } |
| #endif |
| /*report the dial fail status*/ |
| send_disconnect_2host( ctx->pdpinfo->primaryCid - 1, ctx->pdpinfo->IP_Type); |
| } |
| } |
| } |
| } |
| |
| int cm_disconn_partner(int cid) |
| { |
| CM_Connection_Context *ctx = g_CM_Context; |
| int ret = -1; |
| if (cid <= 0) |
| return -1; |
| |
| while (ctx) |
| { |
| if (ctx->pdpinfo && ctx->pdpinfo->parent_cid == cid) |
| { |
| if (ctx->pdpinfo->primaryCid != cid) |
| { |
| CM_Log(cm_disconn_partner, "cm_disconn_partner: disconn cid %d, parent cid %\n", ctx->pdpinfo->primaryCid, ctx->pdpinfo->parent_cid); |
| StopDialer(ctx->pdpinfo->primaryCid); |
| CM_Delete_Cur_Context(ctx); |
| ret = 0; |
| break; |
| } |
| } |
| |
| ctx = ctx->next; |
| } |
| |
| return ret; |
| } |
| |
| //create new PDP, parse from apn_list |
| bool CM_Create_Pdp(Mnc_Apn * apn_list) |
| { |
| Apn_Info *attach_apn; |
| Apn_Info *default_apn; |
| CM_Connection_Context *match_Context; |
| bool ret = FALSE; |
| int back_iptype = 0; |
| |
| if (apn_list == NULL) |
| return FALSE; |
| |
| attach_apn = get_inital_attach_apn(apn_list, NULL); |
| |
| if (attach_apn != NULL) { |
| if (strlen(attach_apn->lte_apn) == 0) |
| strcpy(attach_apn->lte_apn, attach_apn->apn); |
| CM_Log(CM_Create_Pdp, "CM_Create_Pdp: initial attach apn:%s\n", attach_apn->lte_apn); |
| |
| if(g_attachapn == NULL) { |
| g_attachapn = (AttachApn_Info *)malloc(sizeof(AttachApn_Info)); |
| memset(g_attachapn, 0, sizeof(AttachApn_Info)); |
| g_attachapn->iptype = attach_apn->iptype; |
| strcpy(g_attachapn->apn, attach_apn->lte_apn); |
| strcpy(g_attachapn->authtype, attach_apn->lte_authtype); |
| strcpy(g_attachapn->username, attach_apn->lte_usrname); |
| strcpy(g_attachapn->passwd, attach_apn->paswd); |
| SetInitialAttachAPN(attach_apn, true); |
| }else { |
| ret = check_merger_attachapn(g_attachapn, attach_apn); |
| if(ret == TRUE) |
| SetInitialAttachAPN(attach_apn, true); |
| } |
| } |
| |
| default_apn = get_default_apninfo(apn_list, NULL); |
| |
| if (default_apn) { |
| CM_Log(CM_Create_Pdp1, "CM_Create_Pdp: default apn %s, iptype %d\n", default_apn->apn, default_apn->iptype); |
| match_Context = get_match_pdp(default_apn); |
| if (match_Context == NULL) { |
| CM_Log(CM_Create_Pdp2, "CM_Create_Pdp: NO matched pdp context find, will create new one\n"); |
| match_Context = create_new_pdp_ctx(default_apn); |
| ret = TRUE; |
| } else { |
| //check and merger pdp context |
| back_iptype = match_Context->pdpinfo->IP_Type; |
| CM_Log(CM_Create_Pdp3, "CM_Create_Pdp: check and merge pdp context, back_iptype %d", back_iptype); |
| ret = check_merger_pdpcontext(default_apn, match_Context, 0); |
| if(ret == TRUE) |
| { |
| if(match_Context->connectStatus == CM_CONNECT_CONSUCCESS || match_Context->connectStatus == CM_CONNECT_GET_GLOBALIP_ERR) |
| { |
| CM_Log(CM_Create_Pdp4, "CM_Create_Pdp: destroy pdp connection, apn [%s]", match_Context->pdpinfo->APN); |
| match_Context->connectStatus = CM_CONNECT_DISCON; |
| |
| if (cm_disconn_partner(match_Context->pdpinfo->primaryCid) == 0) |
| { |
| match_Context->pdpinfo->IP_Type = default_apn->iptype; |
| } |
| |
| DeleteIPInfo(match_Context->pdpinfo->primaryCid - 1, back_iptype); |
| if(match_Context->pdpinfo->PDP_Type == 1) |
| StopDialer(match_Context->pdpinfo->primaryCid); |
| else |
| StopDialer(match_Context->pdpinfo->secondaryCid); |
| |
| match_Context->pdpinfo->primaryCid = 0; |
| match_Context->pdpinfo->secondaryCid = 0; |
| } |
| |
| } |
| } |
| showConContext(match_Context); |
| if (ret == TRUE) { |
| match_Context->first_dial = 1; |
| CM_StartDialer(match_Context); |
| if (CM_CheckContextValid(match_Context)) |
| { |
| if ((match_Context->dialFailureCode != 0) &&(match_Context->dialFailureCode != PDP_FAIL_GET_GLOBALIP)) { |
| if (match_Context->retryTime != CM_INT_MAX) { |
| match_Context->connectStatus = CM_CONNECT_REDIAL; |
| //call redial method here |
| send_redialmsg_to_redialthread(match_Context->pdpinfo->connectionNum, |
| REDIAL_IMMED); |
| } |
| } |
| } |
| } else { |
| CM_Log(CM_Create_Pdp5, "CM_Create_Pdp: NO need to dial"); |
| } |
| } else { |
| CM_Log(CM_Create_Pdp6, "CM_Create_Pdp: NO default APN"); |
| dialer_query_defaultdatacall(); |
| } |
| |
| //need to add more type here |
| Apn_Info *fota_apn; |
| |
| fota_apn = get_fota_apninfo(apn_list); |
| |
| if(fota_apn != NULL) |
| { |
| CM_Log(CM_Create_Pdp7, "%s: fota apn %s", fota_apn->apn); |
| } |
| |
| return TRUE; |
| } |