view src/g23m-aci/aci/cmh_sims.c @ 223:740a8e8fc9d7

startup sync logic rework for the new PWON button boot scheme Previously we added logic to the MMI task to hold off PEI init until R2D is running, and then extended that condition to wait for FCHG init too. However, the dependencies of MMI upon R2D and FCHG don't start until mmiInit(), and that call is driven by Switch_ON() code, hence the wait for R2D and FCHG init can be made in that code path instead of the MMI task. Furthermore, with our new way of signaling PWON button boot to MMI, we need a new wait to ensure that the MMI task is up - previously this assurance was provided by the wait for Kp pointers to be set. Solution: revert our previous PEI init hold-off additions to MMI, add a new flag indicating MMI task init done, and put the combined wait for all needed conditions into our new PWON button boot code in power.c.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 27 Apr 2021 06:24:52 +0000
parents fa8dc04885d8
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GSM-PS (6147)
|  Modul   :  CMH_SIMS
+-----------------------------------------------------------------------------
|  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 provides the set functions related to the
|             protocol stack adapter for the subscriber identity
|             module.
+-----------------------------------------------------------------------------
*/

#ifndef CMH_SIMS_C
#define CMH_SIMS_C
#endif

#include "aci_all.h"
/*==== INCLUDES ===================================================*/
#include "aci_cmh.h"

#ifdef UART
#include "dti.h"      /* functionality of the dti library */
#include "dti.h"
#include "dti_conn_mng.h"
#endif

#include "ati_cmd.h"

#ifdef FF_ATI
#include "aci_io.h"
#endif /* of #ifdef FF_ATI */

#ifdef FAX_AND_DATA
#include "aci_fd.h"
#endif    /* of #ifdef FAX_AND_DATA */

#include "psa.h"
#include "psa_sim.h"
#include "psa_mm.h"
#include "cmh.h"
#include "cmh_sim.h"
#include "cmh_mm.h"

#ifdef GPRS
  #include "dti_cntrl_mng.h"
  #include "gaci.h"
  #include "gaci_cmh.h"
  #include "psa_gmm.h"
  #include "cmh_gmm.h"
#endif

#include "aci.h"

/* #include "m_fac.h" */
#include "aoc.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#include "phb.h"

#include "aci_ext_pers.h"
#include "aci_slock.h"

#include "cl_imei.h"


#ifdef SIM_PERS
#include "general.h" // included for compilation error UNIT8 in sec_drv.h
#include "sec_drv.h" 
#include "cmh.h"
#include "aci_cmh.h"

EXTERN T_SIM_MMI_INSERT_IND *last_sim_mmi_insert_ind;
EXTERN T_SEC_DRV_CATEGORY *personalisation_nw;
EXTERN T_SEC_DRV_CATEGORY *personalisation_ns;
EXTERN T_SEC_DRV_CATEGORY *personalisation_sp;
EXTERN T_SEC_DRV_CATEGORY *personalisation_cp;
EXTERN T_SEC_DRV_CATEGORY *personalisation_sim;
EXTERN T_SEC_DRV_CONFIGURATION *cfg_data ;
#endif

/*==== CONSTANTS ==================================================*/

/*==== EXPORT =====================================================*/

/*==== VARIABLES ==================================================*/

/*==== FUNCTIONS ==================================================*/
LOCAL T_ACI_RETURN cmhSIM_analyze_SIMLOCK_STATUS( T_SIMLOCK_STATUS status );
LOCAL T_ACI_RETURN sAT_Plus_CAMM_CACM ( T_ACI_AT_CMD  at_cmd_id,
                                        T_ACI_CMD_SRC srcId,
                                        UBYTE         value_type,
                                        void          *value,
                                        UBYTE         *pwd );
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCFUN             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CFUN AT command
            which is responsible to set the phone functionality.

            <fun>:    defines the level of functionality to switch to.
            <rst>:    reset mode
*/

GLOBAL T_ACI_RETURN sAT_PlusCFUN ( T_ACI_CMD_SRC  srcId,
                                   T_ACI_CFUN_FUN fun,
                                   T_ACI_CFUN_RST rst )
{
  T_SIM_SET_PRM * pSIMSetPrm; /* points to MM parameter set */
  T_ACI_RETURN    retCd;      /* holds return code */
  UBYTE           idx;        /* holds index value */

  /* variables for IMEI control mechanism */
#ifndef _SIMULATION_
  BYTE         retVal;                     /* holds return value */
  UBYTE        dummyIMEIBuf[CL_IMEI_SIZE]; /* dummy IMEI buffer */
#endif /* if NOT defined windows simulation */

  TRACE_FUNCTION ("sAT_PlusCFUN()");

#ifndef _SIMULATION_
/*
 *-------------------------------------------------------------------
 * check IMEI
 *-------------------------------------------------------------------
 */

 retVal = cl_get_imeisv(CL_IMEI_SIZE, dummyIMEIBuf, CL_IMEI_CONTROL_IMEI);

 if( retVal NEQ CL_IMEI_OK )
 {
   ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_IMEICheck );
   TRACE_EVENT("IMEI not valid");
   simShrdPrm.imei_blocked = TRUE;
   /*return( AT_FAIL ); We dont return here to enable the stack to go to the state of "Limited Service' to enable emergency calls. */ 
 }
#endif /* if NOT defined windows simulation */

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

  pSIMSetPrm = &simShrdPrm.setPrm[srcId];

/*
 *-------------------------------------------------------------------
 * check entity status
 *-------------------------------------------------------------------
 */
  if( simEntStat.curCmd NEQ AT_CMD_NONE )
  {
    TRACE_EVENT("Entity SIM is busy: cannot proceed command...");
    return( AT_BUSY );
  }

/*
 *-------------------------------------------------------------------
 * process the <rst> parameter
 *-------------------------------------------------------------------
 */
  switch( rst )
  {
    case( CFUN_RST_NotPresent ):  /* default value */
    case( CFUN_RST_NoReset ):

    break;

    default:                      /* unexpected parameter */
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * process the <fun> parameter
 *-------------------------------------------------------------------
 */
  if( fun EQ CFUN_FUN_NotPresent ) fun = CFUNfun;

  switch( fun )
  {
    case( CFUN_FUN_Minimum ):    /* set ME to minimum functionality */
      CFUNfun           = fun;
      simEntStat.curCmd = AT_CMD_CFUN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn = srcId;

    /* Turn off all possible ringing */
#ifdef FF_ATI
    io_setRngInd ( IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)idx )( 0 );  /* Turn of all ringing */
    }


    /* We have to wait for both entities to finish in CFUN. So both EntStat are set to AT_CMD_CFUN and
       when a certain entity finished it also emits AT_OK if the other entity has already finished */

    simEntStat.curCmd = AT_CMD_CFUN;
    simShrdPrm.owner = (T_OWN)srcId;
    simEntStat.entOwn =  srcId;

    mmEntStat.curCmd  = AT_CMD_CFUN;
    mmShrdPrm.owner = (T_OWN)srcId;
    mmEntStat.entOwn  = srcId;

    pb_exit();

/*    simShrdPrm.synCs = SYNC_DEACTIVATE;  */   /* This is moved to pb_exit */
/*    psaSIM_SyncSIM(); */

    /* Reset ONSDesc */
     cmhMM_Reset_ONSDesc();


#if defined (GPRS) AND defined (DTI)
    mmShrdPrm.nrgCs = GMMREG_DT_POWER_OFF;
    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 +COPS" );
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
      return( AT_FAIL );
    }

    percentCSTAT_indication(STATE_MSG_SMS,   ENTITY_STATUS_NotReady);

    retCd = AT_EXCT;
    break;

  case( CFUN_FUN_Full ):       /* set ME to full functionality */
    if ( (CFUNfun EQ CFUN_FUN_Minimum) OR (simShrdPrm.PINStat NEQ PS_RDY) )
    {
      CFUNfun               = fun;
      pSIMSetPrm -> actProc = SIM_INITIALISATION;

      simEntStat.curCmd = AT_CMD_CFUN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn =  srcId;

      if( psaSIM_ActivateSIM() < 0 )   /* activate SIM card */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CFUN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
#ifdef GPRS
     {
       PALLOC (gmmreg_attach_req, GMMREG_ATTACH_REQ);

       /* This is just a dummy req to trigger lower layer
          for power scanning. It will be done based on bootup_act.*/
       gmmreg_attach_req->bootup_act = QUICK_REG;

       PSEND (hCommGMM,gmmreg_attach_req);
     }
#else
     {
       PALLOC (mmr_reg_req, MMR_REG_REQ);

       /* This is just a dummy req to trigger lower layer
          for power scanning. It will be done based on bootup_act.
          Other parameters is filled for the simulation test cases to pass */
       mmr_reg_req->bootup_act = QUICK_REG;

       PSENDX (MM, mmr_reg_req);
     }
#endif
    }
#ifdef SIM_PERS
   else if (CFUNfun EQ CFUN_FUN_Full ) 
   {
   TRACE_EVENT("This is for if MMI calls sAT_PlusCFUN repetedly for verification of LOCKS");
     CFUNfun               = fun;
      pSIMSetPrm -> actProc = SIM_INITIALISATION;

      simEntStat.curCmd = AT_CMD_CFUN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn = srcId;

      if( psaSIM_ActivateSIM() < 0 )   /* activate SIM card */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CFUN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
   }
#endif
  else
    {
      TRACE_EVENT("Switch mobile back on after radio low (CFUN=4)");
      CFUNfun  = fun;
      retCd    = AT_CMPL;
    }
    break;

  case (CFUN_FUN_Disable_TX_RX_RF):
    if (CFUNfun EQ CFUN_FUN_Minimum)
    {
      /* User directly goes to flight mode from power off. Only initialise
         the SIM data */
      CFUNfun               = fun;
      pSIMSetPrm -> actProc = SIM_INITIALISATION;

      simEntStat.curCmd = AT_CMD_CFUN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn =  srcId;

      if( psaSIM_ActivateSIM() < 0 )   /* activate SIM card */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CFUN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;
    }
    CFUNfun           = fun;

    /* Turn off all possible ringing */
#ifdef FF_ATI
    io_setRngInd ( IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)idx )( 0 );  /* Turn of all ringing */
    }

    if( mmEntStat.curCmd NEQ AT_CMD_BAND )
    {
      /* If sAT_PlusCFUN has been called by sAT_PercentBAND !!! */
      mmEntStat.curCmd  = AT_CMD_CFUN;
    }
    mmShrdPrm.owner = (T_OWN)srcId;
    mmEntStat.entOwn  = srcId;

#if defined (GPRS) AND defined (DTI)
    mmShrdPrm.nrgCs = GMMREG_DT_SOFT_OFF;
    if( psaG_MM_CMD_DEREG ( mmShrdPrm.nrgCs ) < 0 )  /* deregister from network */
#else
    mmShrdPrm.nrgCs = CS_SOFT_OFF;
    if( psaMM_DeRegistrate () < 0 )  /* deregister from network */
#endif
    {
      TRACE_EVENT( "FATAL RETURN psaMM_DeRegistrate in +COPS" );
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
      return( AT_FAIL );
    }

    retCd = AT_EXCT;
    break;

  default:                     /* unexpected parameter */

    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * log command execution
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  if( mmEntStat.curCmd NEQ AT_CMD_BAND
    AND simEntStat.curCmd NEQ AT_CMD_BAND )
  {
  T_ACI_CLOG      cmdLog;     /* holds logging info */

  cmdLog.atCmd                = AT_CMD_CFUN;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = retCd;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sCFUN.srcId   = srcId;
  cmdLog.cmdPrm.sCFUN.fun     = fun;
  cmdLog.cmdPrm.sCFUN.rst     = rst;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( retCd );

}

#ifdef TI_PS_FF_AT_P_CMD_SECP
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PercentSECP             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the %SEC AT command
            which is responsible to enter a PIN.

            <pin>:    string of PIN chars.
            <newpin>: string of PIN chars required if requested PIN is
                      SIM PUK
*/

GLOBAL T_ACI_RETURN sAT_PercentSECP ( T_ACI_CMD_SRC srcId,
                                      CHAR * pin,
                                      CHAR * newpin )
{
  T_SIMLOCK_STATUS  result;  
  
  TRACE_FUNCTION ("sAT_PercentSECP()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }
  
  /* Check validity of pin str*/
  if( pin EQ NULL)
  {
     ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
     return( AT_FAIL );
  }

  /* Try to set new pin */
  result = aci_ext_personalisation_CS_change_password( pin, newpin );     

  /* Implements Measure 50 */
  return ( cmhSIM_analyze_SIMLOCK_STATUS ( result ) );
  
}
#endif /* TI_PS_FF_AT_P_CMD_SECP */

#ifdef TI_PS_FF_AT_P_CMD_SECS
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PercentSECS             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the %SECS? AT command
            which is responsible to set the status of the Security Code.

            <securityStatus>:   Status of the security code.
            <code>: Security code required to change the status.
*/


GLOBAL T_ACI_RETURN sAT_PercentSECS ( T_ACI_CMD_SRC srcId,
                                   T_ACI_SECS_STA securityState,
                                   CHAR * code )
{

  T_SIMLOCK_STATUS  result;

  TRACE_FUNCTION ("sAT_PercentSECS()");


/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check status value
 *-------------------------------------------------------------------
 */
  switch (securityState)
  {
      case( SECS_STA_Enable ):
        result = aci_ext_personalisation_CS_set_status(SIMLOCK_ENABLED, code);
        break;      
      case( SECS_STA_Disable ):
        result = aci_ext_personalisation_CS_set_status(SIMLOCK_DISABLED, code);
        break;      
      default:
      return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * analyze answer
 *-------------------------------------------------------------------
 */
  /* Implements Measure 50 */
  return ( cmhSIM_analyze_SIMLOCK_STATUS ( result ) );
}
#endif /* TI_PS_FF_AT_P_CMD_SECS */





/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCPIN             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CPIN AT command
            which is responsible to enter a PIN.

            <pin>:    string of PIN chars.
            <newpin>: string of PIN chars required if requested PIN is
                      SIM PUK
*/

GLOBAL T_ACI_RETURN sAT_PlusCPIN ( T_ACI_CMD_SRC srcId,
                                   CHAR * pin,
                                   CHAR * newpin )
{
  T_SIM_SET_PRM * pSIMSetPrm;  /* points to SIM parameter set */
  T_ACI_RETURN    retCd;              /* holds return code */
  T_SIMLOCK_STATUS retSlStatus; /* holds return code */

  TRACE_FUNCTION ("sAT_PlusCPIN()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

  pSIMSetPrm = &simShrdPrm.setPrm[srcId];

/*
 *-------------------------------------------------------------------
 * check entity status
 *-------------------------------------------------------------------
 */
  if( simEntStat.curCmd NEQ AT_CMD_NONE )

    return( AT_BUSY );

/*
 *-------------------------------------------------------------------
 * check for PIN status
 *-------------------------------------------------------------------
 */
  switch( simShrdPrm.PINStat )
  {
    case( PS_RDY ):
      /*
       *---------------------------------------------------------------
        * Not a SIM PIN State, but a ME personalisation PIN
       *---------------------------------------------------------------
        */
  #ifdef SIM_PERS
      if (AciSLockShrd.blocked)
      {
        retSlStatus = aci_slock_authenticate(AciSLockShrd.current_lock, pin);
        if ( retSlStatus NEQ SIMLOCK_DISABLED)
        {
          TRACE_EVENT( "Wrong PIN given for SIM lock." );
          if (retSlStatus EQ SIMLOCK_BLOCKED)
          {
             if(!aci_slock_set_CFG())
             {
                 ACI_ERR_DESC( ACI_ERR_CLASS_Ext,EXT_ERR_NoMEPD); 
                 return( AT_FAIL );
             }
            aci_set_cme_error(AciSLockShrd.current_lock); 
            MFREE(cfg_data); 
          }
          else
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );
          return( AT_FAIL );
        }
        else
        {
             simEntStat.curCmd     = AT_CMD_CPIN;
	      if(!aci_slock_set_CFG())
             	{
             	   ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_NoMEPD); 
                 return( AT_FAIL );
             	}
             aci_slock_init();
	      
             retSlStatus = SIMLOCK_ENABLED;
	      if(AciSLockShrd.current_lock < SIMLOCK_SIM)
             {
                AciSLockShrd.current_lock=(T_SIMLOCK_TYPE)(AciSLockShrd.current_lock +SIMLOCK_NETWORK_SUBSET);
                 AciSLockShrd.check_lock = SIMLOCK_CHECK_PERS;
	          retSlStatus = aci_slock_checkpersonalisation(AciSLockShrd.current_lock);
		}
		switch(retSlStatus)
                {
                 case  SIMLOCK_ENABLED  :
	                return( AT_CMPL);
                 case  SIMLOCK_BLOCKED :
	                return( AT_FAIL);
                 case  SIMLOCK_WAIT :
                        return (AT_EXCT);
                         
               }           
          }

	 }

     #endif  
    /*
     *---------------------------------------------------------------
     * no PIN input is required
     *---------------------------------------------------------------
     */
      retCd = AT_FAIL;
      break;

    case( NO_VLD_PS ):
    /*
     *---------------------------------------------------------------
     * PIN Status is unknown
     *---------------------------------------------------------------
     */

    /* invoke SIM activate and enter PIN if needed ???? */
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return( AT_FAIL );

    case( PS_PIN1 ):
    /*
     *---------------------------------------------------------------
     * PIN 1 input is required
     *---------------------------------------------------------------
     */
      if( pin EQ NULL                 OR
          strlen( pin ) < MIN_PIN_LEN OR
          strlen( pin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin, pSIMSetPrm -> curPIN, PIN_LEN );
      pSIMSetPrm -> PINType = PHASE_2_PIN_1;
      simEntStat.curCmd     = AT_CMD_CPIN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_VerifyPIN() < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CPIN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

    case( PS_PIN2 ):
    /*
     *---------------------------------------------------------------
     * PIN 2 input is required
     *---------------------------------------------------------------
     */
      if( pin EQ NULL                 OR
          strlen( pin ) < MIN_PIN_LEN OR
          strlen( pin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin, pSIMSetPrm -> curPIN, PIN_LEN );
      pSIMSetPrm -> PINType = PHASE_2_PIN_2;
      simEntStat.curCmd     = AT_CMD_CPIN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_VerifyPIN() < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CPIN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

    case( PS_PUK1 ):
    /*
     *---------------------------------------------------------------
     * PUK 1 input is required
     *---------------------------------------------------------------
     */
      if( newpin EQ NULL                 OR
          strlen( newpin ) EQ 0)
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimPukReq ); /* inform about needed PUK */
        return( AT_FAIL );
      }
      if( pin EQ NULL                    OR
          newpin EQ NULL                 OR
          strlen( pin ) NEQ PUK_LEN      OR
          strlen( newpin ) < MIN_PIN_LEN OR
          strlen( newpin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin,    pSIMSetPrm -> unblkKey, PUK_LEN );
      cmhSIM_FillInPIN ( newpin, pSIMSetPrm -> curPIN,   PIN_LEN );
      pSIMSetPrm -> PINType = PHASE_2_PUK_1;
      simEntStat.curCmd     = AT_CMD_CPIN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_UnblockCard( ) < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CPIN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

    case( PS_PUK2 ):
    /*
     *---------------------------------------------------------------
     * PUK 2 input is required
     *---------------------------------------------------------------
     */
      if( newpin EQ NULL                 OR
          strlen( newpin ) EQ 0)
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimPuk2Req ); /* inform about needed PUK2 */
        return( AT_FAIL );
      }
      if( pin EQ NULL                    OR
          newpin EQ NULL                 OR
          strlen( pin ) NEQ PUK_LEN      OR
          strlen( newpin ) < MIN_PIN_LEN OR
          strlen( newpin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin,    pSIMSetPrm -> unblkKey, PUK_LEN );
      cmhSIM_FillInPIN ( newpin, pSIMSetPrm -> curPIN,   PIN_LEN );
      pSIMSetPrm -> PINType = PHASE_2_PUK_2;
      simEntStat.curCmd     = AT_CMD_CPIN;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_UnblockCard( ) < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in +CPIN" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

  default:
      /*
       *---------------------------------------------------------------
       * unexpected PIN state
       *---------------------------------------------------------------
       */
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_DataCorrupt );
      return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * log command execution
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  {
  T_ACI_CLOG      cmdLog;      /* holds logging info */

  cmdLog.atCmd                = AT_CMD_CPIN;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = retCd;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sCPIN.srcId   = srcId;
  cmdLog.cmdPrm.sCPIN.pin     = pin;
  cmdLog.cmdPrm.sCPIN.newpin  = newpin;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( retCd );
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCAMM             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CAMM AT command
            which is responsible to set the ACMMax.
*/

GLOBAL T_ACI_RETURN sAT_PlusCAMM ( T_ACI_CMD_SRC    srcId,
                                   LONG             acmmax,
                                   CHAR *           pwd)
{
  /* Implements Measure 40 */
  return ( sAT_Plus_CAMM_CACM( AT_CMD_CAMM, srcId, AOC_ACMMAX,
                               (void *) acmmax, (UBYTE *) pwd ));
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCPUC             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CPUC AT command
            which is responsible to set the PUCT values.
*/

GLOBAL T_ACI_RETURN sAT_PlusCPUC ( T_ACI_CMD_SRC    srcId,
                                   CHAR *           currency,
                                   CHAR *           ppu,
                                   CHAR *           pwd)
{
  T_puct          puct;
  T_ACI_RETURN    ret = AT_FAIL;

  TRACE_FUNCTION ("sAT_PlusCPUC()");
/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * send parameters to advice of charge module.
 *-------------------------------------------------------------------
 */
  strcpy ((char *) puct.currency, currency);
  strcpy ((char *) puct.value, ppu);
  simEntStat.curCmd     = AT_CMD_CPUC;
  simShrdPrm.owner = (T_OWN)srcId;
  simEntStat.entOwn     = srcId;
  ret = aoc_set_values (srcId,
                        AOC_PUCT,
                        (void *)&puct,
                        (UBYTE *) pwd);

/*
 *-------------------------------------------------------------------
 * Check return value of aoc_set_values() equal to AT_FAIL,
 * resets simEntStat.curcmd and simEntStat.entown.
 *-------------------------------------------------------------------
 */

  if( ret EQ AT_FAIL )
  {
    simEntStat.curCmd    = AT_CMD_NONE;
    simShrdPrm.owner     = (T_OWN)CMD_SRC_NONE;
    simEntStat.entOwn    = CMD_SRC_NONE;
  }

  return( ret );
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCACM             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CACM AT command
            which is responsible to reset the ACM value.
*/

GLOBAL T_ACI_RETURN sAT_PlusCACM ( T_ACI_CMD_SRC    srcId,
                                   CHAR *           pwd)
{
  /* Implements Measure 40 */
  return ( sAT_Plus_CAMM_CACM( AT_CMD_CACM, srcId, AOC_ACM,
                               (void *) NULL, (UBYTE *) pwd ));
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCPOL             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CPOL AT command
            which is responsible to access the preferred PLMN list.

            <index>:  PLMN list index
            <format>: PLMN format
            <oper>:   PLMN name
            <index2>: second PLMN list index for exchange operation
            <mode>:   supplemental mode information
*/

GLOBAL T_ACI_RETURN sAT_PlusCPOL  ( T_ACI_CMD_SRC srcId,
                                    SHORT index,
                                    T_ACI_CPOL_FRMT format,
                                    CHAR * oper,
                                    SHORT index2,
                                    T_ACI_CPOL_MOD mode )
{
  T_SIM_CMD_PRM * pSIMCmdPrm;       /* points to SIM command parameters */
  UBYTE plmn[ACI_LEN_PLMN_SEL_NTRY];/* holds coded plmn id */

  TRACE_FUNCTION ("sAT_PlusCPOL()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }
  pSIMCmdPrm = &cmhPrm[srcId].simCmdPrm;

/*
 *-------------------------------------------------------------------
 * check mode parameter
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    case( CPOL_MOD_CompactList ):
    case( CPOL_MOD_Insert ):
    case( CPOL_MOD_NotPresent ):
      break;

    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check format parameter
 *-------------------------------------------------------------------
 */
  switch( format )
  {
    case( CPOL_FRMT_Long ):
    case( CPOL_FRMT_Short ):
    case( CPOL_FRMT_Numeric ):

      if( index EQ ACI_NumParmNotPresent AND !oper )
      {
        pSIMCmdPrm->CPOLfrmt = format;
        return( AT_CMPL );
      }
      break;

    case( CPOL_FRMT_NotPresent ):

      format = pSIMCmdPrm->CPOLfrmt;
      break;

    default:
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
    }
  }

/*
 *-------------------------------------------------------------------
 * check for write entry
 *-------------------------------------------------------------------
 */
  if( oper )
  {
    /* code plmn id */
    if( ! cmhSIM_GetCodedPLMN( oper, format, plmn ))
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
    }

    /* if EF is already read */
    if( EfPLMNselStat EQ EF_STAT_READ )
    {
      if( mode EQ CPOL_MOD_CompactList )
      {
        cmhSIM_CmpctPlmnSel( CPOLSimEfDataLen, CPOLSimEfData );
      }

      if( index NEQ ACI_NumParmNotPresent )
      {
        if( index > (CPOLSimEfDataLen / ACI_LEN_PLMN_SEL_NTRY))
        {
          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx );
          return( AT_FAIL );
        }

        return cmhSIM_UpdPlmnSel( srcId, index, plmn, mode );
      }
      else

        return cmhSIM_FndEmptyPlmnSel( srcId, plmn );
    }
    else
    {
      if( simEntStat.curCmd NEQ AT_CMD_NONE )

        return( AT_BUSY );

      pSIMCmdPrm->CPOLidx  = (UBYTE)(index EQ ACI_NumParmNotPresent)?
                                    NOT_PRESENT_8BIT:index;
      pSIMCmdPrm->CPOLmode = mode;
      pSIMCmdPrm->CPOLact  = CPOL_ACT_Write;
      memcpy( pSIMCmdPrm->CPOLplmn, plmn, ACI_LEN_PLMN_SEL_NTRY );

      simEntStat.curCmd = AT_CMD_CPOL;
      simEntStat.entOwn = srcId;

    /* Implements Measure 150 and 159 */
    return cmhSIM_Req_or_Write_PlmnSel( srcId, ACT_RD_DAT );
    }
  }

/*
 *-------------------------------------------------------------------
 * check for delete entry
 *-------------------------------------------------------------------
 */
  else
  {
    /* check presence of index */
    if( index EQ ACI_NumParmNotPresent )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx );
      return( AT_FAIL );
    }

    /* if EF is already read */
    if( EfPLMNselStat EQ EF_STAT_READ )
    {
      if( mode EQ CPOL_MOD_CompactList )
      {
        cmhSIM_CmpctPlmnSel( CPOLSimEfDataLen, CPOLSimEfData );
      }

      if( index  > (CPOLSimEfDataLen / ACI_LEN_PLMN_SEL_NTRY) OR
         (index2 > (CPOLSimEfDataLen / ACI_LEN_PLMN_SEL_NTRY) AND
          index2 NEQ ACI_NumParmNotPresent))
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx );
        return( AT_FAIL );
      }

      if( index2 EQ ACI_NumParmNotPresent )

        return cmhSIM_DelPlmnSel( srcId, index, mode );

      else

        return cmhSIM_ChgPlmnSel( srcId, index, index2 );
    }
    else
    {
      if( simEntStat.curCmd NEQ AT_CMD_NONE )

        return( AT_BUSY );

      pSIMCmdPrm->CPOLidx  = (UBYTE)index;
      pSIMCmdPrm->CPOLidx2 = (index2 NEQ ACI_NumParmNotPresent)?
                             (UBYTE)index2:NOT_PRESENT_8BIT;
      pSIMCmdPrm->CPOLmode = mode;
      pSIMCmdPrm->CPOLact  = CPOL_ACT_Delete;

      simEntStat.curCmd = AT_CMD_CPOL;
      simEntStat.entOwn = srcId;

    /* Implements Measure 150 and 159 */
    return cmhSIM_Req_or_Write_PlmnSel( srcId, ACT_RD_DAT );
    }
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCRSM             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CRSM AT command
            which is responsible for restricted SIM access.

            <cmd>:     access command.
            <fileId>:  file identifier
            <p1>:      parameter 1
            <p2>:      parameter 2
            <p3>:      parameter 3
            <dataLen>: length of data
            <data>:    pointer to data
*/

T_ACI_RETURN sAT_PlusCRSM  ( T_ACI_CMD_SRC  srcId,
                             T_ACI_CRSM_CMD cmd,
                             SHORT          fileId,
                             SHORT          p1,
                             SHORT          p2,
                             SHORT          p3,
                             SHORT          dataLen,
                             UBYTE         *data   )
{
  T_SIM_TRNS_ACC_PRM prm;   /* holds access parameter */

  TRACE_FUNCTION ("sAT_PlusCRSM()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check entity status
 *-------------------------------------------------------------------
 */
  if( simEntStat.curCmd NEQ AT_CMD_NONE )

    return( AT_BUSY );

/*
 *-------------------------------------------------------------------
 * check command, data, p1, p2 and p3 parameters
 *-------------------------------------------------------------------
 */
  switch( cmd )
  {
    case( CRSM_CMD_UpdBin ):
    case( CRSM_CMD_UpdRec ):

      if( !data OR !dataLen )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }
      /*lint -fallthrough*/

    case( CRSM_CMD_ReadBin ):
    case( CRSM_CMD_ReadRec ):

      if( p1 EQ ACI_NumParmNotPresent OR
          p2 EQ ACI_NumParmNotPresent OR
          p3 EQ ACI_NumParmNotPresent )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }
      break;

    case( CRSM_CMD_GetResp ):
    case( CRSM_CMD_Status ):

      if( p3 EQ ACI_NumParmNotPresent )
        p3 = 0;
      break;

    case( CRSM_CMD_NotPresent ):
    default:
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
    }
  }

/*
 *-------------------------------------------------------------------
 * check fileId parameter
 *-------------------------------------------------------------------
 */
  if( fileId EQ ACI_NumParmNotPresent AND cmd NEQ CRSM_CMD_Status )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * convert command
 *-------------------------------------------------------------------
 */
  switch( cmd )
  {
    case( CRSM_CMD_UpdBin  ): prm.cmd = SIM_UPDATE_BINARY;break;
    case( CRSM_CMD_UpdRec  ): prm.cmd = SIM_UPDATE_RECORD;break;
    case( CRSM_CMD_ReadBin ): prm.cmd = SIM_READ_BINARY;break;
    case( CRSM_CMD_ReadRec ): prm.cmd = SIM_READ_RECORD;break;
    case( CRSM_CMD_GetResp ): prm.cmd = SIM_GET_RESPONSE;break;
    case( CRSM_CMD_Status  ): prm.cmd = SIM_STATUS;break;
  }

/*
 *-------------------------------------------------------------------
 * access SIM
 *-------------------------------------------------------------------
 */
  simEntStat.curCmd = AT_CMD_CRSM;
  simEntStat.entOwn = srcId;

  prm.reqDataFld = (USHORT)fileId;
  prm.p1         = (UBYTE)p1;
  prm.p2         = (UBYTE)p2;
  prm.p3         = (UBYTE)p3;
  prm.dataLen    = (UBYTE)dataLen;
  prm.transData  = data;

  psaSIM_TrnsSIMAccess( &prm );

  return( AT_EXCT );
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PlusCSIM             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CSIM AT command
            which is responsible for generic SIM access.

*/

T_ACI_RETURN sAT_PlusCSIM  ( T_ACI_CMD_SRC  srcId,
                             USHORT         dataLen,
                             UBYTE         *data    )
{
  T_SIM_TRNS_ACC_PRM prm;   /* holds access parameter */

  TRACE_FUNCTION ("sAT_PlusCSIM()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check entity status
 *-------------------------------------------------------------------
 */
  if( simEntStat.curCmd NEQ AT_CMD_NONE )
  {
    return( AT_BUSY );
  }

#ifndef ALLOW_CSIM_GSM
  if (data[0] EQ GSM_CLASS)
  {
    /* GSM instruction class is not allowed */
    TRACE_EVENT("GSM instruction class is not allowed");
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }
#endif

#if 0 /* do we really need the check for the ATP source ? */
#ifdef _TARGET_
  if (ati_is_src_type((UBYTE)srcId, ATI_SRC_TYPE_RIV) EQ FALSE)
  {
    /* don't allow other source type than RIV */
    TRACE_EVENT("other src type than RIV is not allowed");
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }
#endif /*_TARGET_*/
#endif /* */
  if (dataLen > MAX_SIM_TRANSP)
  {
    /* wrong length value */
    TRACE_EVENT("wrong length value");
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * access SIM
 *-------------------------------------------------------------------
 */
  simEntStat.curCmd = AT_CMD_CSIM;
  simEntStat.entOwn = srcId;

  prm.cmd        = SIM_TRANSP_CMD;
  prm.dataLen    = dataLen;
  prm.transData  = data;

  psaSIM_TrnsSIMAccess( &prm );

  return( AT_EXCT );

}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                 |
| STATE   : code                  ROUTINE : sAT_PercentPVRF          |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the %PVRF AT command
            which is responsible to verify a specific PIN.

            <pin>:    string of PIN chars.
            <newpin>: string of PIN chars required if requested PIN is
                      SIM PUK
*/

GLOBAL T_ACI_RETURN sAT_PercentPVRF( T_ACI_CMD_SRC   srcId,
                                     T_ACI_PVRF_TYPE type,
                                     CHAR * pin,
                                     CHAR * newpin )
{
  T_SIM_SET_PRM * pSIMSetPrm;  /* points to SIM parameter set */
  T_ACI_RETURN    retCd;       /* holds return code */

  TRACE_FUNCTION ("sAT_PercentPVRF()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

  pSIMSetPrm = &simShrdPrm.setPrm[srcId];

/*
 *-------------------------------------------------------------------
 * check entity status
 *-------------------------------------------------------------------
 */
  if( simEntStat.curCmd NEQ AT_CMD_NONE )

    return( AT_BUSY );

/*
 *-------------------------------------------------------------------
 * check for PIN type
 *-------------------------------------------------------------------
 */
  switch( type )
  {
    case( PVRF_TYPE_Pin1 ):
    case( PVRF_TYPE_Pin2 ):
    /*
     *---------------------------------------------------------------
     * PIN 1/2 verify is required
     *---------------------------------------------------------------
     */
      if( pin EQ NULL                 OR
          strlen( pin ) < MIN_PIN_LEN OR
          strlen( pin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin, pSIMSetPrm -> curPIN, PIN_LEN );
      pSIMSetPrm -> PINType = (type EQ PVRF_TYPE_Pin1)?
                                  PHASE_2_PIN_1:PHASE_2_PIN_2;
      simEntStat.curCmd     = AT_CMD_PVRF;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_VerifyPIN() < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in %%PVRF" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

    case( PVRF_TYPE_Puk1 ):
    case( PVRF_TYPE_Puk2 ):
    /*
     *---------------------------------------------------------------
     * PUK 1/2 verify is required
     *---------------------------------------------------------------
     */
      if( pin EQ NULL                    OR
          newpin EQ NULL                 OR
          strlen( pin ) NEQ PUK_LEN      OR
          strlen( newpin ) < MIN_PIN_LEN OR
          strlen( newpin ) > PIN_LEN        )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }

      cmhSIM_FillInPIN ( pin,    pSIMSetPrm -> unblkKey, PUK_LEN );
      cmhSIM_FillInPIN ( newpin, pSIMSetPrm -> curPIN,   PIN_LEN );
      pSIMSetPrm -> PINType = (type EQ PVRF_TYPE_Puk1)?
                                  PHASE_2_PUK_1:PHASE_2_PUK_2;
      simEntStat.curCmd     = AT_CMD_PVRF;
      simShrdPrm.owner     = (T_OWN)srcId;
      simEntStat.entOwn     = srcId;

      if( psaSIM_UnblockCard( ) < 0 )  /* verify PIN */
      {
        TRACE_EVENT( "FATAL RETURN psaSIM in %%PVRF" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return( AT_FAIL );
      }

      retCd = AT_EXCT;
      break;

  default:
    /*
     *---------------------------------------------------------------
     * unexpected PIN state
     *---------------------------------------------------------------
     */
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_DataCorrupt );
      return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * log command execution
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  {
  T_ACI_CLOG      cmdLog;      /* holds logging info */

  cmdLog.atCmd                = AT_CMD_PVRF;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = retCd;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sPVRF.srcId   = srcId;
  cmdLog.cmdPrm.sPVRF.type    = type;
  cmdLog.cmdPrm.sPVRF.pin     = pin;
  cmdLog.cmdPrm.sPVRF.newpin  = newpin;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( retCd );
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                |
|                                 ROUTINE : sAT_PercentCPRI         |
+-------------------------------------------------------------------+

  PURPOSE : set the CPRI mode for displaying/not displaying
            ciphering indications
*/

GLOBAL T_ACI_RETURN sAT_PercentCPRI( T_ACI_CMD_SRC srcId,
                                     UBYTE mode   )
{
  TRACE_FUNCTION ("sAT_PercentCPRI()");

  if( !cmh_IsVldCmdSrc( srcId ) )
  {
    return( AT_FAIL );
  }

  if (simShrdPrm.ciSIMEnabled NEQ FALSE)   /* Since this function is used by MMI,it just returns AT_CMPL */
  {
    return( AT_CMPL );               /* If CPRI is enabled in the SIM,it just returns AT_CMPL */
  }

  else
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }
}

#ifdef FF_DUAL_SIM
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                |
|                                 ROUTINE : sAT_PercentSIM         |
+-------------------------------------------------------------------+

  PURPOSE : Select the SIM to be powered on
*/

GLOBAL T_ACI_RETURN sAT_PercentSIM( T_ACI_CMD_SRC srcId,
                                     UBYTE sim_num   )
{
  T_SIM_SET_PRM * pSIMSetPrm; /* points to SIM parameter set */
 
  TRACE_FUNCTION ("sAT_PercentSIM()");

  if( !cmh_IsVldCmdSrc( srcId ) )
  {
    return( AT_FAIL );
  }

  pSIMSetPrm = &simShrdPrm.setPrm[srcId];

  if( simEntStat.curCmd NEQ AT_CMD_NONE )
  {
    TRACE_EVENT("Entity SIM is busy: cannot proceed command...");
    return( AT_BUSY );
  }

  if(CFUNfun EQ CFUN_FUN_Full)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  if(sim_num < SIM_NUM_0 OR sim_num > SIM_NUM_2)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  pSIMSetPrm->SIM_Selected = sim_num;

  simEntStat.curCmd = AT_CMD_SIM;
  simShrdPrm.owner = (T_OWN)srcId;
  simEntStat.entOwn =  srcId;

  if( psaSIM_SelectSIM() < 0 )   /* select SIM card */
  {
    TRACE_EVENT( "FATAL RETURN psaSIM in %SIM" );
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
    return( AT_FAIL );
  }
  return(AT_EXCT);
}
#endif /*FF_DUAL_SIM*/

#ifdef FF_CPHS_REL4
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                |
|                                 ROUTINE : sAT_PercentCFIS         |
+-------------------------------------------------------------------+

  PURPOSE : Set/Read the CFU staus in EF-CFIS file present in SIM
*/

GLOBAL T_ACI_RETURN sAT_PercentCFIS( T_ACI_CMD_SRC srcId,
                                    T_ACI_CFIS_MOD mode, 
                                    UBYTE index,
                                    UBYTE mspId,
                                    UBYTE cfuStat,
                                    CHAR* number, 
                                    T_ACI_TOA* type,
                                    UBYTE cc2_id)
{

  TRACE_FUNCTION ("sAT_PercentCFIS()");

 /*
  *-------------------------------------------------------------------
  * check command source
  *-------------------------------------------------------------------
  */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

 /*
  *-------------------------------------------------------------------
  * check entity status
  *-------------------------------------------------------------------
  */  
  if( simEntStat.curCmd NEQ AT_CMD_NONE )
    return( AT_BUSY );

 /*
  *-------------------------------------------------------------------
  * process parameter <mode>
  *-------------------------------------------------------------------
  */
  switch( mode )
  {
    case ( CFIS_MOD_Write ):
    case ( CFIS_MOD_Delete ):
      return cmhSIM_WrCfis (srcId,mode,index,mspId,cfuStat,number, 
                           type,cc2_id);
    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
  }
}
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                |
|                                 ROUTINE : sAT_PercentMWIS         |
+-------------------------------------------------------------------+

  PURPOSE :Set the Message Waiting status in EF-MWIS file in SIM
*/

GLOBAL T_ACI_RETURN sAT_PercentMWIS( T_ACI_CMD_SRC srcId,
                                     T_ACI_MWIS_MOD mode, 
                                     UBYTE mspId,
                                     T_ACI_MWIS_MWI *mwis)
{

  TRACE_FUNCTION ("sAT_PercentMWIS()");

 /*
  *-------------------------------------------------------------------
  * check command source
  *-------------------------------------------------------------------
  */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

 /*
  *-------------------------------------------------------------------
  * check entity status
  *-------------------------------------------------------------------
  */  
  if( simEntStat.curCmd NEQ AT_CMD_NONE )
    return( AT_BUSY );

 /*
  *-------------------------------------------------------------------
  * process parameter <mode>
  *-------------------------------------------------------------------
  */
  switch( mode )
  {
    case ( MWIS_MOD_Write ):
    case ( MWIS_MOD_Delete ):
      return cmhSIM_WrMwis (srcId,mode,mspId,mwis);
      break;
    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
  }
}
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_SIMS                |
|                                 ROUTINE : sAT_PercentMBDN         |
+-------------------------------------------------------------------+

  PURPOSE : Set/Read the Mailbox Numbers in EF-MBDN file present in SIM
*/

GLOBAL T_ACI_RETURN sAT_PercentMBDN( T_ACI_CMD_SRC srcId,
                                     T_ACI_MBN_MODE mode, 
                                     UBYTE index,
                                     CHAR* number, 
                                     T_ACI_TOA* type,
                                     UBYTE cc2_id,
                                     T_ACI_PB_TEXT *text)
{

  TRACE_FUNCTION ("sAT_PercentMBDN()");

#ifndef NO_ASCIIZ
  /* convert Text */
  if ( text NEQ NULL )
  {
    UBYTE   tmpBuf[MAX_ALPHA_LEN];
    USHORT  len;
    text->cs = CS_Sim;
    cmh_cvtToDefGsm ( (CHAR*)text->data, (CHAR*)tmpBuf, &len );
    text->len = (UBYTE)len;
    memcpy ( text->data, tmpBuf, text->len );
  }
#endif /* #ifndef NO_ASCIIZ */
 /*
  *-------------------------------------------------------------------
  * check command source
  *-------------------------------------------------------------------
  */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

 /*
  *-------------------------------------------------------------------
  * check entity status
  *-------------------------------------------------------------------
  */  
  if( simEntStat.curCmd NEQ AT_CMD_NONE )
    return( AT_BUSY );

 /*
  *-------------------------------------------------------------------
  * process parameter <mode>
  *-------------------------------------------------------------------
  */
  switch( mode )
  {
    case ( MBN_Mode_Write ): 
      if (number EQ NULL)
      { 
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return (AT_FAIL);
      }
    /* lint-fallthrough */
    case ( MBN_Mode_Delete ): 
      return cmhSIM_WrMbdn (srcId, mode, index, number, 
                           type, cc2_id, text);
    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
  }
}
#endif /* FF_CPHS_REL4 */


/* Implements Measure 50 */
/*
+------------------------------------------------------------------------------
|  Function    : cmhSIM_analyze_SIMLOCK_STATUS
+------------------------------------------------------------------------------
|  Description : This Function will analyze the SIMLOCK STATUS, passed as an
|                argument to this function and accordingly returns  AT_CMPL
|                AT_FAIL
|
|  Parameters  : status  -  SIMLOCK STATUS that needs to be analyzed
|                 
|  Return      : ACI Return Codes (Either AT_CMPL  or  AT_FAIL)
+------------------------------------------------------------------------------
*/

LOCAL T_ACI_RETURN cmhSIM_analyze_SIMLOCK_STATUS( T_SIMLOCK_STATUS status )
{
  TRACE_FUNCTION ( "cmhSIM_analyze_SIMLOCK_STATUS()" );

  switch ( status )
  {
    case SIMLOCK_ENABLED:
    case SIMLOCK_DISABLED:
      /* success */
      return AT_CMPL;

    case SIMLOCK_BLOCKED:  /* password tried too many times, phone blocked */
      ACI_ERR_DESC(ACI_ERR_CLASS_Cme, CME_ERR_PhoneFail);
      return AT_FAIL;

    case SIMLOCK_LOCKED: /* password wrong */
      ACI_ERR_DESC(ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd);
      return AT_FAIL;

    default: /* other error */
      ACI_ERR_DESC(ACI_ERR_CLASS_Cme, CME_ERR_Unknown);
      return AT_FAIL;
  }
}

/* Implements Measure 40 */
/*
+------------------------------------------------------------------------------
|  Function    : sAT_Plus_CAMM_CACM
+------------------------------------------------------------------------------
|  Description : This is the functional counterpart to the +CACM or +CAMM
|                AT commands.
|
|  Parameters  : at_cmd_id  - AT command identifier 
|                srcId      - AT command source identifier
|                value_type - AOC_ACM or AOC_ACMMAX 
|                value      - NULL in case of +CACM
|                             acmmax in case of +CAMM
|                pwd        - password
|
|  Return      : ACI functional return codes 
+------------------------------------------------------------------------------
*/

LOCAL T_ACI_RETURN sAT_Plus_CAMM_CACM ( T_ACI_AT_CMD  at_cmd_id,
                                        T_ACI_CMD_SRC srcId,
                                        UBYTE         value_type,
                                        void          *value,
                                        UBYTE         *pwd )
{
  T_ACI_RETURN  ret = AT_FAIL;

  TRACE_FUNCTION ( "sAT_Plus_CAMM_CACM()" );
  /*
   *-------------------------------------------------------------------
   * check command source
   *-------------------------------------------------------------------
   */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

  /*
   *-------------------------------------------------------------------
   * send parameters to advice of charge module.
   *-------------------------------------------------------------------
   */
  simEntStat.curCmd     = at_cmd_id;
  simShrdPrm.owner      = (T_OWN)srcId;
  simEntStat.entOwn     = srcId;
  ret = aoc_set_values ( srcId,
                         value_type,
                         value,
                         pwd );

  /*
   *-------------------------------------------------------------------
   * Check return value of aoc_set_values() equal to AT_FAIL,
   * resets simEntStat.curcmd and simEntStat.entown.
   *-------------------------------------------------------------------
   */

  if( ret EQ AT_FAIL )
  {
    simEntStat.curCmd     = AT_CMD_NONE;
    simShrdPrm.owner      = (T_OWN)srcId;
    simEntStat.entOwn     = srcId;
  }

  return( ret );

}




/*==== EOF ========================================================*/