FreeCalypso > hg > tcs211-l1-reconst
diff g23m/condat/ms/src/aci/cmh_mmf.c @ 0:509db1a7b7b8
initial import: leo2moko-r1
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Mon, 01 Jun 2015 03:24:05 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/g23m/condat/ms/src/aci/cmh_mmf.c Mon Jun 01 03:24:05 2015 +0000 @@ -0,0 +1,2589 @@ +/* ++----------------------------------------------------------------------------- +| 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 ========================================================*/ \ No newline at end of file