view src/aci2/aci/cmh_sims.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 93999a60b835
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 "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 ==================================================*/

/*
+--------------------------------------------------------------------+
| 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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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;
      simEntStat.entOwn = simShrdPrm.owner = srcId;

    /* Turn off all possible ringing */
#ifdef FF_ATI
    io_setRngInd ( IO_RING_OFF, CRING_TYP_NotPresent, CRING_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, 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;
    simEntStat.entOwn = simShrdPrm.owner = srcId;

    mmEntStat.curCmd  = AT_CMD_CFUN;
    mmEntStat.entOwn  = mmShrdPrm.owner = srcId;

    pb_exit();

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


#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;
      simEntStat.entOwn = simShrdPrm.owner = 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 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;
      simEntStat.entOwn = simShrdPrm.owner = 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)
    {
      TRACE_EVENT("Not possible to proceed when mobile is switched off");
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return (AT_FAIL);
    }
    CFUNfun           = fun;

    /* Turn off all possible ringing */
#ifdef FF_ATI
    io_setRngInd ( IO_RING_OFF, CRING_TYP_NotPresent, CRING_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, 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;
    }
    mmEntStat.entOwn  = mmShrdPrm.owner = 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 );

}

/*
+--------------------------------------------------------------------+
| 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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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 );     

  switch (result)
  {
      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;
    }

  
}


/*
+--------------------------------------------------------------------+
| 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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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
 *-------------------------------------------------------------------
 */
  switch (result)
    {
      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;
    }
}






/*
+--------------------------------------------------------------------+
| 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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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)
          {
            switch (AciSLockShrd.current_lock)
            {
              case SIMLOCK_NETWORK:          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NetworkPersPukReq);       break;
              case SIMLOCK_NETWORK_SUBSET:   ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NetworkSubsetPersPukReq); break;
              case SIMLOCK_SERVICE_PROVIDER: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_ProviderPersPukReq);      break;
              case SIMLOCK_CORPORATE:        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_CorporatePersPukReq);     break;
              case SIMLOCK_SIM:              ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_PhoneFail);               break;
                /* for SIMLOCK_SIM there is no PUK available. Instead the phone is blocked and can only be unblocked
                   by the manufacturer as an anti-theft protection. (See manual of several competitor phones ...) */
              case SIMLOCK_FIRST_SIM:        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_PhFSimPukReq);            break;
              default:                       ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );            break;
            }
          }
          else
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );
          return( AT_FAIL );
        }
        else			
        {
             simEntStat.curCmd     = AT_CMD_CPIN;
	      aci_slock_set_CFG();
             if(cfg_data EQ NULL)
             	{
             	  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_Unknown ); 
                 return( AT_FAIL );
             	}
             aci_slock_init();
	      
             retSlStatus = SIMLOCK_ENABLED;
	      if(AciSLockShrd.current_lock < SIMLOCK_SIM)
             {
                AciSLockShrd.current_lock= AciSLockShrd.current_lock +1;
                 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;
      simEntStat.entOwn     = simShrdPrm.owner = 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;
      simEntStat.entOwn     = simShrdPrm.owner = 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;
      simEntStat.entOwn     = simShrdPrm.owner = 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;
      simEntStat.entOwn     = simShrdPrm.owner = 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)
{
  T_ACI_RETURN  ret = AT_FAIL;

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

/*
 *-------------------------------------------------------------------
 * send parameters to advice of charge module.
 *-------------------------------------------------------------------
 */
  simEntStat.curCmd     = AT_CMD_CAMM;
  simEntStat.entOwn     = simShrdPrm.owner = srcId;
  ret = aoc_set_values (srcId,
                        AOC_ACMMAX,
                        (void *) acmmax,
                        (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;
    simEntStat.entOwn     = simShrdPrm.owner = OWN_NONE;
  }

  return( ret );
}

/*
+--------------------------------------------------------------------+
| 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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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;
  simEntStat.entOwn     = simShrdPrm.owner = 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;
    simEntStat.entOwn     = simShrdPrm.owner = OWN_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)
{
  T_ACI_RETURN  ret = AT_FAIL;
  
  TRACE_FUNCTION ("sAT_PlusCACM()");
/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * send parameters to advice of charge module.
 *-------------------------------------------------------------------
 */
  simEntStat.curCmd     = AT_CMD_CACM;
  simEntStat.entOwn     = simShrdPrm.owner = srcId;
  ret = aoc_set_values (srcId,
                        AOC_ACM,
                        (void *) NULL,
                        (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;
    simEntStat.entOwn     = simShrdPrm.owner = OWN_NONE;
  }

  return( ret );
}

/*
+--------------------------------------------------------------------+
| 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 */
  T_SIM_SET_PRM * pSIMSetPrm;       /* points to SIM parameter set */
  UBYTE plmn[ACI_LEN_PLMN_SEL_NTRY];/* holds coded plmn id */

  TRACE_FUNCTION ("sAT_PlusCPOL()");

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

  pSIMSetPrm = &simShrdPrm.setPrm[srcId];
  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;

      return cmhSIM_ReqPlmnSel ( srcId );
    }
  }

/*
 *-------------------------------------------------------------------
 * 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;

      return cmhSIM_ReqPlmnSel ( srcId );
    }
  }
}

/*
+--------------------------------------------------------------------+
| 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))
  {
    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 );

/*
 *-------------------------------------------------------------------
 * 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))
  {
    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 );
  }

#if 0 // Dmitriy: for EAP-SIM we need to run the GSM algorithm
  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))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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;
      simEntStat.entOwn     = simShrdPrm.owner = 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;
      simEntStat.entOwn     = simShrdPrm.owner = 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 ) )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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 ) )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    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;
  simEntStat.entOwn = simShrdPrm.owner = 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*/
/*==== EOF ========================================================*/