FreeCalypso > hg > fc-magnetite
view src/aci2/aci/cmh_mmf.c @ 640:16eb1b9640dc
target gtm900 renamed to gtm900mgc2
This change reflects the fact that the build target in question supports
MGC2GSMT hardware only, and will NOT work on other hw that confusing bears
the same end user name of GTM900, neither the LoCosto-based GTM900-C
nor the Calypso-based MG01GSMT that has a different and incompatible RFFE.
If we ever get our hands on a piece of MG01GSMT hw and add support for it,
that other target will be named gtm900mg01.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 31 Jan 2020 00:46:07 +0000 |
parents | 93999a60b835 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS (6147) | Modul : CMH_MMF +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module defines the functions used by the command | handler for mobility management. +----------------------------------------------------------------------------- */ #ifndef CMH_MMF_C #define CMH_MMF_C #endif #include "aci_all.h" /*==== INCLUDES ===================================================*/ #include "aci_cmh.h" #include "ati_cmd.h" #include "aci_cmd.h" #include "aci_mem.h" #include "pcm.h" #ifdef FAX_AND_DATA #include "aci_fd.h" #endif /* of #ifdef FAX_AND_DATA */ #include "aci.h" #include "psa.h" #include "psa_cc.h" #include "psa_mm.h" #include "psa_sim.h" #include "psa_sat.h" #include "psa_util.h" #include "cmh.h" #ifdef DTI #include "dti.h" /* functionality of the dti library */ #include "dti_conn_mng.h" /* #include "dti_cntrl_mng.h" */ #endif #ifdef GPRS #include "gaci.h" #include "gaci_cmh.h" #include "psa_gmm.h" #include "cmh_gmm.h" #endif /* GPRS */ #include "cmh_mm.h" #include "cmh_sim.h" #ifndef _SIMULATION_ #include "ffs/ffs.h" #include "ffs_coat.h" #endif /* !_SIMULATION_ */ #ifdef FF_CPHS #include "cphs.h" #endif /* FF_CPHS */ /*==== CONSTANTS ==================================================*/ /* Countries, for which the ECC should be ignored, i.e. done as normal call */ /* contains MCC and ECC, last element should be always NULL*/ GLOBAL const T_ECCIgnoreRec ECCIgnoreTable[] = { { 0x260, ALL_MNC, "999" }, /* Poland */ { 0x454, 0x04F, "112" }, /* "HK ORANGE" */ { 0x454, 0x10F, "112" }, /* "HK New World" */ { -1, -1, NULL } /* End mark */ }; #define ONS_EXT_DCS 0x80 /*==== TYPES ======================================================*/ /*==== EXPORT =====================================================*/ /*==== VARIABLES ==================================================*/ LOCAL T_OPER_ENTRY ONSDesc; GLOBAL T_ONS_READ_STATE ONSReadStatus = ONS_READ_NOT_DONE; /* This is required because FFS is not available in the Simulation Mode */ #ifdef _SIMULATION_ T_FFSPLMNIMSI RAMPlmnIMSI = {0}; #endif #if defined GPRS AND defined (DTI) EXTERN T_GMM_SHRD_PRM gmmShrdPrm; #endif /*==== FUNCTIONS ==================================================*/ /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_wild_compare | +-------------------------------------------------------------------+ PURPOSE : */ LOCAL BOOL cmhMM_wild_compare( int sim, int bcch ) { if ((bcch & 0x00F) != (sim & 0x00F) AND (sim & 0x00F) != 0x00D) return FALSE; if ((bcch & 0x0F0) != (sim & 0x0F0) AND (sim & 0x0F0) != 0x0D0) return FALSE; if ((bcch & 0xF00) != (sim & 0xF00) AND (sim & 0xF00) != 0xD00) return FALSE; return TRUE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhSIM_plmn_equal_sim_wc| +-------------------------------------------------------------------+ PURPOSE : */ LOCAL BOOL cmhSIM_plmn_equal_sim_wc (int bcch_mcc, int bcch_mnc, int sim_mcc, int sim_mnc) { /*TRACE_FUNCTION ("cmhSIM_plmn_equal_sim()");*/ /* Check MCC */ if (!cmhMM_wild_compare(sim_mcc, bcch_mcc)) return FALSE; /* Check first 2 MNC digits */ if (!cmhMM_wild_compare(sim_mnc & 0xff0, bcch_mnc & 0xff0)) return FALSE; /* Check for full match */ if (cmhMM_wild_compare(sim_mnc & 0xf, bcch_mnc & 0xf)) return TRUE; /* The 3rd digit of the MNC differs */ if ((bcch_mcc >= 0x310) AND (bcch_mcc <= 0x316)) { /* * The MCC is in the range 310..316, this means North America. * The zero suffix rule applies. */ return ((((sim_mnc & 0xf) EQ 0xf) AND ((bcch_mnc & 0xf) EQ 0x0)) OR (((sim_mnc & 0xf) EQ 0x0) AND ((bcch_mnc & 0xf) EQ 0xf))); } return ((bcch_mnc & 0xf) EQ 0xf); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_FindPLMN | +-------------------------------------------------------------------+ PURPOSE : scan the list of operators to find the PLMN representation. NOTE: This function looks as if it could be simplified and shortened. However, it is expected that it works. */ GLOBAL BOOL cmhMM_FindPLMN( T_OPER_ENTRY * plmnDesc, SHORT mcc, SHORT mnc, U16 lac, BOOL nw_search ) { int i; /* holds list idx */ EF_PLMN plmn; /* holds PLMN identifier */ SHORT sim_mcc; /* Integer representation MCC */ SHORT sim_mnc; /* Integer representation MNC */ USHORT maxRec; /* holds maximum records */ USHORT recNr; /* holds record number */ UBYTE retVal; /* holds return value */ UBYTE ver; /* holds version */ /* *------------------------------------------------------------------- * search list of PNN records if SIM is EONS enabled *------------------------------------------------------------------- */ TRACE_FUNCTION ("cmhMM_FindPLMN()"); TRACE_EVENT_P3 ("mcc: %x, mnc %x, lac: %x", mcc, mnc, lac); /* Initial conditions for Data Coding Scheme and PLMN name source */ memset (plmnDesc, 0, sizeof (T_OPER_ENTRY)); /* plmnDesc.dcs = 0; */ plmnDesc->pnn = FALSE; if(psaSIM_ChkSIMSrvSup(SRV_PNN)) { if (!nw_search) /* this is not for network search list */ { if(psaSIM_ChkSIMSrvSup(SRV_OPL) || cmhSIM_plmn_is_hplmn (mcc, mnc)) { if (mmShrdPrm.PNNLst.plmn.v_plmn EQ VLD_PLMN) { plmnDesc->mcc = mcc; plmnDesc->mnc = mnc; plmnDesc->pnn = TRUE; plmnDesc->long_len = mmShrdPrm.PNNLst.long_len; plmnDesc->long_ext_dcs = mmShrdPrm.PNNLst.long_ext_dcs; plmnDesc->shrt_len = mmShrdPrm.PNNLst.shrt_len; plmnDesc->shrt_ext_dcs = mmShrdPrm.PNNLst.shrt_ext_dcs; if(mmShrdPrm.PNNLst.long_len) { memcpy (plmnDesc->longName, mmShrdPrm.PNNLst.long_name, MINIMUM(mmShrdPrm.PNNLst.long_len, MAX_LONG_OPER_LEN - 1)); } if(mmShrdPrm.PNNLst.shrt_len > 0) { memcpy (plmnDesc->shrtName, mmShrdPrm.PNNLst.shrt_name, MINIMUM(mmShrdPrm.PNNLst.shrt_len, MAX_SHRT_OPER_LEN - 1)); } return TRUE; } else { U16 current_lac = lac; if (current_lac EQ NOT_PRESENT_16BIT) current_lac = mmShrdPrm.lac; for (i=0; i<simShrdPrm.opl_list.num_rcd; i++) { int pnn_rec_number = simShrdPrm.opl_list.opl_rcd[i].pnn_rec_num; SHORT sim_mcc, sim_mnc; cmhSIM_getMncMccFrmPLMNsel (simShrdPrm.opl_list.opl_rcd[i].plmn, &sim_mcc, &sim_mnc); if (pnn_rec_number EQ 0xFF) continue; /* empty record, continue with next one */ if(cmhSIM_plmn_equal_sim_wc( mcc, mnc, sim_mcc, sim_mnc) AND ( (simShrdPrm.opl_list.opl_rcd[i].lac1 EQ 0x0000 AND simShrdPrm.opl_list.opl_rcd[i].lac2 EQ 0xFFFE) OR (simShrdPrm.opl_list.opl_rcd[i].lac1 <= current_lac AND simShrdPrm.opl_list.opl_rcd[i].lac2 >= current_lac) ) ) { if (pnn_rec_number EQ 0) break; /* 31.102: 4.2.59 EFOPL (Operator PLMN List): A value of '00' indicates that the name is to be taken from other sources, see TS 22.101 [24] */ pnn_rec_number--; /* adjust to zero based array */ if (simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].v_plmn) { plmnDesc->mcc = mcc; plmnDesc->mnc = mnc; plmnDesc->pnn = TRUE; plmnDesc->long_len = MINIMUM (simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].long_len, MAX_LONG_OPER_LEN - 1); memcpy (plmnDesc->longName, simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].long_name, plmnDesc->long_len); plmnDesc->long_ext_dcs = simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].long_ext_dcs; plmnDesc->shrt_len = MINIMUM (simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].shrt_len, MAX_SHRT_OPER_LEN - 1); memcpy (plmnDesc->shrtName, simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].shrt_name, plmnDesc->shrt_len); plmnDesc->shrt_ext_dcs = simShrdPrm.pnn_list.pnn_rcd[pnn_rec_number].shrt_ext_dcs; return TRUE; } } } } } } else /* the procedure is used for building the PLMN selection list */ { T_pnn_name *current; /* points to PNN element currently compared */ current = (T_pnn_name *)mmShrdPrm.PNNLst.next; while (current != NULL) { SHORT sim_mcc, sim_mnc; cmhMM_CnvrtPLMN2INT (current->plmn.mcc, current->plmn.mnc, &sim_mcc, &sim_mnc); if (cmhSIM_plmn_equal_sim (mcc, mnc, sim_mcc, sim_mnc) AND (current->lac EQ lac)) { if(current->plmn.v_plmn EQ VLD_PLMN) { plmnDesc->mcc = mcc; plmnDesc->mnc = mnc; plmnDesc->pnn = TRUE; plmnDesc->long_len = MINIMUM (current->long_len, MAX_LONG_OPER_LEN - 1); plmnDesc->long_ext_dcs = current->long_ext_dcs; plmnDesc->shrt_len = MINIMUM (current->shrt_len, MAX_SHRT_OPER_LEN - 1); plmnDesc->shrt_ext_dcs = current->shrt_ext_dcs; if (current->long_len) { memcpy (plmnDesc->longName, current->long_name, plmnDesc->long_len); } if (current->shrt_len) { memcpy (plmnDesc->shrtName, current->shrt_name, plmnDesc->shrt_len); } return TRUE; } } else current = (T_pnn_name *)current->next; } } } if((ONSReadStatus EQ ONS_READ_OVER) AND cmhSIM_plmn_is_hplmn (mcc, mnc)) { *plmnDesc = ONSDesc; /* Struct assignment */ plmnDesc->mcc = mcc; plmnDesc->mnc = mnc; return TRUE; } /* *------------------------------------------------------------------- * search list of operators ( PCM table ) *------------------------------------------------------------------- */ recNr = 1; do { retVal= pcm_ReadRecord( (UBYTE *) EF_PLMN_ID, recNr, SIZE_EF_PLMN, (UBYTE *)&plmn, &ver, &maxRec ); if( retVal EQ PCM_INVALID_SIZE OR retVal EQ PCM_INVALID_RECORD ) break; sim_mcc = (plmn.mcc[0] << 8) + plmn.mcc[1]; sim_mnc = (plmn.mnc[0] << 8) + plmn.mnc[1]; if (cmhSIM_plmn_equal_sim (mcc, mnc, sim_mcc, sim_mnc)) { cmhMM_CnvrtTrmPCMOpNam( plmnDesc, &plmn ); plmnDesc->mcc = sim_mcc; plmnDesc->mnc = sim_mnc; return TRUE; } recNr++; } while( recNr <= maxRec ); /* *------------------------------------------------------------------- * search list of operators ( fixed table ) *------------------------------------------------------------------- */ for( i = 0; operListFixed[i].mcc NEQ -1 AND operListFixed[i].mnc NEQ -1; i++ ) { sim_mcc = operListFixed[i].mcc; sim_mnc = operListFixed[i].mnc; if (cmhSIM_plmn_equal_sim (mcc, mnc, sim_mcc, sim_mnc)) { strncpy (plmnDesc->longName, operListFixed[i].longName, MAX_LONG_OPER_LEN - 1); strncpy (plmnDesc->shrtName, operListFixed[i].shrtName, MAX_SHRT_OPER_LEN - 1); plmnDesc->mcc = operListFixed[i].mcc; plmnDesc->mnc = operListFixed[i].mnc; return TRUE; } } /* *------------------------------------------------------------------- * only mnc and mcc description available *------------------------------------------------------------------- */ plmnDesc->mcc = mcc; plmnDesc->mnc = mnc; /* * The competitor has here a more sophisticated algorithm: * If they know the country code, they don't display the * MCC in numerical representation, but an abbreviation * for the country. We are satisfied displaying the MCC * and saving the ROM space for the country table. */ if ( ( mnc & 0xF) NEQ 0xf ) /* is 3rd digit mnc? */ { sprintf (plmnDesc->longName, "%03x %03x", mcc, mnc); } else { /* only 2-digit-MNC */ mnc = (mnc & 0x0FF0) >> 4; sprintf (plmnDesc->longName, "%03x %02x", mcc, mnc); } strcpy (plmnDesc->shrtName, plmnDesc->longName); return TRUE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_isBandAllowed | +-------------------------------------------------------------------+ PURPOSE : Check if band combination is part of bands allowed by manufacturer. To be used by AT%BAND. Per convention: if AllowedBands = 0, all bands are allowed. band 0 is never allowed (that is not a combination !!) */ GLOBAL BOOL cmhMM_isBandAllowed( UBYTE band, UBYTE AllowedBands ) { if( AllowedBands EQ 0x00 ) { /* no manufacturer constraint */ return(TRUE); } if( band EQ 0x00) { return(FALSE); } if( (band & AllowedBands) EQ band ) { return( TRUE ); } else return( FALSE ); } /* +---------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_writeSetBand | +---------------------------------------------------------------------+ PURPOSE : */ #define SIZE_OF_RFCAP (16*sizeof(UBYTE)) GLOBAL BOOL cmhMM_writeSetBand( UBYTE setband ) { #ifndef _SIMULATION_ T_FFS_RET ret_ffs; UBYTE RFCap[SIZE_OF_RFCAP]; /* RFCap has 16 bytes */ ret_ffs = FFS_fread("/gsm/com/rfcap", RFCap, SIZE_OF_RFCAP); if(ret_ffs < 1) /* error */ { TRACE_EVENT_P1("RFCap: cannot read FFS: error n: %d", ret_ffs); return(FALSE); } /* write user bands into FFS */ RFCap[0] = setband; ret_ffs = FFS_fwrite("/gsm/com/rfcap", RFCap, SIZE_OF_RFCAP); if( ret_ffs NEQ EFFS_OK ) { TRACE_EVENT_P1("Cannot write value on RFCap, error n: %d", ret_ffs); return(FALSE); } TRACE_EVENT("cmhMM_writeSetBand: data writing in FFS successful"); #endif /* _SIMULATION_ */ return( TRUE ); } /* +---------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_getBandSettings | +---------------------------------------------------------------------+ PURPOSE : */ GLOBAL void cmhMM_getBandSettings( UBYTE *SetBands, UBYTE *AllowedBands ) { UBYTE intern_set_bands = 0x00, /* initialized to NOT SET */ intern_allowed_bands = 0x00; /* avoid several checks against NULL */ #ifndef _SIMULATION_ UBYTE RFCap[SIZE_OF_RFCAP]; /* RFCap has 16 bytes */ T_FFS_RET ret_ffs; TRACE_FUNCTION("cmhMM_getBandSettings()"); ret_ffs = FFS_fread("/gsm/com/rfcap", RFCap, SIZE_OF_RFCAP); if(ret_ffs < 1) /* error */ { TRACE_EVENT_P1("cmhMM_getBandSettings: RFCap: cannot read FFS: error n: %d", ret_ffs); } else { TRACE_EVENT("cmhMM_getBandSettings: data reading from FFS successful"); intern_set_bands = RFCap[0]; intern_allowed_bands = RFCap[1]; } #endif /* #ifndef _SIMULATION_ */ if( SetBands NEQ NULL ) { *SetBands = intern_set_bands; TRACE_EVENT_P1("User defined Band bitfield: %d", *SetBands); } if( AllowedBands NEQ NULL ) { *AllowedBands = intern_allowed_bands; TRACE_EVENT_P1("Manufacturer defined Band bitfield: %d", *AllowedBands); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_FindNumeric | +-------------------------------------------------------------------+ PURPOSE : Convert operator representation from string into numeric. NOTE: The cmhMM_FindNumeric() function is not part of the public declared interface to ACI. However some guys from the MFW team are using this function in mfw_nma.c, declaring the function prototype in the nfw_nma.c file locally. Be careful with changes. */ GLOBAL BOOL cmhMM_FindNumeric( T_OPER_ENTRY * plmnDesc, const CHAR *numStr ) { USHORT idx; BOOL ready; TRACE_FUNCTION ("cmhMM_FindNumeric()"); plmnDesc->mcc = 0; plmnDesc->mnc = 0; ready = FALSE; /* * Convert string representation into internal represention */ for (idx = 0; idx < SIZE_MCC + SIZE_MNC; idx++) { if (idx < SIZE_MCC) { /* * Converting MCC */ if (!ready AND numStr[idx] >= '0' AND numStr[idx] <= '9') { plmnDesc->mcc = (plmnDesc->mcc << 4) + numStr[idx] - '0'; } else { ready = TRUE; } } else { /* * Converting MNC */ if (!ready AND numStr[idx] >= '0' AND numStr[idx] <= '9') { plmnDesc->mnc = (plmnDesc->mnc << 4) + numStr[idx] - '0'; } else { ready = TRUE; if ((plmnDesc->mnc & 0x00F) NEQ 0xF) plmnDesc->mnc = (plmnDesc->mnc << 4) + 0xF; } } } /* *------------------------------------------------------------------- * search list of operators *------------------------------------------------------------------- */ (void)cmhMM_FindPLMN (plmnDesc, plmnDesc->mcc, plmnDesc->mnc, NOT_PRESENT_16BIT, FALSE); /* decode 7 Bit default GSM for MFW */ if (plmnDesc->pnn) { char longName[(MAX_ALPHA_OPER_LEN*8+6)/7]; char shrtName[(MAX_ALPHA_OPER_LEN*8+6)/7]; longName[0]=shrtName[0]='\0'; if (plmnDesc->long_len) { switch (plmnDesc->long_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)plmnDesc->longName, (UBYTE) plmnDesc->long_len, plmnDesc->long_ext_dcs, (UBYTE *)longName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2"); break; default: TRACE_ERROR ("ERROR: Unknown DCS"); break; } strncpy (plmnDesc->longName, longName, MAX_LONG_OPER_LEN - 1); plmnDesc->longName[MAX_LONG_OPER_LEN - 1] = '\0'; plmnDesc->long_len = strlen(longName); } if (plmnDesc->shrt_len) { switch (plmnDesc->shrt_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)plmnDesc->shrtName, (UBYTE) plmnDesc->shrt_len, plmnDesc->shrt_ext_dcs, (UBYTE *)shrtName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2"); break; default: TRACE_ERROR ("ERROR: Unknown DCS"); break; } strncpy (plmnDesc->shrtName, shrtName, MAX_SHRT_OPER_LEN - 1); plmnDesc->shrtName[MAX_SHRT_OPER_LEN - 1] = '\0'; plmnDesc->shrt_len = strlen(shrtName); } } return TRUE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_FindName | +-------------------------------------------------------------------+ PURPOSE : scan the list of operators to find the short or long name representation. NOTE: The cmhMM_FindName() function is not part of the public declared interface to ACI. However some guys from the MFW team are using this function in mfw_nma.c, declaring the function prototype in the nfw_nma.c file locally. Be careful with changes. */ GLOBAL BOOL cmhMM_FindName( T_OPER_ENTRY * plmnDesc, const CHAR *string, T_ACI_CPOL_FRMT format ) { USHORT idx; /* holds list idx */ EF_PLMN plmn; /* holds PLMN identifier */ USHORT maxRec; /* holds maximum records */ USHORT recNr; /* holds record number */ UBYTE retVal; /* holds return value */ UBYTE ver; /* holds version */ char longName[(MAX_ALPHA_OPER_LEN*8+6)/7]; char shrtName[(MAX_ALPHA_OPER_LEN*8+6)/7]; /* *------------------------------------------------------------------- * search list of PNN records if SIM is EONS enabled *------------------------------------------------------------------- */ if(psaSIM_ChkSIMSrvSup(SRV_PNN) && psaSIM_ChkSIMSrvSup(SRV_OPL)) { T_pnn_name *current; /* points to PNN element currently compared */ current = (T_pnn_name *)mmShrdPrm.PNNLst.next; while (current != NULL) { longName[0]=shrtName[0]='\0'; if (current->long_len) { switch (current->long_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)current->long_name, current->long_len, current->long_ext_dcs, (UBYTE *)longName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2"); break; default: TRACE_ERROR ("ERROR: Unknown DSC"); break; } } if (current->shrt_len) { switch (current->shrt_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)current->shrt_name, current->shrt_len, current->shrt_ext_dcs, (UBYTE *)shrtName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2"); break; default: TRACE_ERROR ("ERROR: Unknown DSC"); break; } } if((format EQ CPOL_FRMT_Long) && (strcmp (string, (char *)longName) EQ 0) || (format EQ CPOL_FRMT_Short) && (strcmp (string,(char *)shrtName) EQ 0)) { plmnDesc->pnn = 1; /* decode Name since MFW expects 8-Bit string */ strncpy (plmnDesc->longName, longName, MAX_LONG_OPER_LEN - 1); plmnDesc->longName[MAX_LONG_OPER_LEN - 1] = '\0'; plmnDesc->long_len = strlen (plmnDesc->longName); strncpy (plmnDesc->shrtName, shrtName, MAX_SHRT_OPER_LEN - 1); plmnDesc->shrtName[MAX_SHRT_OPER_LEN -1] = '\0'; plmnDesc->shrt_len = strlen (plmnDesc->shrtName); cmhMM_CnvrtPLMN2INT( current->plmn.mcc, current->plmn.mnc, &plmnDesc->mcc, &plmnDesc->mnc ); if (current->plmn.v_plmn EQ VLD_PLMN) { return TRUE; } } else current = (T_pnn_name *)current->next; } } /* *------------------------------------------------------------------- * search list of operators ( PCM table ) *------------------------------------------------------------------- */ recNr = 1; do { retVal= pcm_ReadRecord( (UBYTE *) EF_PLMN_ID, recNr, SIZE_EF_PLMN, (UBYTE *)&plmn, &ver, &maxRec ); if( retVal EQ PCM_INVALID_SIZE OR retVal EQ PCM_INVALID_RECORD ) break; cmhMM_CnvrtTrmPCMOpNam( plmnDesc, &plmn ); if ((format EQ CPOL_FRMT_Short AND strcmp(plmnDesc->shrtName, string) EQ 0) OR (format EQ CPOL_FRMT_Long AND strcmp(plmnDesc->longName, string) EQ 0)) { plmnDesc->mcc = (plmn.mcc[0] << 8) + plmn.mcc[1]; plmnDesc->mnc = (plmn.mnc[0] << 8) + plmn.mnc[1]; return TRUE; } recNr++; } while( recNr <= maxRec ); /* *------------------------------------------------------------------- * search list of operators ( fixed table ) *------------------------------------------------------------------- */ for( idx = 0; operListFixed[idx].shrtName NEQ NULL; idx++ ) { if ((format EQ CPOL_FRMT_Short AND strcmp((char*)operListFixed[idx].shrtName, string) EQ 0) OR (format EQ CPOL_FRMT_Long AND strcmp((char*)operListFixed[idx].longName, string) EQ 0)) { memset (plmnDesc, 0, sizeof (T_OPER_ENTRY)); strncpy (plmnDesc->longName, operListFixed[idx].longName, MAX_LONG_OPER_LEN - 1); strncpy (plmnDesc->shrtName, operListFixed[idx].shrtName, MAX_SHRT_OPER_LEN - 1); plmnDesc->mcc = operListFixed[idx].mcc; plmnDesc->mnc = operListFixed[idx].mnc; return TRUE; } } return FALSE; } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_CnvrtPLMN2INT | +-------------------------------------------------------------------+ PURPOSE : convert the BCD PLMN notation for mcc and mnc into integer values. */ GLOBAL void cmhMM_CnvrtPLMN2INT( const UBYTE * BCDmcc, const UBYTE * BCDmnc, SHORT * mccBuf, SHORT * mncBuf ) { SHORT idx; /* * Convert MCC */ *mccBuf = 0; for (idx = 0; idx < SIZE_MCC; idx++) { *mccBuf = (*mccBuf << 4) + BCDmcc[idx]; } /* * Convert MNC */ *mncBuf = 0; for (idx = 0; idx < SIZE_MNC; idx++) { *mncBuf = (*mncBuf << 4) + BCDmnc[idx]; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_CnvrtINT2PLMN | +-------------------------------------------------------------------+ PURPOSE : convert the integer PLMN notation for mcc and mnc into BCD representation. */ GLOBAL void cmhMM_CnvrtINT2PLMN( SHORT INTmcc, SHORT INTmnc, UBYTE * mccBuf, UBYTE * mncBuf ) { SHORT idx; SHORT shift; /* * Convert MCC */ shift = 0; for (idx = SIZE_MCC - 1; idx >= 0; idx--) { /*lint -e{702} */ mccBuf[idx] = (INTmcc >> shift) & 0xf; shift += 4; } /* * Convert MNC */ shift = 0; for (idx = SIZE_MNC - 1; idx >= 0; idx--) { /*lint -e{702} */ mncBuf[idx] = (INTmnc >> shift) & 0xf; shift += 4; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_GetNregCREGStat | +-------------------------------------------------------------------+ PURPOSE : return CREG status for a not registered state. */ GLOBAL T_ACI_CREG_STAT cmhMM_GetNregCREGStat( void ) { switch( mmShrdPrm.regMode ) { case( MODE_AUTO ): #if defined GPRS AND defined (DTI) if ( cmhGMM_isClassCG() ) return(CREG_STAT_NoSearch); else #endif { /* Depending on the deregistration cause proper CREG state has been sent to the user */ switch(mmShrdPrm.deregCs) { case( NREG_LIMITED_SERVICE ): return(CREG_STAT_Denied); case( NREG_NO_SERVICE ): return(CREG_STAT_NoSearch); default: return(CREG_STAT_Unknown); } } case( MODE_MAN ): return(CREG_STAT_NoSearch); default: return(CREG_STAT_Unknown); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_GetNregCMEStat | +-------------------------------------------------------------------+ PURPOSE : return CME error status for a not registered state. */ GLOBAL T_ACI_CME_ERR cmhMM_GetNregCMEStat( void ) { switch( mmShrdPrm.regStat ) { case( NO_VLD_RS ): case( RS_NO_SRV ): return( CME_ERR_NoServ ); case( RS_LMTD_SRV ): return( CME_ERR_LimServ ); default: return( CME_ERR_Unknown ); } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_GetOperLstLen | +-------------------------------------------------------------------+ PURPOSE : return CME error status for a not registered state. */ GLOBAL USHORT cmhMM_GetOperLstLen( void ) { return((sizeof(operListFixed)/sizeof(T_OPER_NTRY_FIXED))-1); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MM | | ROUTINE : cmhMM_CnvrtTrmPCMOpNam | +-------------------------------------------------------------------+ PURPOSE : Convert and terminate PCM long and short operator names. */ GLOBAL void cmhMM_CnvrtTrmPCMOpNam( T_OPER_ENTRY *plmnDesc, void *pPCMBuf ) { UBYTE len; EF_PLMN * pPlmn = (EF_PLMN *)pPCMBuf; /* convert and terminate long name */ for( len = 0; len < SIZE_EF_PLMN_LONG AND pPlmn->lngNam[len] NEQ 0xFF; len++ ) ; if (len > MAX_LONG_OPER_LEN - 1) len = MAX_LONG_OPER_LEN - 1; utl_cvtGsmIra( pPlmn->lngNam, len, (UBYTE *)plmnDesc->longName, len, CSCS_DIR_GsmToIra ); plmnDesc->longName[len] = '\0'; /* convert and terminate short name */ for( len = 0; len < SIZE_EF_PLMN_SHRT AND pPlmn->shrtNam[len] NEQ 0xFF; len++ ) ; if (len > MAX_SHRT_OPER_LEN - 1) len = MAX_SHRT_OPER_LEN - 1; utl_cvtGsmIra( pPlmn->shrtNam, len, (UBYTE *)plmnDesc->shrtName, len, CSCS_DIR_GsmToIra ); plmnDesc->shrtName[len] = '\0'; } /* +----------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH | | ROUTINE : cmhMM_Ntfy_NtwRegistrationStatus | +----------------------------------------------------------------------------+ PURPOSE : report function */ #ifdef FF_CPHS LOCAL BOOL has_roaming_state_changed(T_ACI_CREG_STAT creg) { static T_ACI_CREG_STAT last_creg_notified = CREG_STAT_NotPresent; UBYTE previous_creg; TRACE_EVENT_P2("has_roaming_state_changed() creg: %d, previous creg: %d", creg, last_creg_notified); previous_creg = last_creg_notified; /* update last_creg_notified */ last_creg_notified = creg; /* status has not changed at all */ if(creg EQ previous_creg) return(FALSE); /* Mobile is entering Roaming service: since creg is different from last_creg */ if(creg EQ CREG_STAT_Roam) return(TRUE); /* Mobile is not in Roaming service: Check whether this has already been told to the user */ if(previous_creg EQ CREG_STAT_Roam) return(TRUE); return(FALSE); } LOCAL void cmhMM_cphs_roaming(T_ACI_CREG_STAT creg) { if(has_roaming_state_changed(creg)) { /* Roaming state has changed */ if(creg EQ CREG_STAT_Roam) { cphs_roaming_ind(CPHS_ROAMING_ON); } else if(creg NEQ CREG_STAT_NotPresent) { cphs_roaming_ind(CPHS_ROAMING_OFF); } } } #endif /* FF_CPHS */ GLOBAL void cmhMM_Ntfy_NtwRegistrationStatus( T_ACI_CREG_STAT creg ) { SHORT src; T_ACI_P_CREG_GPRS_IND gprs_ind; TRACE_FUNCTION ("cmhMM_Ntfy_NtwRegistrationStatus()"); #ifdef FF_CPHS cmhMM_cphs_roaming(creg); #endif /* FF_CPHS */ #if defined (GPRS) AND defined (DTI) gprs_ind = gmmShrdPrm.gprs_indicator; #else gprs_ind = P_CREG_GPRS_Not_Supported; /* ACI-SPR-17218: use ACI type */ #endif /* notify GSM change in network status */ /* +CREG */ if( creg NEQ CREG_STAT_NotPresent ) { mmShrdPrm.creg_status = creg; for( src = 0; src < CMD_SRC_MAX; src++ ) { R_AT( RAT_CREG, src )( creg, mmShrdPrm.lac, mmShrdPrm.cid ); R_AT( RAT_P_CREG, src )( creg, mmShrdPrm.lac, mmShrdPrm.cid, gprs_ind ); } } } /* +-------------------------------------------------------------------------------------+ | PROJECT : GSM-PS MODULE : CMH | | ROUTINE : cmhMM_OpCheckName | +-------------------------------------------------------------------------------------+ PURPOSE : Function for EONS support. Checks if the operator name should be read from EF_PNN upon registration or location update. */ GLOBAL void cmhMM_OpCheckName() { SHORT mncCur, mccCur; /* holds converted mnc and mcc of current PLMN */ SHORT mncOpl, mccOpl; T_opl_field *ptrOpl; UBYTE i, pnn_rec_num=0; TRACE_FUNCTION ("cmhMM_OpCheckName()"); /* check if PNN is active and allocated on SIM */ if(psaSIM_ChkSIMSrvSup(SRV_PNN)) { /* check if OPL is active and allocated */ /* if OPL not activate the first record of PNN holds the operator name of the HPLMN */ if(!psaSIM_ChkSIMSrvSup(SRV_OPL)) { /* only read PNN if not already present */ if(mmShrdPrm.PNNLst.plmn.v_plmn != VLD_PLMN) { /* if HPLMN: this sequence is copied from cmhMM_Registered() */ cmhMM_CnvrtPLMN2INT( mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &mccCur, &mncCur ); if( cmhSIM_plmn_is_hplmn (mccCur, mncCur)) { cmhMM_OpReadName(1); } } return; } /* check if the registered PLMN or LAC has changed since last registration */ if (memcmp (mmShrdPrm.usedPLMN.mcc, mmShrdPrm.PNNLst.plmn.mcc, SIZE_MCC) != 0 || memcmp (mmShrdPrm.usedPLMN.mnc, mmShrdPrm.PNNLst.plmn.mnc, SIZE_MNC) != 0 || mmShrdPrm.lac != mmShrdPrm.PNNLst.lac) { ptrOpl = cmhSIM_GetOPL(); if (ptrOpl->opl_status) { /* search the OPL list for the new PNN record number */ i = 0; pnn_rec_num = 0; /* if PNN record number in OPL is 0, no PNN name is available. */ while (i < ptrOpl->num_rcd) { cmhMM_CnvrtPLMN2INT( mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &mccCur, &mncCur ); cmhSIM_getMncMccFrmPLMNsel (ptrOpl->opl_rcd[i].plmn, &mccOpl, &mncOpl); if(cmhSIM_plmn_equal_sim_wc (mccCur, mncCur, mccOpl, mncOpl) AND (ptrOpl->opl_rcd[i].lac1 <= mmShrdPrm.lac) AND (mmShrdPrm.lac <= ptrOpl->opl_rcd[i].lac2)) { pnn_rec_num = ptrOpl->opl_rcd[i].pnn_rec_num; break; } else i++; } if (pnn_rec_num != 0) { /* only read PNN if it is different from the last one saved */ if (mmShrdPrm.PNNLst.pnn_rec_num != pnn_rec_num) { cmhMM_OpReadName(pnn_rec_num); mmShrdPrm.PNNLst.plmn.v_plmn = INVLD_PLMN; } } } else TRACE_EVENT("OPL list unavailable");; /* no OPL list available */ } } /* if CPHS ONS file is not already read then read it */ if (!pnn_rec_num AND (ONSReadStatus EQ ONS_READ_NOT_DONE)) { #ifdef FF_CPHS cmhMM_ONSReadName(); #endif mmShrdPrm.PNNLst.plmn.v_plmn = INVLD_PLMN; } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhMM_OpReadName | +-------------------------------------------------------------------+ PURPOSE : Sends a SIM read request RESULT: has an error occured ? Returns: FALSE if primitive has been sent and TRUE if not */ GLOBAL BOOL cmhMM_OpReadName(UBYTE rcd) { TRACE_FUNCTION ("cmhMM_OpReadName()"); if (cmhSIM_ReadRecordEF (CMD_SRC_NONE, AT_CMD_NONE, SIM_PNN, rcd, NOT_PRESENT_8BIT, NULL, cmhMM_OpReadNameCb) EQ AT_FAIL) { TRACE_EVENT("FATAL ERROR"); return(TRUE); } return(FALSE); } /* +---------------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhMM_OpReadNameCb | +---------------------------------------------------------------------------------+ PURPOSE : Call back for SIM retrieval of EF_PNN. */ GLOBAL void cmhMM_OpReadNameCb(SHORT table_id) { UBYTE *data; TRACE_FUNCTION ("cmhMM_OpReadNameCb()"); data = simShrdPrm.atb[table_id].exchData; /* Decode and copy PNN record data to PNN list*/ /*------------------------------------------*/ if (simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR) /* Process only if file is read */ { mmShrdPrm.PNNLst.plmn = mmShrdPrm.usedPLMN; mmShrdPrm.PNNLst.lac = mmShrdPrm.lac; mmShrdPrm.PNNLst.pnn_rec_num = simShrdPrm.atb[table_id].recNr; if (*data++ EQ PNN_LONG_NAME_IEI) { mmShrdPrm.PNNLst.long_len = (*data++)-1; /* substract dcs byte from lem */ mmShrdPrm.PNNLst.long_ext_dcs = *data++; memcpy (mmShrdPrm.PNNLst.long_name, data, MINIMUM(mmShrdPrm.PNNLst.long_len, sizeof(mmShrdPrm.PNNLst.long_name))); data += mmShrdPrm.PNNLst.long_len; /* PNN_SHORT_NAME_IEI is an optional field */ if (*data++ EQ PNN_SHORT_NAME_IEI) { mmShrdPrm.PNNLst.shrt_len = (*data++)-1; /* substract dcs byte from len */ mmShrdPrm.PNNLst.shrt_ext_dcs = *data++; memcpy (mmShrdPrm.PNNLst.shrt_name, data, MINIMUM(mmShrdPrm.PNNLst.shrt_len, sizeof(mmShrdPrm.PNNLst.shrt_name))); } else { mmShrdPrm.PNNLst.shrt_len = 0; } mmShrdPrm.PNNLst.next = NULL; } else /* PNN_LONG_NAME_IEI is a mandatory field in PNN, if not present, PNN is invalid */ { /* PNN record number 0 indicates no PNN name is available */ mmShrdPrm.PNNLst.pnn_rec_num = 0; } } cmhMM_Registered (); simShrdPrm.atb[table_id].ntryUsdFlg = FALSE; } /* +---------------------------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhMM_OpSetPNNLst | +---------------------------------------------------------------------------------------------+ PURPOSE : starts reading of EF_PNN from SIM and creates PNN list for manual PLMN selection. */ GLOBAL void cmhMM_OpSetPNNLst() { T_opl_field *ptrOpl; UBYTE i,j, pnn_rec_num; TRACE_FUNCTION ("cmhMM_OpSetPNNLst()"); ptrOpl = cmhSIM_GetOPL(); if (ptrOpl->opl_status) { mmShrdPrm.pnn_read_cnt = 0; /* search the OPL list for the PNN record number for every entry in the network search lists */ /* OPL list is searched for every entry in the network search lists */ for (j=0; j < MAX_PLMN_ID; j++) { /* check if entry in PLMNLst is valid */ if( mmShrdPrm.PLMNLst[j].v_plmn != INVLD_PLMN ) { pnn_rec_num = 0; /* if PNN record number in OPL is 0, no PNN name is available. */ i = 0; ptrOpl = cmhSIM_GetOPL(); while (i < ptrOpl->num_rcd) /* search OPL list for PLMN nr. j */ { SHORT bcch_mcc, bcch_mnc; SHORT sim_mcc, sim_mnc; cmhMM_CnvrtPLMN2INT (mmShrdPrm.PLMNLst[j].mcc, mmShrdPrm.PLMNLst[j].mnc, &bcch_mcc, &bcch_mnc); cmhSIM_getMncMccFrmPLMNsel (ptrOpl->opl_rcd[i].plmn, &sim_mcc, &sim_mnc); if (cmhSIM_plmn_equal_sim (bcch_mcc, bcch_mnc, sim_mcc, sim_mnc) AND ((ptrOpl->opl_rcd[i].lac1 EQ 0x0000 AND ptrOpl->opl_rcd[i].lac2 EQ 0xFFFE) OR (ptrOpl->opl_rcd[i].lac1 <= mmShrdPrm.LACLst[j] AND mmShrdPrm.LACLst[j] <= ptrOpl->opl_rcd[i].lac2))) { pnn_rec_num = ptrOpl->opl_rcd[i].pnn_rec_num; break; } else i++; } if (pnn_rec_num != 0) { if (cmhSIM_ReadRecordEF (CMD_SRC_NONE, AT_CMD_NONE, SIM_PNN, pnn_rec_num, /* the PNN rec. number is read */ NOT_PRESENT_8BIT, NULL, cmhMM_OpExtractNameCB) EQ AT_FAIL) { TRACE_EVENT("FATAL ERROR"); break; /* try to continue with the next one instead of return since otherwise AT+COPS=? will hang if cmhMM_NetworkLst() is not called! */ } /* in cmhMM_OpExtractNameCB the latest received PNN is placed right after the PNN-list head */ /* pnn_nr array is used for finding the associated plmn and lac in cmhMM_OpExtractNameCB. */ mmShrdPrm.pnn_nr[j] = pnn_rec_num; mmShrdPrm.pnn_read_cnt++; } else { /* name is to be taken from other sources, 3G TS 22.101 */ } } else { break; /* and Invalid PLMN indicates the end of the list. */ } } if (mmShrdPrm.pnn_read_cnt EQ 0) /* nothing processed? */ { if(( mmEntStat.curCmd EQ AT_CMD_COPS) OR ( mmEntStat.curCmd EQ AT_CMD_P_COPS) ) cmhMM_NetworkLst(); /* then print list anyway, otherwise AT+COPS=? will fail. */ } } else { if(( mmEntStat.curCmd EQ AT_CMD_COPS) OR ( mmEntStat.curCmd EQ AT_CMD_P_COPS) ) cmhMM_NetworkLst(); /* then print list anyway, otherwise AT+COPS=? will fail. */ } } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_SMSF | | STATE : code ROUTINE : cmhMM_OpExtractName | +-------------------------------------------------------------------+ PURPOSE : decodes EF_PNN record read from SIM. */ GLOBAL void cmhMM_OpExtractNameCB(SHORT table_id) { UBYTE *data; UBYTE i; T_pnn_name *newPNN; TRACE_FUNCTION ("cmhMM_OpExtractNameCB()"); data = simShrdPrm.atb[table_id].exchData; if (*data++ EQ PNN_LONG_NAME_IEI) { MALLOC(newPNN,sizeof(T_pnn_name)); newPNN->next = NULL; newPNN->pnn_rec_num = simShrdPrm.atb[table_id].recNr; /*find the associated PLMN and LAC for this PNN */ i = 0; while (i < MAX_PLMN_ID) { if (mmShrdPrm.pnn_nr[i] EQ newPNN->pnn_rec_num) { newPNN->plmn = mmShrdPrm.PLMNLst[i]; newPNN->lac = mmShrdPrm.LACLst[i]; break; } else i++; } newPNN->long_len = (*data++)-1; /* substract dcs byte */ newPNN->long_ext_dcs = *data++; memcpy (newPNN->long_name, data, MINIMUM(newPNN->long_len, sizeof(newPNN->long_name))); data += newPNN->long_len; /*----- IEI PNN short name ------*/ if (*data++ EQ PNN_SHORT_NAME_IEI) { newPNN->shrt_len = (*data++)-1; /* substract dcs byte */ newPNN->shrt_ext_dcs = *data++; memcpy (newPNN->shrt_name, data, MINIMUM(newPNN->shrt_len,sizeof(newPNN->shrt_name))); } else { newPNN->shrt_len = 0; } /* insert new element right after the static stored PNN name. */ newPNN->next = mmShrdPrm.PNNLst.next; mmShrdPrm.PNNLst.next = newPNN; } mmShrdPrm.pnn_read_cnt--; /* reading of PNN records completed, network list is prepared */ if (mmShrdPrm.pnn_read_cnt EQ 0) cmhMM_NetworkLst (); /* Deallocation of elements in linked list PNN */ // As you see, you see nothing. // ============================ // Immediate deallocation is not possible as someone could have // the idea to do a AT+COPS=? and immediately thereafter a // AT+COPS=1,0,"T-Mobile D" or AT+COPS=1,1,"TMO D" // A workaround could be to free everything not present in the actual // network list. Until now only a theoretical problem. For further study. // There is a second problem that this MM EONS extension list is not // affected by SAT changes of the respective files. Until now also // only theoretical and for further study. // And there is a third problem. This is, there exist 2 solutions // in the PS for EONS, the first one sitting in SIM related ACI around // the T_pnn data structure and the second one sitting in MM related ACI // around the T_pnn_name data structure. Two solutions for the same // problem. // => We should consider in the future to remove the implementation around // T_pnn_name and to enhance the T_pnn in SIM to end up in only one // implementation. This would improve the PS and save ROM. // Maybe the increasement of PNN_MAX_RECORDS to MAX_PLMN_ID + 1 or // something somewhat bigger will already do, otherwise an // intelligent entry replacement (aging) algorithm has to be introduced. // For further study. simShrdPrm.atb[table_id].ntryUsdFlg = FALSE; } /* +-------------------------------------------------------------------------------------+ | PROJECT : GSM-PS MODULE : CMH | | ROUTINE : cmhMM_OpUpdateName | +-------------------------------------------------------------------------------------+ PURPOSE : Function for EONS support. Updates the operator name by reading EF_PNN. RETURNS: false if PS busy with reading files (primitive has been sent) TRUE if PS can go on with the updating */ GLOBAL BOOL cmhMM_OpUpdateName() { SHORT mncCur, mccCur; /* holds converted mnc and mcc of current PLMN */ T_opl_field *ptrOpl; UBYTE i, pnn_rec_num; TRACE_FUNCTION ("cmhMM_OpUpdateName()"); /* check if OPL is active and allocated */ /* if OPL not activate the first record of PNN holds the operator name of the HPLMN */ if(!psaSIM_ChkSIMSrvSup(SRV_OPL)) { cmhMM_CnvrtPLMN2INT( mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &mccCur, &mncCur ); if( cmhSIM_plmn_is_hplmn (mccCur, mncCur)) { return(cmhMM_OpReadName(1)); } return(TRUE); /* no primitive has been sent to SIM */ } else /* OPL is active and allocated */ { ptrOpl = cmhSIM_GetOPL(); if (ptrOpl->opl_status) { /* search the OPL list for the new PNN record number */ i = 0; pnn_rec_num = 0; /* if PNN record number in OPL is 0, no PNN name is available. */ while (i < ptrOpl->num_rcd) { SHORT bcch_mcc, bcch_mnc; SHORT sim_mcc, sim_mnc; cmhMM_CnvrtPLMN2INT (mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &bcch_mcc, &bcch_mnc); cmhSIM_getMncMccFrmPLMNsel (ptrOpl->opl_rcd[i].plmn, &sim_mcc, &sim_mnc); if (cmhSIM_plmn_equal_sim (bcch_mcc, bcch_mnc, sim_mcc, sim_mnc) AND (ptrOpl->opl_rcd[i].lac1 <= mmShrdPrm.lac) AND (mmShrdPrm.lac <= ptrOpl->opl_rcd[i].lac2)) { pnn_rec_num = ptrOpl->opl_rcd[i].pnn_rec_num; break; } else i++; } if (pnn_rec_num != 0) { return(cmhMM_OpReadName(pnn_rec_num)); } } else TRACE_EVENT("OPL list unavailable");; /* no OPL list available */ } return(TRUE); /* no primitive has been sent to SIM */ } /* +-------------------------------------------------------------------------------------+ | PROJECT : GSM-PS MODULE : CMH | | ROUTINE : cmhMM_GetCmerSettings | +-------------------------------------------------------------------------------------+ */ GLOBAL void cmhMM_GetCmerSettings(T_ACI_CMD_SRC srcId, T_ACI_MM_CMER_VAL_TYPE *sCmerSettings) { sCmerSettings->sCmerModeParam = cmhPrm[srcId].mmCmdPrm.sIndicationParam.sMmCMERSettings.sCmerModeParam; sCmerSettings->sCmerIndParam = cmhPrm[srcId].mmCmdPrm.sIndicationParam.sMmCMERSettings.sCmerIndParam; sCmerSettings->sCmerBfrParam = cmhPrm[srcId].mmCmdPrm.sIndicationParam.sMmCMERSettings.sCmerBfrParam; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_ChkIgnoreECC | +--------------------------------------------------------------------+ PURPOSE : This function is used to check if ECC should be set as a normal call. (Issue 17570) RETURN: TRUE - if further ECC checking should be ignored and call must be placed as normal FALSE - if ECC checking should be continued */ GLOBAL BOOL cmhMM_ChkIgnoreECC(CHAR *dialStr) { int i=0; SHORT mnc, mcc; /* remove any CLIR suppression/invocation prior checking for ECC */ if (!strncmp( dialStr, "*31#", 4) OR !strncmp( dialStr, "#31#", 4) ) { dialStr+=4; /* skip CLIR supression/invocation digits */ if ( *dialStr EQ '\0' ) { return( FALSE ); /* end already reached? */ } } if(mmShrdPrm.usedPLMN.v_plmn EQ VLD_PLMN) { cmhMM_CnvrtPLMN2INT( mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &mcc, &mnc ); while (ECCIgnoreTable[i].mcc NEQ -1 AND ECCIgnoreTable[i].mnc NEQ -1 ) { if ( ECCIgnoreTable[i].mcc EQ mcc AND (ECCIgnoreTable[i].mnc EQ mnc OR ECCIgnoreTable[i].mnc EQ ALL_MNC) ) { if(!strcmp(ECCIgnoreTable[i].ecc, dialStr)) { TRACE_EVENT("cmhCC_ChkIgnoreECC(): no ECC but normal call detected"); return (TRUE); } } i++; } } return (FALSE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_OperatorSelect | +--------------------------------------------------------------------+ PURPOSE : This function encapsulates the common CMH functionality of sAT_PlusCOPS(), sAT_PercentCOPS(), and sAT_PercentNRG(). The body of this function is based on the former sAT_PercentNRG(). */ GLOBAL T_ACI_RETURN cmhMM_OperatorSelect(T_ACI_CMD_SRC srcId, T_ACI_NRG_RGMD regMode, T_ACI_NRG_SVMD srvMode, T_ACI_NRG_FRMT oprFrmt, CHAR *opr) { T_MM_CMD_PRM * pMMCmdPrm; /* points to MM command parameters */ T_SIM_SET_PRM * pSIMSetPrm; /* points to SIM parameter set */ T_OPER_ENTRY plmnDesc; /* points to PLMN description */ T_ACI_RETURN retVal=AT_FAIL; /* holds return value */ BOOL found; /* result of cmhMM_FindXXX() */ UBYTE rm; /* holds converted registration mode */ TRACE_FUNCTION ("cmhMM_OperatorSelect()"); /* *------------------------------------------------------------------- * check command source *------------------------------------------------------------------- */ if(!cmh_IsVldCmdSrc (srcId)) { mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } pMMCmdPrm = &cmhPrm[srcId].mmCmdPrm; pSIMSetPrm = &simShrdPrm.setPrm[srcId]; mmShrdPrm.regModeBeforeAbort = mmShrdPrm.regMode; /* *------------------------------------------------------------------- * process the regMode parameter *------------------------------------------------------------------- */ switch( regMode ) { case( NRG_RGMD_Auto ): rm = MODE_AUTO; break; case( NRG_RGMD_Manual ): case( NRG_RGMD_Both ): rm = MODE_MAN; if(!cmhSIM_isplmnmodebit_set()) { mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow ); return( AT_FAIL ); } break; case( NRG_RGMD_Dereg ): rm = MODE_AUTO; break; default: mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } /* *------------------------------------------------------------------- * process the srvMode parameter *------------------------------------------------------------------- */ switch( srvMode ) { /* *--------------------------------------------------------------- * setting of registration mode only. This is only used by %NRG. It is obsolete and * should be removed at some point in the future. *--------------------------------------------------------------- */ case( NRG_SVMD_SetRegModeOnly ): /* * Unset the Current Command to match exactly what sAT_PercentNRG() * used to do. */ mmEntStat.curCmd = AT_CMD_NONE; mmShrdPrm.regMode = rm; mmShrdPrm.regModeAutoBack = FALSE; /* * Documentation (8415.052.00.002) says: * * "<srvMode>=3 can be used to change the behaviour of registration * in case of a loss of coverage. If connection to the operator is * lost and <regMode> was set to manual, ME tries to register the previous * operator automatically.". This is not exactly what is done here. * What is done is that the registration mode is set to automatic in MM. * The main difference is that for phase 2+ the HPLMN search period * will be evaluated by RR and the HPLMN may be reselected after 30 minutes, * even without any loss of coverage. */ #ifdef GPRS if( psaG_MM_CMD_SET_REGMD ( rm ) < 0 ) /* restore former registration mode*/ #else if( psaMM_SetRegMode ( rm ) < 0 ) /* set registration mode */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_SetRegMode in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; } else retVal = AT_CMPL; break; /* *--------------------------------------------------------------- * registration to full service *--------------------------------------------------------------- */ case( NRG_SVMD_Full ): /* For the %NRG case, only if SIM data is available we can start a registration attempt * But the COPS commands dont require that. */ if(( simShrdPrm.SIMStat EQ SS_OK AND simShrdPrm.PINStat EQ PS_RDY ) OR (mmEntStat.curCmd NEQ AT_CMD_NRG)) { switch( regMode ) { case( NRG_RGMD_Auto ): /* automatic registration */ mmShrdPrm.regModeAutoBack = FALSE; mmShrdPrm.regMode = MODE_AUTO; mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS /* Taken from the former sAT_PlusCOPS() * COPS will be request an only GSM registration. * If the ME is an only GPRS mobile, then it is impossible to request only GSM. * This patch will be eliminate an error in this situation. * * brz, 02.07.01 */ if ( cmhGMM_class_eq_CG() EQ TRUE ) { mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ return AT_CMPL; } #endif #ifdef GPRS if( psaG_MM_CMD_REG ( ) < 0 ) /* register to network */ #else if( psaMM_Registrate () < 0 ) /* register to network */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_Registrate in cmhMM_OperatorSelect()" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; break; } cmhMM_Ntfy_NtwRegistrationStatus(CREG_STAT_Search); retVal = AT_EXCT; break; case( NRG_RGMD_Manual ): /* manual registration */ case( NRG_RGMD_Both ): /* manual followed by automatic reg. */ mmShrdPrm.regModeAutoBack = (regMode EQ NRG_RGMD_Both); /* * The following code is for %COPS=1 and %NRG=1. * It will get the IMSI and last registered PLMN from FFS. * If the IMSI has changed or no information is available in FFS, * it will tell MM to register to the operator stored in EF(LOCI). * If the IMSI hasn't changed, it will manually register to the Operator stored in FFS. * */ if( !opr OR !*opr) { UBYTE mcc[SIZE_MCC]; UBYTE mnc[SIZE_MNC]; UBYTE IMSI[MAX_IMSI-1]; char tempIMSI[MAX_IMSI] = {'\0'}; BOOL readFromLOCI =FALSE; mmShrdPrm.slctPLMN.v_plmn = VLD_PLMN; /* Get the IMSI and last registered PLMN from FFS. * Compare the IMSI stored in FFS to the current one. If the same, copy MCC and MNC * to pMMSetPrm -> slctPLMN. This will select this network manually. */ if (cmhMM_OperatorReadFromFFS(mcc,mnc,IMSI)) { TRACE_EVENT("Operator and IMSI succesfully read from FFS!"); if (!memcmp(IMSI,simShrdPrm.imsi.field,MAX_IMSI-1)) { memcpy(mmShrdPrm.slctPLMN.mcc, mcc,SIZE_MCC); memcpy(mmShrdPrm.slctPLMN.mnc, mnc,SIZE_MNC); } else { readFromLOCI = TRUE; } } else readFromLOCI = TRUE; /* If the SIM has changed or FFS cannot be read, read EF(LOCI) from the SIM. /* This wil now lead to a PLMN_RES with MNC,MCC=0xFFF: */ if (readFromLOCI) { psaSIM_cnvrtIMSI2ASCII(tempIMSI); psaSIM_decodeIMSI(IMSI,simShrdPrm.imsi.c_field,tempIMSI); cmhMM_CnvrtINT2PLMN( 0xFFF, 0xFFF, mmShrdPrm.slctPLMN.mcc, mmShrdPrm.slctPLMN.mnc ); } } else { switch( oprFrmt ) { case( NRG_FRMT_Long ): found = cmhMM_FindName (&plmnDesc, opr, COPS_FRMT_Long); break; case( NRG_FRMT_Short ): found = cmhMM_FindName (&plmnDesc, opr, COPS_FRMT_Short); break; case( NRG_FRMT_Numeric ): found = cmhMM_FindNumeric(&plmnDesc, opr); break; default: found = FALSE; break; } if (!found) { mmEntStat.curCmd = AT_CMD_NONE; /* Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } mmShrdPrm.slctPLMN.v_plmn = VLD_PLMN; cmhMM_CnvrtINT2PLMN( plmnDesc.mcc, /*lint -e644 plmnDesc may not have been initialized*/ plmnDesc.mnc, mmShrdPrm.slctPLMN.mcc, mmShrdPrm.slctPLMN.mnc ); } mmShrdPrm.regMode = MODE_MAN; mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS if( psaG_MM_CMD_NET_SEL ( ) < 0 ) /* register to network */ #else if( psaMM_NetSel () < 0 ) /* register to network */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_NetSel in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; break; } cmhMM_Ntfy_NtwRegistrationStatus(CREG_STAT_Search); retVal = AT_EXCT; break; } } /* * No SIM data is available, activate SIM * The following block of code was only available in the former sAT_PercentNRG() * Therefore, it will only be executed by the %NRG command. */ else { /* check SIM entity status */ if( simEntStat.curCmd NEQ AT_CMD_NONE ) return( AT_BUSY ); /* prepare PLMN desc for later use */ if( regMode EQ NRG_RGMD_Manual ) { if( ! opr ) { mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } switch( oprFrmt ) { case( NRG_FRMT_Long ): found = cmhMM_FindName (&plmnDesc, opr, COPS_FRMT_Long); break; case( NRG_FRMT_Short ): found = cmhMM_FindName (&plmnDesc, opr, COPS_FRMT_Short); break; case( NRG_FRMT_Numeric): found = cmhMM_FindNumeric (&plmnDesc, opr); break; default: found = FALSE; break; } if (!found) { mmEntStat.curCmd = AT_CMD_NONE; /* Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } mmShrdPrm.slctPLMN.v_plmn = VLD_PLMN; cmhMM_CnvrtINT2PLMN( plmnDesc.mcc, plmnDesc.mnc, mmShrdPrm.slctPLMN.mcc, mmShrdPrm.slctPLMN.mnc ); } pSIMSetPrm -> actProc = SIM_INITIALISATION; simEntStat.curCmd = AT_CMD_NRG; simEntStat.entOwn = simShrdPrm.owner = srcId; if( psaSIM_ActivateSIM() < 0 ) /* activate SIM card */ { TRACE_EVENT( "FATAL RETURN psaSIM in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; break; } retVal = AT_EXCT; } break; /* *--------------------------------------------------------------- * registration to limited service. * The COPS commands will use this for deregistration *--------------------------------------------------------------- */ case( NRG_SVMD_Limited ): mmShrdPrm.regModeAutoBack = FALSE; switch( mmShrdPrm.regStat ) { case( RS_LMTD_SRV ): mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ retVal = AT_CMPL; break; case( RS_NO_SRV ): case( NO_VLD_RS ): /* * if SIM data is available, do not destory it in ACI. * It may be needed later */ if(( simShrdPrm.SIMStat EQ SS_OK AND simShrdPrm.PINStat EQ PS_RDY ) OR (mmEntStat.curCmd NEQ AT_CMD_NRG)) { /* flag a pending request. It only applies to the %NRG case */ if (mmEntStat.curCmd EQ AT_CMD_NRG) regReqPnd = TRUE; mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS mmShrdPrm.nrgCs = GMMREG_DT_COMB; if( psaG_MM_CMD_DEREG ( mmShrdPrm.nrgCs ) < 0 ) /* deregister from network */ #else mmShrdPrm.nrgCs = CS_SIM_REM; if( psaMM_DeRegistrate () < 0 ) /* deregister from network */ #endif /* GPRS */ { TRACE_EVENT( "FATAL RETURN psaMM_DeRegistrate in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; } else { /* Next line commented out HM 28.08.00 */ /* simShrdPrm.SIMStat = NO_VLD_SS; */ /* no SIM data available */ retVal = AT_EXCT; } } /* * No SIM data is available, try a registration to limited service. * The following block of code was only available in the former sAT_PercentNRG() * Therefore, it will only be executed by the %NRG command. */ else { mmShrdPrm.regMode = MODE_AUTO; mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS if( psaG_MM_CMD_REG ( ) < 0 ) /* register to network */ #else if( psaMM_Registrate () < 0 ) /* register to network */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_Registrate in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; } else { retVal = AT_EXCT; } } break; case( RS_FULL_SRV ): mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS mmShrdPrm.nrgCs = GMMREG_DT_COMB; if( psaG_MM_CMD_DEREG ( mmShrdPrm.nrgCs ) < 0 ) /* deregister from network */ #else mmShrdPrm.nrgCs = CS_SIM_REM; if( psaMM_DeRegistrate () < 0 ) /* deregister from network */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_Deregistrate in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; break; } /* Next line commented out HM 28.08.00 */ /* simShrdPrm.SIMStat = NO_VLD_SS; */ /* no SIM data available */ retVal = AT_EXCT; break; } break; /* *--------------------------------------------------------------- * registration to no service. Only used by %NRG *--------------------------------------------------------------- */ case( NRG_SVMD_NoSrv ): mmShrdPrm.regModeAutoBack = FALSE; mmEntStat.entOwn = mmShrdPrm.owner = srcId; #ifdef GPRS mmShrdPrm.nrgCs = GMMREG_DT_COMB; if( psaG_MM_CMD_DEREG ( mmShrdPrm.nrgCs ) < 0 ) /* deregister from network */ #else mmShrdPrm.nrgCs = CS_POW_OFF; if( psaMM_DeRegistrate () < 0 ) /* deregister from network */ #endif { TRACE_EVENT( "FATAL RETURN psaMM_Deregistrate in %%NRG" ); ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal ); retVal = AT_FAIL; break; } retVal = AT_EXCT; break; default: mmEntStat.curCmd = AT_CMD_NONE; /*Unset the Current Command */ ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter ); return( AT_FAIL ); } /* *------------------------------------------------------------------- * update NRG parameters *------------------------------------------------------------------- */ if (mmEntStat.curCmd EQ AT_CMD_NRG) { pMMCmdPrm -> NRGsrvMode = srvMode; pMMCmdPrm -> NRGregMode = regMode; pMMCmdPrm -> NRGoprFrmt = oprFrmt; } /* *------------------------------------------------------------------- * log command execution *------------------------------------------------------------------- */ #if defined SMI OR defined MFW OR defined FF_MMI_RIV { T_ACI_CLOG cmdLog; /* holds logging info */ cmdLog.atCmd = mmEntStat.curCmd; cmdLog.cmdType = CLOG_TYPE_Set; cmdLog.retCode = retVal; cmdLog.cId = ACI_NumParmNotPresent; cmdLog.sId = ACI_NumParmNotPresent; if (mmEntStat.curCmd EQ AT_CMD_NRG) { cmdLog.cmdPrm.sNRG.srcId = srcId; cmdLog.cmdPrm.sNRG.regMode = regMode; cmdLog.cmdPrm.sNRG.srvMode = srvMode; cmdLog.cmdPrm.sNRG.oprFrmt = oprFrmt; cmdLog.cmdPrm.sNRG.opr = opr; } else /*+COPS and %COPS. At the moment, the same message sent by both */ { cmdLog.cmdPrm.sCOPS.srcId = srcId; cmdLog.cmdPrm.sCOPS.mode = mmShrdPrm.COPSmode; cmdLog.cmdPrm.sCOPS.format = pMMCmdPrm -> COPSfrmt; cmdLog.cmdPrm.sCOPS.oper = opr; } rAT_PercentCLOG( &cmdLog ); } #endif return( retVal ); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_OperatorQuery | +--------------------------------------------------------------------+ PURPOSE : This function encapsulates the common CMH functionality of qAT_PlusCOPS(), qAT_PercentCOPS(), and qAT_PercentNRG(). It basically gets the Network Operator name based on the format parameter. */ GLOBAL void cmhMM_OperatorQuery( T_ACI_CMD_SRC srcId, T_ACI_COPS_FRMT format, CHAR *oper) { SHORT mcc, mnc; /* holds coverted values for mcc and mnc */ T_OPER_ENTRY plmnDesc; /* entry of operator list */ BOOL found; TRACE_FUNCTION ("cmhMM_OperatorQuery()"); if( mmShrdPrm.regStat EQ RS_FULL_SRV AND mmShrdPrm.usedPLMN.v_plmn EQ VLD_PLMN) { cmhMM_CnvrtPLMN2INT( mmShrdPrm.usedPLMN.mcc, mmShrdPrm.usedPLMN.mnc, &mcc, &mnc ); found = cmhMM_FindPLMN (&plmnDesc, mcc, mnc, mmShrdPrm.lac, FALSE); if (!found) { TRACE_EVENT("!cmhMM_FindPLMN()"); if( format EQ COPS_FRMT_Numeric ) { if ((mnc & 0x00F) EQ 0xF) /*lint -e{702} */ sprintf (oper, "%03X%02X", mcc, mnc >> 4); else sprintf (oper, "%03X%03X", mcc, mnc); } } else { char longName[(MAX_ALPHA_OPER_LEN*8+6)/7]; char shrtName[(MAX_ALPHA_OPER_LEN*8+6)/7]; longName[0] = shrtName[0] = '\0'; switch( format ) { case( COPS_FRMT_Long ): TRACE_EVENT("COPS_FRMT_Long"); if (plmnDesc.pnn) { if (plmnDesc.long_len) { switch (plmnDesc.long_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)plmnDesc.longName, plmnDesc.long_len, plmnDesc.long_ext_dcs, (UBYTE *)longName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2 DCS"); break; default: TRACE_ERROR ("ERROR: Unknown DCS"); break; } } strncpy( oper, longName, MAX_ALPHA_OPER_LEN-1 ); } else { strncpy( oper, plmnDesc.longName, MAX_ALPHA_OPER_LEN-1 ); } oper[MAX_ALPHA_OPER_LEN-1] = '\0'; break; case( COPS_FRMT_Short ): if (plmnDesc.pnn) { if (plmnDesc.shrt_len) { switch (plmnDesc.shrt_ext_dcs>>4 & 0x07) { case 0x00: utl_cvtPnn7To8((UBYTE *)plmnDesc.shrtName, plmnDesc.shrt_len, plmnDesc.shrt_ext_dcs, (UBYTE *)shrtName); break; case 0x01: TRACE_ERROR ("ERROR: Unhandled UCS2"); break; default: TRACE_ERROR ("ERROR: Unknown DCS"); break; } } strncpy( oper, shrtName, MAX_ALPHA_OPER_LEN-1 ); } else { strncpy( oper, plmnDesc.shrtName, MAX_ALPHA_OPER_LEN-1 ); } oper[MAX_ALPHA_OPER_LEN-1] = '\0'; break; case( COPS_FRMT_Numeric ): if ((mnc & 0x00F) EQ 0xF) /*lint -e{702} */ sprintf (oper, "%03X%02X", mcc, mnc >> 4); else sprintf (oper, "%03X%03X", mcc, mnc); break; } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_OperatorStoreInFFS | +--------------------------------------------------------------------+ PURPOSE : This function stores the Operator given by MCC and MNC, and the IMSI number in the FFS file given by MM_FFS_OPER_FILE. If the directory in which the file is stored does not exist, it will create it. */ GLOBAL BOOL cmhMM_OperatorStoreInFFS(UBYTE* mcc, UBYTE* mnc, UBYTE* IMSI) { #ifndef _SIMULATION_ T_FFS_RET result; #endif T_FFSPLMNIMSI currentPlmnIMSI; TRACE_FUNCTION("cmhMM_OperatorStoreInFFS"); memcpy( currentPlmnIMSI.IMSI, IMSI, MAX_IMSI-1); memcpy(currentPlmnIMSI.mcc,mcc,SIZE_MCC); memcpy(currentPlmnIMSI.mnc,mnc,SIZE_MNC); #ifndef _SIMULATION_ switch(FFS_mkdir(MM_FFS_OPER_DIR)) {/* Check / Create ffs directory */ case EFFS_OK: TRACE_EVENT("cmhMM_OperatorStoreInFFS: Dir Created "); break; case EFFS_EXISTS: TRACE_EVENT("cmhMM_OperatorStoreInFFS:Dir Exists "); break; default: TRACE_EVENT("cmhMM_OperatorStoreInFFS:Dir Not Created"); return ( FALSE ); } result = FFS_fwrite(MM_FFS_OPER_FILE, ¤tPlmnIMSI, sizeof(T_FFSPLMNIMSI)); TRACE_EVENT_P1("cmhMM_OperatorStoreInFFS:FFS dir ok,FFS_fwrite res %x", result); if (result < EFFS_OK) return FALSE; #else /*Simulation is defined*/ memcpy(&RAMPlmnIMSI,¤tPlmnIMSI,sizeof(T_FFSPLMNIMSI)); #endif return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_OperatorReadFromFFS | +--------------------------------------------------------------------+ PURPOSE : This function reads the Operator given by MCC and MNC, and the IMSI number from the FFS file given by MM_FFS_OPER_FILE. */ GLOBAL BOOL cmhMM_OperatorReadFromFFS(UBYTE* mcc, UBYTE* mnc, UBYTE* IMSI) { #ifndef _SIMULATION_ T_FFS_RET result; #endif T_FFSPLMNIMSI currentPlmnIMSI; TRACE_FUNCTION("cmhMM_OperatorReadFromFFS()"); #ifndef _SIMULATION_ result = FFS_fread(MM_FFS_OPER_FILE, ¤tPlmnIMSI, sizeof(T_FFSPLMNIMSI)); TRACE_EVENT_P1("FFS result = %d",result); if (result < EFFS_OK) return FALSE; #else memcpy(¤tPlmnIMSI,&RAMPlmnIMSI,sizeof(T_FFSPLMNIMSI)); #endif memcpy( IMSI,currentPlmnIMSI.IMSI, MAX_IMSI-1); memcpy(mcc,currentPlmnIMSI.mcc,SIZE_MCC); memcpy(mnc,currentPlmnIMSI.mnc,SIZE_MNC); return TRUE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_GetActingHPLMN | +--------------------------------------------------------------------+ PURPOSE : fills the Acting HPLMN if present. */ GLOBAL BOOL cmhMM_GetActingHPLMN(SHORT * mccBuf, SHORT * mncBuf) { TRACE_FUNCTION("cmhMM_GetActingHPLMN"); if(mmShrdPrm.ActingHPLMN.v_plmn EQ VLD_PLMN) { cmhMM_CnvrtPLMN2INT( mmShrdPrm.ActingHPLMN.mcc, mmShrdPrm.ActingHPLMN.mnc, mccBuf, mncBuf ); TRACE_EVENT("Acting HPLMN Present"); return(TRUE); } TRACE_EVENT("Acting HPLMN not Present"); return (FALSE); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_ONSReadName | +-------------------------------------------------------------------+ PURPOSE : Sends a SIM read request RESULT: has an error occured ? Returns: FALSE if primitive has been sent and TRUE if not */ GLOBAL BOOL cmhMM_ONSReadName() { TRACE_FUNCTION ("cmhMM_ONSReadName()"); if (cmhSIM_ReadTranspEF (CMD_SRC_NONE, AT_CMD_NONE, SIM_CPHS_ONSTR, 0, NOT_PRESENT_8BIT, NULL, cmhMM_ONSReadNameCb) EQ AT_FAIL) { TRACE_EVENT("FATAL ERROR"); return(TRUE); } ONSReadStatus = ONS_READING; return(FALSE); } /* +-------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_ONSReadNameCb | +-------------------------------------------------------------------+ PURPOSE : Call back for SIM retrieval of EF_ONS. */ GLOBAL void cmhMM_ONSReadNameCb(SHORT table_id) { int i =0; TRACE_FUNCTION ("cmhMM_ONSReadNameCb()"); if(!(simShrdPrm.atb[table_id].exchData NEQ NULL AND simShrdPrm.atb[table_id].exchData[0] NEQ 0xFF AND simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)) { ONSReadStatus = ONS_READ_FAIL; } else { ONSReadStatus = ONS_READ_OVER; memset (&ONSDesc, 0, sizeof (T_OPER_ENTRY)); ONSDesc.long_len = 0; while (simShrdPrm.atb[table_id].exchData[i] NEQ 0xFF AND ONSDesc.long_len < MAX_LONG_OPER_LEN - 1) { ONSDesc.long_len++; i++; } if (ONSDesc.long_len <= MAX_SHRT_OPER_LEN - 1) { ONSDesc.shrt_len = ONSDesc.long_len; } else { ONSDesc.shrt_len = MAX_SHRT_OPER_LEN - 1; } /* Issue OMAPS00058768 : EFons may have fewer bytes than MAX_LONG_OPER_LEN and if all of them are used bytes then we will not come across 0xFF (unused bytes), which causes ONSDesc.long_len = MAX_LONG_OPER_LEN - 1. So this leads to the function memcpy() to copy garbage characters in front of operator name. */ ONSDesc.long_len = MINIMUM(simShrdPrm.atb[table_id].dataLen, ONSDesc.long_len); ONSDesc.shrt_len = MINIMUM(simShrdPrm.atb[table_id].dataLen, ONSDesc.shrt_len); memcpy (ONSDesc.longName, simShrdPrm.atb[table_id].exchData, ONSDesc.long_len); memcpy (ONSDesc.shrtName, simShrdPrm.atb[table_id].exchData, ONSDesc.shrt_len); ONSDesc.long_ext_dcs = ONS_EXT_DCS; ONSDesc.shrt_ext_dcs = ONS_EXT_DCS; /* Issue OMAPS00058768 : For file update of ONS we no need to call cmhMM_Registered() */ #ifdef SIM_TOOLKIT if (simShrdPrm.fuRef < 0) #endif { cmhMM_Registered (); } #ifdef SIM_TOOLKIT if (simShrdPrm.fuRef >= 0) { psaSAT_FUConfirm (simShrdPrm.fuRef, (USHORT)((simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)? SIM_FU_SUCCESS: SIM_FU_ERROR)); } #endif } simShrdPrm.atb[table_id].ntryUsdFlg = FALSE; } /* +-------------------------------------------------------------- + | PROJECT : GSM-PS (6147) MODULE : CMH_MMF | | STATE : code ROUTINE : cmhMM_Reset_ONSDesc | +---------------------------------------------------------------+ PURPOSE :Issue OMAPS00058768: Reset ONSDesc. */ GLOBAL void cmhMM_Reset_ONSDesc() { memset(&ONSDesc,0x00,sizeof(ONSDesc)); ONSReadStatus = ONS_READ_NOT_DONE; } /*==== EOF ========================================================*/