/**************************************************************************** * * Copy right: 2019-, Copyrigths of EigenComm Ltd. * File name: plat_config.c * Description: platform configuration source file * History: Rev1.0 2019-01-18 * ****************************************************************************/ #include #include #include "lfs_port.h" #include "ctcc_dm.h" #include "osasys.h" #include "ostask.h" #include DEBUG_LOG_HEADER_FILE #include "networkmgr.h" #include "dm_task.h" #include "ps_event_callback.h" #include "ps_lib_api.h" #include "HTTPClient.h" #include "base64.h" #define CTDMCONN_TASK_STACK_SIZE 1024 #define CTDM_MODULE_URL "http://zzhc.vnet.cn:9999/" #define CTDM_SMART_URL "http://zzhc.vnet.cn:9998/" #define CTDM_CONTTYPE "application/encrypted-json" #define CTDM_HTTP_RECV_BUF_SIZE (300) #define CTDM_HTTP_HEAD_BUF_SIZE (400) #define CTDM_MACHINESTATE(S) \ ((S) == CTDM_INIT_STATE ? "CTDM_INIT_STATE" : \ ((S) == CTDM_SIM_READY ? "CTDM_SIM_READY" : \ ((S) == CTDM_NOT_RIGHT_SIM ? "CTDM_NOT_RIGHT_SIM" : \ ((S) == CTDM_IPREADY_STATE ? "CTDM_IPREADY_STATE" : \ ((S) == CTDM_IDLE_STATE ? "CTDM_IDLE_STATE" : \ ((S) == CTDM_TIME_TO_RETRY ? "CTDM_TIME_TO_RETRY" : \ ((S) == CTDM_WAIT_IPREADY ? "CTDM_WAIT_IPREADY" : \ "Unknown"))))))) extern uint32_t mwGetSimCcidValue(uint8_t *ccid, uint8_t len); extern uint32_t mwSetSimCcidValue(uint8_t *ccid, uint8_t len); extern uint8_t mwGetCtccAutoRegFlag(void); extern void mwSetCtccAutoRegFlag(uint8_t autoReg); extern INT32 psSetEpsAttached (uint32_t atHandle, bool fAttached); extern int mbedtls_base64_encode( unsigned char *dst, size_t dlen, size_t *olen, const unsigned char *src, size_t slen ); static uint8_t ctccDmSlpHandler = 0xff; static uint8_t curImei[IMEI_LEN+1] = {0}; static uint8_t curImsi[IMSI_LEN+1] = {0}; static uint8_t curCCID[MID_WARE_DM_SIM_CCID_LEN+1] = {0}; static bool running = false; static ctdmStateMachine_t stateMachine = CTDM_INIT_STATE; static HttpClientContext gHttpClient = {0}; static MWNvmCfgDmCtccParam* dmCtccParam = NULL; static INT32 ctdmPSUrcCallback(PsEventID eventID, void *param, uint32_t paramLen) { NmAtiNetInfoInd *netif = NULL; CmiSimImsiStr *imsi = NULL; uint8_t imsiStr[IMSI_LEN+1] = {0}; switch(eventID) { case PS_URC_ID_SIM_READY: { imsi = (CmiSimImsiStr *)param; memcpy(imsiStr, imsi->contents, imsi->length); if((imsiStr[0] == '4')&&(imsiStr[1] == '6')&&(imsiStr[2] == '0')&& (((imsiStr[3] == '0')&&(imsiStr[4] == '3'))|| ((imsiStr[3] == '0')&&(imsiStr[4] == '5'))|| ((imsiStr[3] == '1')&&(imsiStr[4] == '1')))) { stateMachine = CTDM_SIM_READY; ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_1_1, P_INFO, "sim is ready and it's ctcc card"); } else { stateMachine = CTDM_NOT_RIGHT_SIM; ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_1_2, P_INFO, "it's not ctcc card, abort autoreg"); } break; } case PS_URC_ID_PS_NETINFO: { netif = (NmAtiNetInfoInd *)param; if (netif->netifInfo.netStatus == NM_NETIF_ACTIVATED) { if(stateMachine == CTDM_WAIT_IPREADY){ ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_2, P_INFO, "PSIF network active change statemachine to DM_IPREADY_STATE"); stateMachine = CTDM_IPREADY_STATE; }else{ ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_2_1, P_INFO, "PSIF network active but state is:%d",stateMachine); } } else if (netif->netifInfo.netStatus == NM_NETIF_OOS) { ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_2_2, P_INFO, "PSIF network OOS"); } else if (netif->netifInfo.netStatus == NM_NO_NETIF_OR_DEACTIVATED || netif->netifInfo.netStatus == NM_NO_NETIF_NOT_DIAL) { ECPLAT_PRINTF(UNILOG_DM, ctdmPSUrcCallback_2_3, P_INFO, "PSIF network deactive"); } break; } default:break; } return 0; } bool checkNetworkReadyTimeOut(uint8_t times) { uint8_t number = 0; NmAtiNetifInfo netInfo; while(number < times) { appGetNetInfoSync(0, &netInfo); if(netInfo.netStatus == NM_NETIF_ACTIVATED) { return true; } else { osDelay(500); } number++; } return false; } static uint32_t ctdmGetCellid() { uint32_t cellID = 6888; CmiDevGetExtStatusCnf ueExtStatusInfo; memset(&ueExtStatusInfo, 0, sizeof(CmiDevGetExtStatusCnf)); if(appGetUeExtStatusInfoSync(UE_EXT_STATUS_ERRC, &ueExtStatusInfo) == CMS_RET_SUCC) { cellID = ueExtStatusInfo.rrcStatus.cellId; ECPLAT_PRINTF(UNILOG_DM, ctdmGetCellid_1, P_INFO, "Cell ID = %d", cellID); } else { ECPLAT_PRINTF(UNILOG_DM, ctdmGetCellid_2, P_INFO, "get cellid failed use default"); } return cellID; } static HTTPResult ctdmhttppost(char* postbuf, uint32_t postlen, uint8_t portType) { HTTPResult ret = HTTP_OK; HttpClientData clientData = {0}; uint8_t code = 0; char *responseBuf = NULL; char * curUrl = NULL; if(portType == 1){ curUrl = CTDM_SMART_URL; }else{ curUrl = CTDM_MODULE_URL; } clientData.respBuf = mallocEc(CTDM_HTTP_RECV_BUF_SIZE); clientData.respBufLen = CTDM_HTTP_RECV_BUF_SIZE; clientData.headerBuf = mallocEc(CTDM_HTTP_HEAD_BUF_SIZE); memset(clientData.headerBuf, 0, CTDM_HTTP_HEAD_BUF_SIZE); clientData.headerBufLen = CTDM_HTTP_HEAD_BUF_SIZE; clientData.postBuf = postbuf; clientData.postBufLen = postlen; clientData.postContentType = CTDM_CONTTYPE; ret = httpConnect(&gHttpClient, curUrl); if(ret == HTTP_OK) { ret = httpSendRequest(&gHttpClient, curUrl, HTTP_POST, &clientData); if (ret != HTTP_OK){ goto exit; } do { memset(clientData.respBuf, 0, CTDM_HTTP_RECV_BUF_SIZE); memset(clientData.headerBuf, 0, CTDM_HTTP_HEAD_BUF_SIZE); ret = httpRecvResponse(&gHttpClient, &clientData); ECPLAT_PRINTF(UNILOG_DM, ctdmhttppost_1, P_INFO, "respCode=%d,recvContentLength=%d", gHttpClient.httpResponseCode, clientData.recvContentLength); if(ret == HTTP_OK) { responseBuf = mallocEc(clientData.recvContentLength+1); memset(responseBuf, 0, clientData.recvContentLength+1); memcpy(responseBuf, clientData.respBuf, clientData.blockContentLen); } } while (ret == HTTP_MOREDATA || ret == HTTP_CONN ); } if(ret != HTTP_OK) { ECOMM_TRACE(UNILOG_DM, ctdmhttppost_2, P_INFO, 1, "ret=%d", ret); } else { ECPLAT_PRINTF(UNILOG_DM, ctdmhttppost_3, P_INFO, "resp:%s", (uint8_t*)responseBuf); char* strPtr = strstr(responseBuf, "resultCode"); strPtr += 12; if( sscanf(strPtr, "\"%d\"%*[^\"]", &code) != 1 ) { //Cannot match string, error ECPLAT_PRINTF(UNILOG_DM, ctdmhttppost_3_1, P_INFO, "parse resposne fail"); ret = HTTP_PARSE; }else{ if(code == 0){ ECPLAT_PRINTF(UNILOG_DM, ctdmhttppost_4, P_INFO, "autoreg success"); ret = HTTP_OK;//HTTP_INTERNAL; }else{ ECPLAT_PRINTF(UNILOG_DM, ctdmhttppost_5, P_INFO, "autoreg code=%d ", code); ret = HTTP_PARSE; } } } exit: freeEc(clientData.respBuf); freeEc(clientData.headerBuf); if(responseBuf != NULL){ freeEc(responseBuf); } return ret; } int8_t ctdmAutoRegHttp(uint8_t *IMEI, uint8_t *ICCID, uint8_t *IMSI) { char rawPayload[SRC_DATA_LEN] = {0}; char extrPayload[50] = {0}; int rawPayloadLen = 0; char *encodePayload = NULL; int encodePayloadLen = 0; int outLen = 0; uint32_t cellid = 0; char time[20] = {0}; utc_timer_value_t timeUtc; int8_t ret = 0; HTTPResult result = HTTP_OK; MWNvmCfgDmCtccParam2 param2 = {0}; ret = appGetSystemTimeUtcSync(&timeUtc);//appCheckSystemTimeSync if(ret == 0) { snprintf(time, 20, "%d-%02d-%02d %02d:%02d:%02d", timeUtc.UTCtimer1>>16, (timeUtc.UTCtimer1&0xFF00)>>8, (timeUtc.UTCtimer1&0xFF), (timeUtc.UTCtimer2>>24)+8, (timeUtc.UTCtimer2&0xFF0000)>>16, (timeUtc.UTCtimer2&0xFF00)>>8); } else { snprintf(time, 20, "2021-05-20 15:12:43"); } cellid = ctdmGetCellid(); ECPLAT_PRINTF(UNILOG_DM, ctdmAutoRegHttp_1, P_INFO, "time=%s", (uint8_t*)time); sprintf((char*)rawPayload, "{\"REGVER\":\"5.0\",\"MEID\":\"\",\"MODEL\":\"%s\",\"SWVER\":\"%s\",\"IMEI1\":\"%s\",\"SIM1CDMAIMSI\":\"\",\"SIM1ICCID\":\"%s\",\"SIM1LTEIMSI\":\"%s\",\"SIM1CELLID\":\"%d\",\"REGDATE\":\"%s\"", dmCtccParam->model, dmCtccParam->swver, IMEI, ICCID, IMSI, cellid, time); mwNvmCfgGetDmCtccParam2(¶m2); if(strlen((char*)param2.ueType) != 0) { sprintf(extrPayload, ",\"UETYPE\":\"%s\",\"OSVER\":\"%s\"}", param2.ueType, param2.osVer); strcat(rawPayload, extrPayload); } else { strcat(rawPayload, "}"); } rawPayloadLen = strlen(rawPayload); ECPLAT_PRINTF(UNILOG_DM, ctdmAutoRegHttp_3, P_INFO, "rawpayload=%s", (uint8_t*)rawPayload); encodePayload = mallocEc(DST_DATA_LEN); memset(encodePayload, 0, DST_DATA_LEN); mbedtls_base64_encode((unsigned char *)encodePayload, (size_t)DST_DATA_LEN, (size_t*)&outLen, (unsigned char *)rawPayload,(size_t)rawPayloadLen); encodePayloadLen = strlen(encodePayload); ECPLAT_PRINTF(UNILOG_DM, ctdmAutoRegHttp_2, P_INFO, "terminaltype=%d", dmCtccParam->terminaltype); result = ctdmhttppost(encodePayload, encodePayloadLen, dmCtccParam->terminaltype); if(result == HTTP_OK){ ret = 0; }else{ ret = -1; } freeEc(encodePayload); return ret; } bool ctdmIfAutoRegister() { bool result = false; UINT8 cfun = 0xff; OsaGetImeiNumSync((char *)curImei); appGetImsiNumSync((char *)curImsi); appGetIccidNumSync((char *)curCCID); ECPLAT_PRINTF(UNILOG_DM, ctdmIfAutoRegister_1_1, P_INFO, "current iccid is %s", (uint8_t *)curCCID); ECPLAT_PRINTF(UNILOG_DM, ctdmIfAutoRegister_1_2, P_INFO, "previous iccid is %s", (uint8_t *)dmCtccParam->ccid); /* check ccid, and start auto register */ if(strcmp((char *)dmCtccParam->ccid, (char *)curCCID) != 0) { ECPLAT_PRINTF(UNILOG_DM, ctdmIfAutoRegister_2, P_INFO, "new sim iccid, need auto register"); result = true; } else { ECPLAT_PRINTF(UNILOG_DM, ctdmIfAutoRegister_3, P_INFO, "same iccid, has autoreg=%d", dmCtccParam->hasReg); if(dmCtccParam->hasReg == 0) { result = true; } } appGetCFUN(&cfun); if(cfun == 0) { result = false; } return result; } void ctdmAutoRegisterTask(void *argument) { int8_t result = 0; result = ctdmAutoRegHttp(curImei, curCCID, curImsi); if(result == 0) { memcpy(dmCtccParam->ccid, curCCID, MID_WARE_DM_SIM_CCID_LEN); dmCtccParam->hasReg = 1; mwNvmCfgSetAndSaveDmCtccParam(dmCtccParam); ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterTask_1_1, P_INFO, "autoReg sucess,record current iccid to NV"); } else { ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterTask_1_2, P_INFO, "autoReg failed, start deeptimer retry autoreg after 1 hour"); slpManDeepSlpTimerStart(DEEPSLP_TIMER_ID9, 3600*1000); } slpManPlatVoteEnableSleep(ctccDmSlpHandler,SLP_SLP2_STATE); //open the sleep2 gate, it can go to sleep2 and hib state slpManGivebackPlatVoteHandle(ctccDmSlpHandler); ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterTask_2, P_INFO, "give back vote handle, ctdmAutoRegisterTask exit"); osThreadExit(); } static void ctdmConnectTask(void *arg) { bool needAutoReg = false; ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_0_0, P_INFO, "running=%d", running); while (running) { char logbuf[64] = {0}; snprintf(logbuf,64,"%s",CTDM_MACHINESTATE(stateMachine)); ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_0, P_INFO, "handle stateMachine:%s", (uint8_t *)logbuf); switch(stateMachine) { case CTDM_INIT_STATE: case CTDM_WAIT_IPREADY: osDelay(500/portTICK_PERIOD_MS); break; case CTDM_SIM_READY: needAutoReg = ctdmIfAutoRegister(); if(needAutoReg) { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_0_1, P_INFO, "need autoreg disable sleep"); slpManPlatVoteDisableSleep(ctccDmSlpHandler,SLP_SLP2_STATE); stateMachine = CTDM_WAIT_IPREADY; } else { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_0_2, P_INFO, "no need autoreg exit connectTask"); running = false; } break; case CTDM_IPREADY_STATE://poweron to register { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_1, P_INFO, "start ctccAutoReg task and exit connectTask"); osThreadAttr_t task_attr; memset(&task_attr, 0, sizeof(task_attr)); task_attr.name = "ctccAutoReg"; task_attr.stack_size = CTCC_AUTO_REG_TASK_STACK_SIZE; #if defined FEATURE_LITEOS_ENABLE task_attr.priority = osPriorityBelowNormal2; #elif defined FEATURE_FREERTOS_ENABLE task_attr.priority = osPriorityBelowNormal5; #endif #ifdef TYPE_EC718M task_attr.reserved = osThreadDynamicStackAlloc; #endif osThreadNew(ctdmAutoRegisterTask, NULL,&task_attr); running = false; break; } case CTDM_NOT_RIGHT_SIM: { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_2, P_INFO, "not cmcc card give back vote handle exit connecttask"); slpManGivebackPlatVoteHandle(ctccDmSlpHandler); running = false; break; } case CTDM_IDLE_STATE://nothing to do can handle key event { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_3, P_INFO, "nothing to do exit connecttask"); running = false; break; } case CTDM_TIME_TO_RETRY://time up retry autoregister { // wait 60s for network if(checkNetworkReadyTimeOut(120) != true) { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_4_1, P_INFO, "network not ready give up autoreg this time"); slpManPlatVoteEnableSleep(ctccDmSlpHandler, SLP_SLP2_STATE); stateMachine = CTDM_IDLE_STATE; } else { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_4, P_INFO, "network ok go IPREADY_STATE"); stateMachine = CTDM_IPREADY_STATE; needAutoReg = true; } break; } default: { ECPLAT_PRINTF(UNILOG_DM, ctdmConnectTask_5, P_INFO, "unknown state exit connecttask"); running = false; break; } } } deregisterPSEventCallback((psEventCallback_t)ctdmPSUrcCallback); osThreadExit(); } static void ctdmStartConncetTask() { osThreadAttr_t task_attr; memset(&task_attr,0,sizeof(task_attr)); task_attr.name = "ctdmConn"; task_attr.stack_size = CTDMCONN_TASK_STACK_SIZE; #if defined FEATURE_LITEOS_ENABLE task_attr.priority = osPriorityNormal1; #elif defined FEATURE_FREERTOS_ENABLE task_attr.priority = osPriorityNormal; #endif #ifdef TYPE_EC718M task_attr.reserved = osThreadDynamicStackAlloc; #endif running = true; osThreadNew(ctdmConnectTask, NULL, &task_attr); } void ctdmAutoregRetryTimeExpCallback(void) { slpManPlatVoteDisableSleep(ctccDmSlpHandler,SLP_SLP2_STATE); stateMachine = CTDM_TIME_TO_RETRY; } void ctdmDeepSleepTimerCbRegister(void) { slpManDeepSlpTimerRegisterExpCb(DEEPSLP_TIMER_ID9, (slpManUsrDeepSlpTimerCb_Func)ctdmAutoregRetryTimeExpCallback); } void ctccAutoRegisterInit(MWNvmCfgDmCtccParam* ctccParam, slpManSlpState_t slpState) { ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterInit, P_INFO, "start connect task"); dmCtccParam = ctccParam; slpManApplyPlatVoteHandle("CTCC_DM",&ctccDmSlpHandler); registerPSEventCallback(PS_GROUP_ALL_MASK, (psEventCallback_t)ctdmPSUrcCallback); ctdmStartConncetTask(); if(slpState == SLP_HIB_STATE || slpState == SLP_SLP2_STATE)//wakeup from deep sleep { ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterInit_0_1, P_INFO, "wakeup from deep sleep"); } else { ECPLAT_PRINTF(UNILOG_DM, ctccAutoRegisterInit_0_2, P_INFO, "system reset"); } }