/* 
+----------------------------------------------------------------------------- 
|  Project :  GSM-PS (6147)
|  Modul   :  CMH_SSS
+----------------------------------------------------------------------------- 
|  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 SS.
+----------------------------------------------------------------------------- 
*/ 

#ifndef CMH_SSS_C
#define CMH_SSS_C
#endif

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

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

#ifdef UART
#include "dti.h"
#include "dti_conn_mng.h"
#endif

#include "ksd.h"
#include "psa.h"
#include "psa_ss.h"
#include "psa_sim.h"
#include "psa_sms.h"
#include "psa_cc.h"
#include "cmh.h"
#include "cmh_ss.h"
#include "cmh_sim.h"
#include "cmh_sms.h"
#include "cmh_cc.h"

#ifdef SIM_TOOLKIT
#include "psa_cc.h"
#include "psa_sat.h"
#include "cmh_sat.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#include "cmh_cc.h"
#endif /* of SIM_TOOLKIT */

#include "psa_util.h"
#ifdef GPRS
#include "gaci_cmh.h"
#endif /* GPRS */
#include "phb.h"


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

#ifdef SIM_PERS
#include "general.h"  // inluded for UINT8 compilation error in sec_drv.h
#include "sec_drv.h"

EXTERN T_SEC_DRV_CONFIGURATION *cfg_data;
EXTERN T_SIM_MMI_INSERT_IND *last_sim_mmi_insert_ind;
#endif

/*==== CONSTANTS ==================================================*/
#define AT_TOA_DEF_INT    (129)  /* toa default for international no.*/
#define AT_TOA_DEF_NAT    (145)  /* toa default for national no.*/
#define AT_TOS_DEF        (128)  /* tos default */
#define AT_CFNRY_DEF_TIME (20)   /* default no reply time */




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

/*==== VARIABLES ==================================================*/
EXTERN T_ACI_CUSCFG_PARAMS cuscfgParams;
GLOBAL SHORT Ext_USSD_Res_Pending_sId;
GLOBAL T_CUSDR_EXT_USSD_RES Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Not_Pending;

/*==== FUNCTIONS ==================================================*/

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

  PURPOSE : This is the functional counterpart to the +CCFC AT command
            which is responsible to set the parameters for call
            forwarding supplementary services.

            <reason> : reason for CF.
            <mode>   : CF mode.
            <number> : number to be forwarded to.
            <type>   : type of number.
            <class>  : class of calls.
            <subaddr>: subaddress of number.
            <satype> : type of subaddress.
            <time>   : no reply time.
*/

GLOBAL T_ACI_RETURN sAT_PlusCCFC  ( T_ACI_CMD_SRC srcId,
                                    T_ACI_CCFC_RSN reason,
                                    T_ACI_CCFC_MOD mode,
                                    CHAR*          number,
                                    T_ACI_TOA*     type,
                                    T_ACI_CLASS    class_type,
                                    CHAR*          subaddr,
                                    T_ACI_TOS*     satype,
                                    SHORT          time)
{
  SHORT sId1, sId2;         /* holds service id */
  UBYTE ssCd;               /* holds ss code */
  UBYTE bst1, bst2;         /* holds basic service type */
  UBYTE bs1, bs2;           /* holds basic service */
  UBYTE ton, tos;           /* holds type of number/subaddress */
  UBYTE npi, oe;            /* holds numbering plan/odd.even indicator */
  BOOL  mltyTrnFlg = FALSE; /* flags for multi transaction */
  T_CLPTY_PRM *ccfc_cldPty;

 #ifdef SIM_TOOLKIT
  T_ACI_RETURN   retVal;
 #endif /* of SIM_TOOLKIT */
 
  TRACE_FUNCTION ("sAT_PlusCCFC");

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

  if( cmhPrm[srcId].ssCmdPrm.mltyTrnFlg NEQ 0 )
  {
    TRACE_EVENT("ssCmdPrm.mltyTrnFlg NEQ 0 !!! CCFC busy");
    return( AT_BUSY );
  }

/*
 *-------------------------------------------------------------------
 * check parameter <time>
 *-------------------------------------------------------------------
 */
  if( time EQ ACI_NumParmNotPresent )
  {
    time = AT_CFNRY_DEF_TIME;
  }
  else if (time < CCFC_TIME_MIN AND time >= 1)
  {
    /* 07.07 allows [1...30] for time while
       09.02 allows [5...30]. So map [1..4] to 5 */
    time = CCFC_TIME_MIN;
  }
  else if( time > CCFC_TIME_MAX OR time < CCFC_TIME_MIN )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check parameter <reason>
 *-------------------------------------------------------------------
 */
  switch( reason )
  {
    case( CCFC_RSN_Uncond      ): ssCd = SS_CD_CFU;       break;
    case( CCFC_RSN_Busy        ): ssCd = SS_CD_CFB;       break;
    case( CCFC_RSN_NoReply     ): ssCd = SS_CD_CFNRY;     break;
    case( CCFC_RSN_NotReach    ): ssCd = SS_CD_CFNRC;     break;
    case( CCFC_RSN_Forward     ): ssCd = SS_CD_ALL_FWSS;  break;
    case( CCFC_RSN_CondForward ): ssCd = SS_CD_ALL_CFWSS; break;

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

/*
 *-------------------------------------------------------------------
 * check parameter <class>
 *-------------------------------------------------------------------
 */
  if( !cmhSS_CheckClass( class_type, &bs1, &bst1, &bs2, &bst2, &mltyTrnFlg ))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/* SIM TOOLKIT & FDN HANDLING */

    retVal = cmhSS_CF_SAT_Handle( srcId, reason, mode, number, type, class_type, subaddr, satype, time);

    if( retVal NEQ AT_CMPL )
        return( retVal );
  




/*
 *-------------------------------------------------------------------
 * check parameter <class> against possible ALS-Lock
 *-------------------------------------------------------------------
 */
  if ((ALSlock EQ ALS_MOD_SPEECH     AND class_type EQ  CLASS_AuxVce) OR
      (ALSlock EQ ALS_MOD_AUX_SPEECH AND class_type NEQ CLASS_AuxVce))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_AlsLock );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * get a new service table entry
 *-------------------------------------------------------------------
 */
  sId1 = psaSS_stbNewEntry();

  if( sId1 EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
    return( AT_FAIL );
  }

  sId2 = NO_ENTRY;

  if( mltyTrnFlg )
  {
    ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;

    sId2 = psaSS_stbNewEntry();

    if( sId2 EQ NO_ENTRY )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
      return( AT_FAIL );
    }
  }

/*
 *-------------------------------------------------------------------
 * check parameter <mode>
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    /*
     *---------------------------------------------------------------
     * enable, disable and erase call forwarding service
     *---------------------------------------------------------------
     */
    case( CCFC_MOD_Disable    ):
    case( CCFC_MOD_Enable     ):
    case( CCFC_MOD_Erasure    ):

      CCD_START;

      if( mode EQ CCFC_MOD_Disable )
        psaSS_asmDeactivateSS( ssCd, bst1, bs1 );

      else if( mode EQ CCFC_MOD_Enable )
        psaSS_asmActivateSS( ssCd, bst1, bs1 );

      else if( mode EQ CCFC_MOD_Erasure )
        psaSS_asmEraseSS( ssCd, bst1, bs1 );

      ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;
      ssShrdPrm.stb[sId1].ssCode     = ssCd;
      ssShrdPrm.stb[sId1].srvOwn     = srcId;
      ssShrdPrm.stb[sId1].ClassType  = class_type;  /* the complete classes defined by the user */

      /* start first transaction */
      ssShrdPrm.stb[sId1].curCmd        = AT_CMD_CCFC;

      cmhSS_flagTrn( sId1, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
      psaSS_NewTrns(sId1);

      if( mltyTrnFlg )
      {
        if( mode EQ CCFC_MOD_Disable )
          psaSS_asmDeactivateSS( ssCd, bst2, bs2 );

        else if( mode EQ CCFC_MOD_Enable )
          psaSS_asmActivateSS( ssCd, bst2, bs2 );

        else if( mode EQ CCFC_MOD_Erasure )
          psaSS_asmEraseSS( ssCd, bst2, bs2 );

        ssShrdPrm.stb[sId2].ntryUsdFlg = TRUE;
        ssShrdPrm.stb[sId2].ssCode     = ssCd;
        ssShrdPrm.stb[sId2].srvOwn     = srcId;
        ssShrdPrm.stb[sId2].ClassType  = class_type;  /* the complete classes defined by the user */

        /* start second transaction */
        ssShrdPrm.stb[sId2].curCmd = AT_CMD_CCFC;

        cmhSS_flagTrn( sId2, &(ssShrdPrm.mltyTrnFlg)); /* only for the second one */
        cmhSS_flagTrn( sId2, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));

        psaSS_NewTrns(sId2);
      }

      CCD_END;
      break;

    /*
     *---------------------------------------------------------------
     * register call forwarding service
     *---------------------------------------------------------------
     */
    case( CCFC_MOD_Register   ):

      if(number EQ NULL)
      {
        TRACE_EVENT("ERROR: cannot register CCFC without a number");
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
      }
      MALLOC(ccfc_cldPty, sizeof(T_CLPTY_PRM));
      cmhCC_init_cldPty( ccfc_cldPty );

      cmh_bldCalPrms( number, ccfc_cldPty );

      /* check for TOA default */
      if(type EQ NULL)
      {
        ton = ccfc_cldPty->ton;
        npi = ccfc_cldPty->npi;
      }
      else if(type->ton EQ TON_NotPresent OR
              type->npi EQ NPI_NotPresent)
      {
        ton = ccfc_cldPty->ton;
        npi = ccfc_cldPty->npi;
      }
      else
      {
        ton = type->ton;
        npi = type->npi;
      }

      /* check for TOS default */
      if(satype EQ NULL)
      {
        tos = TOS_X213;
        oe  = OEI_EVEN;
      }
      else if(satype->tos EQ TOS_NotPresent OR
              satype->oe  EQ OE_NotPresent)
      {
        tos = TOS_X213;
        oe  = OEI_EVEN;
      }
      else
      {
        tos = satype -> tos;
        oe  = satype -> oe;
      }

      if(subaddr EQ NULL           AND
         ccfc_cldPty->sub[0] NEQ 0) /* if not set by user AND number contained a subaddress */
      {
        subaddr = (CHAR *)ccfc_cldPty->sub;
      }

      CCD_START;

      psaSS_asmRegisterSS( ssCd, bst1, bs1,
                           ton, npi, (UBYTE*)ccfc_cldPty->num, tos, oe, (UBYTE *)subaddr, (UBYTE)time );

      ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;
      ssShrdPrm.stb[sId1].ssCode     = ssCd;
      ssShrdPrm.stb[sId1].srvOwn     = srcId;

      /* start first transaction */
      ssShrdPrm.stb[sId1].curCmd        = AT_CMD_CCFC;
      cmhSS_flagTrn( sId1, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
      psaSS_NewTrns(sId1);

      if( mltyTrnFlg )
      {
        psaSS_asmRegisterSS( ssCd, bst2, bs2,
                             ton, npi, (UBYTE*)ccfc_cldPty->num, tos, oe, (UBYTE *)subaddr, (UBYTE)time );

        ssShrdPrm.stb[sId2].ntryUsdFlg = TRUE;
        ssShrdPrm.stb[sId2].ssCode     = ssCd;
        ssShrdPrm.stb[sId2].srvOwn     = srcId;

        /* start second transaction */
        ssShrdPrm.stb[sId2].curCmd = AT_CMD_CCFC;
        cmhSS_flagTrn( sId2, &(ssShrdPrm.mltyTrnFlg)); /* only for the second one */
        cmhSS_flagTrn( sId2, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
        psaSS_NewTrns(sId2);
      }
      MFREE(ccfc_cldPty);
      CCD_END;
      break;

    /*
     *---------------------------------------------------------------
     * unexpected mode
     *---------------------------------------------------------------
     */
    case( CCFC_MOD_NotPresent ):
    default:

      ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
      if( sId2 NEQ NO_ENTRY ) ssShrdPrm.stb[sId2].ntryUsdFlg = FALSE;

      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
  {
  T_ACI_CLOG cmdLog;        /* holds logging info */

  cmdLog.atCmd                = AT_CMD_CCFC;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = sId1+1;
  cmdLog.cmdPrm.sCCFC.srcId   = srcId;
  cmdLog.cmdPrm.sCCFC.reason  = reason;
  cmdLog.cmdPrm.sCCFC.mode    = mode;
  cmdLog.cmdPrm.sCCFC.number  = number;
  cmdLog.cmdPrm.sCCFC.type    = type;
  cmdLog.cmdPrm.sCCFC.class_type = class_type;
  cmdLog.cmdPrm.sCCFC.subaddr = subaddr;
  cmdLog.cmdPrm.sCCFC.satype  = satype;
  cmdLog.cmdPrm.sCCFC.time    = time;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( AT_EXCT );
}

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

  PURPOSE : This is the functional counterpart to the +CLCK AT command
            which is responsible to set the parameters for call
            barring supplementary services.

            <fac>    : CB facility.
            <mode>   : CB mode.
            <passwd> : password for CB facility.
            <class_type>: class of calls.
*/
LOCAL BOOL check_sat_cb_pwd_required(UBYTE ssCd, CHAR  *passwd)
{
#ifdef SIM_TOOLKIT
  SHORT ss_id = NO_ENTRY;
  T_OWN owner;

  /* Special case: there was an SS (by STK) transaction running. 
     It returned get password, handle the password for this transaction */

  TRACE_FUNCTION ("check_sat_ss_pwd_required ()");

  /* satShrdPrm.sId_pwd_requested will be reset by any mnss_end_ind
  to be sure it has been reset.
  This means: user has to give password right after error has been
  shown. */
  ss_id = satShrdPrm.sId_pwd_requested;
  if( ss_id EQ NO_ENTRY)
  {
    return(FALSE);
  }

  if( ssShrdPrm.stb[ss_id].srvOwn NEQ OWN_SAT )
  {
    satShrdPrm.sId_pwd_requested = NO_ENTRY;
    return(FALSE);
  }
  TRACE_EVENT("Password required during a SAT session");
  
  if( ssShrdPrm.stb[ss_id].curCmd NEQ KSD_CMD_CB )
  {
    TRACE_EVENT_P1("Wrong command context: %d", ssShrdPrm.stb[ss_id].curCmd);
    satShrdPrm.sId_pwd_requested = NO_ENTRY;
    return(FALSE);
  }
  owner = ssShrdPrm.stb[ss_id].srvOwn;

  if(ssShrdPrm.stb[ss_id].ssCode EQ ssCd)
  { 
    /* store for later use (as usual)*/
    strncpy
    (
      (char *) cmhPrm[owner].ssCmdPrm.CXXXpwd,
      (char *) passwd,
      MAX_PWD_NUM
    );
    cmhPrm[owner].ssCmdPrm.CXXXpwd[MAX_PWD_NUM] = '\0';
    psaSS_asmVerifyPWD( cmhPrm[owner].ssCmdPrm.CXXXpwd);
    psaSS_CntTrns(ss_id);
    satShrdPrm.sId_pwd_requested = NO_ENTRY;
    return(TRUE); /* as pwd only needed for SAT session*/
  }
  else
  {
    TRACE_EVENT_P1("Wrong Service type: %d", ssCd);
  }
  satShrdPrm.sId_pwd_requested = NO_ENTRY;
#endif /* SIM_TOOLKIT */
  return(FALSE);
}

/*
+------------------------------------------------------------------------------
|  Function    : sAT_PlusCLCK
+------------------------------------------------------------------------------
|  Description : This is the functional counterpart to the +CLCK AT command
|            which is responsible to set the parameters for call
|            barring supplementary services. also fo locking and unlocking ME for categories 
|            Networl lock, Network Subset lock, Service Provider Lock, Corporate Lock, SIM Lock
|
|  Parameters  : <fac>    : CB facility.
|                      <mode>   : CB mode.
|                      <passwd> : password for CB facility.
|                      <class_type>: class of calls.
|
|  Return      :  AT_FAIL    -      execution of command failed 
|         AT_CMPL   -      execution of command completed 
|         AT_EXCT   -      execution of command is in progress 
|         AT_BUSY   -      execution of command is rejected due
|
+------------------------------------------------------------------------------
*/

GLOBAL T_ACI_RETURN sAT_PlusCLCK  ( T_ACI_CMD_SRC srcId,
                                    T_ACI_CLCK_FAC fac,
                                    T_ACI_CLCK_MOD mode,
                                    CHAR  *        passwd,
                                    T_ACI_CLASS    class_type)
{
  SHORT sId1, sId2;        /* holds service id  */
  UBYTE ssCd;                  /* holds ss code     */
  UBYTE bst1, bst2;         /* holds basic service type */
  UBYTE bs1,  bs2;           /* holds basic service */
  BOOL  mltyTrnFlg = FALSE; /* flags for multi transaction */
  #ifdef SIM_PERS
  T_SIMLOCK_TYPE slocktype;
  T_SIMLOCK_STATUS rlockstatus;
  T_SIMLOCK_TYPE lock_type; 
  T_SIMLOCK_TYPE last_lock_type; 
  #endif
  SHORT psasim_ret;
  BOOL  done = FALSE;
#ifdef SIM_PERS
  T_ACI_CME_ERR err_code = CME_ERR_NotPresent; /* code holding the correct error code calculated */
  UBYTE cmdBuf;                 /* buffers current command */
#endif
#ifdef SIM_PERS
  T_OPER_RET_STATUS fcResetStat;  /*holds Failure Counter Reset Return Status Introduced on 11/03/2005*/
  T_SIMLOCK_STATUS retSlStatus; /* holds return code */
#endif
  T_ACI_RETURN   retVal;

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

/*
 *-------------------------------------------------------------------
 * check parameter <fac>
 *-------------------------------------------------------------------
 */
  switch( fac )
  {
    case( CLCK_FAC_Ao ): ssCd = SS_CD_BAOC;     break;
    case( CLCK_FAC_Oi ): ssCd = SS_CD_BOIC;     break;
    case( CLCK_FAC_Ox ): ssCd = SS_CD_BOICXH;   break;
    case( CLCK_FAC_Ai ): ssCd = SS_CD_BAIC;     break;
    case( CLCK_FAC_Ir ): ssCd = SS_CD_BICRM;    break;
    case( CLCK_FAC_Ab ): ssCd = SS_CD_ALL_CBSS; break;
    case( CLCK_FAC_Ag ): ssCd = SS_CD_BOC;      break;
    case( CLCK_FAC_Ac ): ssCd = SS_CD_BIC;      break;

    case( CLCK_FAC_Sc ):
    case( CLCK_FAC_Fd ):
#ifdef SIM_PERS
    case( CLCK_FAC_Pn ):
    case( CLCK_FAC_Pu ):
    case( CLCK_FAC_Pc ):
    case( CLCK_FAC_Pp ):
    case( CLCK_FAC_Pf ):
    case( CLCK_FAC_Ps ):
#endif
    case( CLCK_FAC_Al ):
#ifdef SIM_PERS
    case( CLCK_FAC_Fc ):
    case(CLCK_FAC_Fcm): 
#endif
      ssCd = NOT_PRESENT_8BIT; break;

    case( CLCK_FAC_NotPresent  ):
    default:

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

/*
 *-------------------------------------------------------------------
 * if action is related to SS
 *-------------------------------------------------------------------
 */
  if( ssCd NEQ NOT_PRESENT_8BIT )
  {
  /*
   *-------------------------------------------------------------------
   * check parameter <passwd>
   *-------------------------------------------------------------------
   */
    if( passwd AND strlen( passwd ) > MAX_PWD_NUM )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
    }

  /*
   *-------------------------------------------------------------------
   * check parameter <class>
   *-------------------------------------------------------------------
   */
    if( !cmhSS_CheckCbClass( class_type, &bs1, &bst1, &bs2, &bst2, &mltyTrnFlg ))
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return( AT_FAIL );
    }

    if( cmhPrm[srcId].ssCmdPrm.mltyTrnFlg NEQ 0 )
      return( AT_BUSY );

  /*
   *-------------------------------------------------------------------
   * check combination of <mode> and <fac>
   *-------------------------------------------------------------------
   */
    if((fac EQ CLCK_FAC_Ab OR fac EQ CLCK_FAC_Ag OR fac EQ CLCK_FAC_Ac)
       AND mode NEQ CLCK_MOD_Unlock )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return( AT_FAIL );
    }

    /*** Shangai's labs tessession fix: adapted to this version from 1.3.3 (TCS 2.0) ****/
      /* Special case: there was an SS (by STK) transaction running. 
         It returned get password, handle the password for this transaction */
    done = check_sat_cb_pwd_required(ssCd, passwd);
    if(done)
    {
      return(AT_CMPL); /* as pwd only needed for SAT session*/
    }
    /* End fix */


/* SIM TOOLKIT & FDN HANDLING */
    retVal = cmhSS_Call_Barr_SAT_Handle( srcId, mode, fac, passwd, class_type);

    if( retVal NEQ AT_CMPL )
        return( retVal );
  
  /*
   *-------------------------------------------------------------------
   * get a new service table entry
   *-------------------------------------------------------------------
   */
    sId1 = psaSS_stbNewEntry();

    if( sId1 EQ NO_ENTRY )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
      return( AT_FAIL );
    }

    sId2 = NO_ENTRY;

    if( mltyTrnFlg )
    {
      ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;
      sId2 = psaSS_stbNewEntry();

      if( sId2 EQ NO_ENTRY )
      {
        ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
        return( AT_FAIL );
      }
    }

  /*
   *-------------------------------------------------------------------
   * check parameter <mode>
   *-------------------------------------------------------------------
   */
    switch( mode  )
    {
      /*
       *---------------------------------------------------------------
       * lock and unlock call barring service
       *---------------------------------------------------------------
       */
      case( CLCK_MOD_Unlock ):
      case( CLCK_MOD_Lock   ):

        CCD_START;

        if( mode EQ CLCK_MOD_Unlock )
          psaSS_asmDeactivateSS( ssCd, bst1, bs1 );

        else if( mode EQ CLCK_MOD_Lock )
          psaSS_asmActivateSS( ssCd, bst1, bs1 );

        ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;
        ssShrdPrm.stb[sId1].ssCode     = ssCd;
        ssShrdPrm.stb[sId1].srvOwn     = srcId;

        /* start first transaction */
        ssShrdPrm.stb[sId1].curCmd        = AT_CMD_CLCK;
        cmhSS_flagTrn( sId1, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
        psaSS_NewTrns(sId1);

        if( mltyTrnFlg )
        {
          if( mode EQ CLCK_MOD_Unlock )
            psaSS_asmDeactivateSS( ssCd, bst2, bs2 );

          else if( mode EQ CLCK_MOD_Lock )
            psaSS_asmActivateSS( ssCd, bst2, bs2 );

          ssShrdPrm.stb[sId2].ntryUsdFlg = TRUE;
          ssShrdPrm.stb[sId2].ssCode      = ssCd;
          ssShrdPrm.stb[sId2].srvOwn     = srcId;

          /* start second transaction */
          ssShrdPrm.stb[sId2].curCmd = AT_CMD_CLCK;
          cmhSS_flagTrn( sId2, &(ssShrdPrm.mltyTrnFlg)); /* only for the second one */
          cmhSS_flagTrn( sId2, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
          psaSS_NewTrns(sId2);
        }
        CCD_END;
        break;

      /*
       *---------------------------------------------------------------
       * unexpected mode
       *---------------------------------------------------------------
       */
      case( CLCK_MOD_NotPresent ):
      default:

        ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
        if( sId2 NEQ NO_ENTRY ) ssShrdPrm.stb[sId2].ntryUsdFlg = FALSE;

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

  /*
   *-------------------------------------------------------------------
   * store password for later use
   *-------------------------------------------------------------------
   */
    if( passwd )
    {
      strncpy
      (
        (char *) cmhPrm[srcId].ssCmdPrm.CXXXpwd,
        (char *) passwd,
        MAX_PWD_NUM
      );
      cmhPrm[srcId].ssCmdPrm.CXXXpwd[MAX_PWD_NUM] = '\0';
    }
  }

  /*
   *-------------------------------------------------------------------
   * if action is related to SIM
   *-------------------------------------------------------------------
   */
  else
  {
      if( simEntStat.curCmd NEQ AT_CMD_NONE )
      return( AT_BUSY );

    switch (fac)
    {
      /*
       *---------------------------------------------------------------
       * access PIN 1
       *---------------------------------------------------------------
       */
      case CLCK_FAC_Sc:
        switch( mode )
        {
          case( CLCK_MOD_Unlock ):
          case( CLCK_MOD_Lock   ):
            if (simShrdPrm.PINStat EQ PS_PUK1)
            {
              ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimPukReq);
              return( AT_FAIL );
            }
            if (!psaSIM_ChkSIMSrvSup(SRV_CHV1_Disable))
            {
              ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow);
              return( AT_FAIL );
            }
            if( !passwd OR (strlen( passwd ) > PIN_LEN) )
            {
              ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
              return( AT_FAIL );
            }
            if( strlen( passwd ) < MIN_PIN_LEN OR   
                strlen( passwd ) > PIN_LEN        )
            {
              ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
              return( AT_FAIL );
            }
            cmhSIM_FillInPIN ( passwd, simShrdPrm.setPrm[srcId].curPIN, PIN_LEN );
            simShrdPrm.setPrm[srcId].PINType = PHASE_2_PIN_1;
            simEntStat.curCmd     = AT_CMD_CLCK;
            simEntStat.entOwn     = simShrdPrm.owner = srcId;

            if( mode EQ CLCK_MOD_Lock )
            {
              psasim_ret = psaSIM_EnablePIN( );
            }
            else /* if( mode EQ CLCK_MOD_Unlock ) */
            {
              psasim_ret = psaSIM_DisablePIN( );
            }

            if(psasim_ret < 0)
            {
              TRACE_EVENT( "FATAL RETURN psaSIM in +CLCK" );
              ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
              return( AT_FAIL );
            }
            break;

          default:

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

      /*
       *---------------------------------------------------------------
       * access fixed dialling feature
       *---------------------------------------------------------------
       */
      case CLCK_FAC_Fd:
    if (!psaSIM_ChkSIMSrvSup(SRV_FDN))
        {
          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow);
          return( AT_FAIL );
        }
        /* 
          Check the SIM PIN States before sending any request to SIM 
        */
        if ( simShrdPrm.PINStat EQ PS_PUK2 )
        {
          TRACE_EVENT("sAT_PlusCLCK_ME(): SIM PIN-2 Bolcked PUK-2 Required");
          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimPuk2Req );
          return( AT_FAIL );
        }
       
        /* 
          According to the standards 27.007 Sec 7.4 for facility "FDN": 
          if PIN2 authentication has not been done during the current session,
          PIN2 is required as <passwd>; Below condition will do the
          same to check to see whether <passwd> is required / not. 
        */

        if ( simShrdPrm.pn2Stat EQ PS_PIN2  OR 
             simShrdPrm.pn2Stat EQ NO_VLD_PS )
        { 
          if ( simShrdPrm.PINStat EQ PS_RDY OR
               simShrdPrm.PINStat EQ PS_PIN2 )
          {
            simShrdPrm.PINStat = PS_PIN2;          
          }
          else
          {
            TRACE_EVENT("sAT_PlusCLCK_ME(): SIM PIN State is NOT Valid");
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimFail );
            return( AT_FAIL );
          }
        
          if( !passwd OR ( strlen( passwd ) > PIN_LEN OR
               strlen( passwd ) < MIN_PIN_LEN ) )
          {
            TRACE_EVENT("sAT_PlusCLCK_ME(): SIM PIN-2 Password is Omitted");
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimPin2Req );
            return( AT_FAIL );
          }
        }

         /* 
         * test class_type whether it is supported and store it temporarily for further use 
         */      
        if( class_type EQ CLASS_NotPresent OR    /* default case */
            class_type EQ CLASS_VceDatFax     )  /* case 7       */
        {
          simShrdPrm.classFDN = CLASS_VceDatFax;
        }
        else if ( class_type EQ CLASS_VceDatFaxSms  ) /* case 15 */
        {
          simShrdPrm.classFDN = CLASS_VceDatFaxSms;  /* set global class type */
        }
        else  /* parameter not supported */
        {
          TRACE_EVENT( "class type not supported, +CLCK rejected" );
          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotSupp );
          return( AT_FAIL );        
        }
        simShrdPrm.setPrm[srcId].actProc = (mode EQ CLCK_MOD_Lock)?
                                             SIM_FDN_ENABLE:SIM_FDN_DISABLE;

        simEntStat.curCmd = AT_CMD_CLCK;
        simEntStat.entOwn = simShrdPrm.owner = srcId;

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

        /* store PIN 2 for later use */
        /* if( passwd )  ... already checked in the beginning! */
        cmhSIM_FillInPIN ( passwd, simShrdPrm.setPrm[srcId].curPIN, PIN_LEN );

        break;

      /*
       *---------------------------------------------------------------
       * lock ALS setting with PIN2
       *---------------------------------------------------------------
       */
      case CLCK_FAC_Al:

        if( !passwd OR ( strlen( passwd ) > PIN_LEN     OR
                         strlen( passwd ) < MIN_PIN_LEN ) )
        {
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
          return( AT_FAIL );
        }

        cmhSIM_FillInPIN ( passwd, simShrdPrm.setPrm[srcId].curPIN, PIN_LEN );

        simShrdPrm.setPrm[srcId].actProc = (mode EQ CLCK_MOD_Lock)?
                                             SIM_ALS_LOCK:SIM_ALS_UNLOCK;

        simShrdPrm.setPrm[srcId].PINType = PHASE_2_PIN_2;

        simEntStat.curCmd = AT_CMD_CLCK;
        simEntStat.entOwn = simShrdPrm.owner = srcId;

        if( psaSIM_VerifyPIN() < 0 )   /* check PIN2 card */
        {
          TRACE_EVENT( "FATAL RETURN psaSIM in +CLCK" );
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
          return( AT_FAIL );
        }

        break;

      /*
       *---------------------------------------------------------------
       * ME Personalisation
       *---------------------------------------------------------------
       */
  #ifdef SIM_PERS
      case CLCK_FAC_Pn:
      case CLCK_FAC_Pu:
      case CLCK_FAC_Pp:
      case CLCK_FAC_Pc:
      case CLCK_FAC_Ps:
      case CLCK_FAC_Pf:
                
        switch (fac)
        {
          case CLCK_FAC_Pn: slocktype = SIMLOCK_NETWORK;          break;
          case CLCK_FAC_Pu: slocktype = SIMLOCK_NETWORK_SUBSET;   break;
          case CLCK_FAC_Pp: slocktype = SIMLOCK_SERVICE_PROVIDER; break;
          case CLCK_FAC_Pc: slocktype = SIMLOCK_CORPORATE;        break;
          case CLCK_FAC_Ps: slocktype = SIMLOCK_SIM;              break;
          case CLCK_FAC_Pf: slocktype = SIMLOCK_FIRST_SIM;        break;
          default: slocktype = SIMLOCK_NETWORK;
        }

       /* 
        * Check whether sim is inserted or not before trying to lock/Unlock 
        */
       
       if(simShrdPrm.SIMStat EQ SS_OK) 
        {
          rlockstatus = (mode EQ CLCK_MOD_Lock)?
          aci_slock_lock(slocktype, passwd):
          aci_slock_unlock(slocktype, passwd);
       }
      else 
       {
          /*
           * Sim is not present: unlocking is allowed if No_SIM_Unlock flag is OFF
          */
         aci_slock_set_CFG();
         if(cfg_data EQ NULL)
         {
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_Unknown);    
           return( AT_FAIL );
         }
         if( (mode EQ CLCK_MOD_Unlock) AND !(cfg_data->Flags & SEC_DRV_HDR_FLAG_No_SIM_Unlock))
         {
            MFREE(cfg_data);
            rlockstatus = aci_slock_unlock(slocktype, passwd);        
         }
        else
        {
           MFREE(cfg_data);
           ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_SimNotIns);    
           return( AT_FAIL );
        }
      }
      cmdBuf = AT_CMD_CLCK ; 
      if ( ( (mode EQ CLCK_MOD_Lock) AND (rlockstatus EQ SIMLOCK_ENABLED) ) OR
              ( (mode EQ CLCK_MOD_Unlock) AND (rlockstatus EQ SIMLOCK_DISABLED) ) )
        {
            return (AT_CMPL);
        }
        else
        {
          if (rlockstatus EQ SIMLOCK_BLOCKED) /* Special error description on blocked personalisation */
           {
               aci_slock_set_CFG();
	        if(cfg_data EQ NULL)
                {
                  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_Unknown);    
                  return( AT_FAIL );
                }
               aci_set_cme_error(slocktype);
               MFREE(cfg_data);
           }
          else if(rlockstatus EQ SIMLOCK_WAIT)
            {
               simEntStat.curCmd = AT_CMD_CLCK;
               simEntStat.entOwn = simShrdPrm.owner = srcId;
              AciSLockShrd.check_lock = SIMLOCK_CHECK_LOCK;
              AciSLockShrd.lock_type = slocktype;
              AciSLockShrd.lock_passwd = passwd;
              
              return( AT_EXCT);
            }
           else 
            {
              err_code =CME_ERR_WrongPasswd; 
              ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );
            }
          
            return( AT_FAIL );
        }

/*
       *---------------------------------------------------------------
       * FC RESET Handling
       Added on 11/03/2005
       *---------------------------------------------------------------
*/
     case CLCK_FAC_Fc:
      fcResetStat=aci_slock_reset_fc(passwd);
      simEntStat.curCmd     = AT_CMD_CLCK;     
      if (fcResetStat EQ OPER_SUCCESS)
      {
             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();
             AciSLockShrd.check_lock = SIMLOCK_CHECK_RESET_FC;           
             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);
                         
             }
            
            
      }
      else if (fcResetStat EQ OPER_FAIL)
      {
         cmdBuf = simEntStat.curCmd;
         simEntStat.curCmd = AT_CMD_NONE;
         err_code =CME_ERR_WrongPasswd;
         R_AT( RAT_CME, simEntStat.entOwn )
         ( cmdBuf, err_code );
         cmh_logRslt ( simEntStat.entOwn, RAT_CME, cmdBuf, -1, -1, err_code );
         return( AT_FAIL );
      }
      
    case CLCK_FAC_Fcm:
           fcResetStat=aci_slock_reset_fc(passwd);
      if (fcResetStat EQ OPER_SUCCESS)
      {
        TRACE_FUNCTION(" AT_CMPL");
        return( AT_CMPL );
      }
      else 
      {
        TRACE_FUNCTION(" AT_FAIL");
        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );
        return( AT_FAIL );
      }
#endif  //SIM_PERS
      /*
       *---------------------------------------------------------------
       * Error handling
       *---------------------------------------------------------------
       */
      default:
        ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_Unknown );
        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_CLCK;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = (ssCd EQ NOT_PRESENT_8BIT)?
                                   ACI_NumParmNotPresent:/*lint -e(644)*/sId1+1;
  cmdLog.cmdPrm.sCLCK.srcId   = srcId;
  cmdLog.cmdPrm.sCLCK.fac     = fac;
  cmdLog.cmdPrm.sCLCK.mode    = mode;
  cmdLog.cmdPrm.sCLCK.passwd  = passwd;
  cmdLog.cmdPrm.sCLCK.class_type = class_type;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( AT_EXCT );
}

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

  PURPOSE : This is the functional counterpart to the +CPWD AT command
            which is responsible to change the password for call
            barring supplementary services.

            <fac>    : CB facility.
            <oldpwd> : current password.
            <newpwd> : new password.
*/

GLOBAL T_ACI_RETURN sAT_PlusCPWD  ( T_ACI_CMD_SRC srcId,
                                    T_ACI_CPWD_FAC fac,
                                    CHAR  *        oldpwd,
                                    CHAR  *        newpwd)
{
  T_ACI_RETURN retCd = AT_FAIL;   /* holds return code */
  UBYTE ssCd;                     /* holds ss code */
  SHORT sId;                      /* holds service id */
#ifdef SIM_PERS
   T_SIMLOCK_TYPE slocktype;
   T_OPER_RET_STATUS status;
#endif
  TRACE_FUNCTION ("sAT_PlusCPWD");

/*
 *-------------------------------------------------------------------
 * check password parameter
 *-------------------------------------------------------------------
 */
  if( !newpwd OR !oldpwd )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check parameter <fac>
 *-------------------------------------------------------------------
 */
  switch( fac )
  {
    /* All Baring Services share the same password so only SS_CD_ALL_CBSS is valid,
       everything else will be rejected by the network! */
    case( CPWD_FAC_Ao ):
    case( CPWD_FAC_Oi ):
    case( CPWD_FAC_Ox ):
    case( CPWD_FAC_Ai ):
    case( CPWD_FAC_Ir ):
    case( CPWD_FAC_Ab ):
    case( CPWD_FAC_Ag ):
    case( CPWD_FAC_Ac ): ssCd = SS_CD_ALL_CBSS;   break;

    case( CPWD_FAC_Sc ):
    case( CPWD_FAC_P2 ):
#ifdef SIM_PERS
    case( CPWD_FAC_Pn ):
    case( CPWD_FAC_Pu ):
    case( CPWD_FAC_Pc ):
    case( CPWD_FAC_Pp ):
    case( CPWD_FAC_Pf ):
    case( CPWD_FAC_Ps ):
#endif
                                        ssCd = NOT_PRESENT_8BIT; break;


    case( CPWD_FAC_NotPresent  ):
    default:

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

/*
 *-------------------------------------------------------------------
 * if password relates to SS
 *-------------------------------------------------------------------
 */
  if( ssCd NEQ NOT_PRESENT_8BIT )
  {
  /*
   *-------------------------------------------------------------------
   * check parameter <oldpwd>
   *-------------------------------------------------------------------
   */
    if( strlen( newpwd ) > MAX_PWD_NUM OR
        strlen( oldpwd ) > MAX_PWD_NUM    )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL );
    }

  /*
   *-----------------------------------------------------------------
   * get a new service table entry to interrogate SS
   *-----------------------------------------------------------------
   */
    sId = psaSS_stbNewEntry();

    if( sId EQ NO_ENTRY )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
      return( AT_FAIL );
    }

  /*
   *-----------------------------------------------------------------
   * set up  facility information element
   *-----------------------------------------------------------------
   */
    CCD_START;

    psaSS_asmRegisterPWD( ssCd );
  /*
   *---------------------------------------------------------------
   * declare service table entry as used and the owner of the service
   *---------------------------------------------------------------
   */
    ssShrdPrm.stb[sId].ntryUsdFlg = TRUE;
    ssShrdPrm.stb[sId].ssCode     = ssCd;
    ssShrdPrm.stb[sId].srvOwn     = srcId;

  /*
   *-----------------------------------------------------------------
   * start a new transaction
   *-----------------------------------------------------------------
   */
    ssShrdPrm.stb[sId].curCmd = AT_CMD_CPWD;
    psaSS_NewTrns(sId);

    CCD_END;

  /*
   *-----------------------------------------------------------------
   * store passwords for later use
   *-----------------------------------------------------------------
   */
    strncpy
    (
      (char *) cmhPrm[srcId].ssCmdPrm.CXXXpwd,
      (char *) oldpwd,
      MAX_PWD_NUM
    );
    cmhPrm[srcId].ssCmdPrm.CXXXpwd[MAX_PWD_NUM] = '\0';

    strncpy
    (
      (char *) cmhPrm[srcId].ssCmdPrm.CXXXnewPwd,
      (char *) newpwd,
      MAX_PWD_NUM
    );
    cmhPrm[srcId].ssCmdPrm.CXXXnewPwd[MAX_PWD_NUM] = '\0';

    strncpy
    (
      (char *) cmhPrm[srcId].ssCmdPrm.CXXXnewPwd2,
      (char *) newpwd,
      MAX_PWD_NUM
    );
    cmhPrm[srcId].ssCmdPrm.CXXXnewPwd2[MAX_PWD_NUM] = '\0';
    retCd = AT_EXCT;
  }
  else
  {
    /*
     *-------------------------------------------------------------------
     * if password relates to SIM
     *-------------------------------------------------------------------
     */
    switch (fac)
    {
      /*
       *---------------------------------------------------------------
       * change PIN 1 / PIN 2
       *---------------------------------------------------------------
       */
      case( CPWD_FAC_Sc ):
      case( CPWD_FAC_P2 ):
        if( simEntStat.curCmd NEQ AT_CMD_NONE )
          return( AT_BUSY );

        if( strlen( newpwd ) > PIN_LEN     OR
            strlen( newpwd ) < MIN_PIN_LEN OR
            strlen( oldpwd ) > PIN_LEN     OR
            strlen( oldpwd ) < MIN_PIN_LEN    )
        {
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
          return( AT_FAIL );
        }

        if( simEntStat.curCmd NEQ AT_CMD_NONE )
          return( AT_BUSY );

        cmhSIM_FillInPIN ( oldpwd, simShrdPrm.setPrm[srcId].curPIN, PIN_LEN );
        cmhSIM_FillInPIN ( newpwd, simShrdPrm.setPrm[srcId].newPIN, PIN_LEN );

        simShrdPrm.setPrm[srcId].PINType = (fac EQ CPWD_FAC_Sc)?
                                   PHASE_2_PIN_1:PHASE_2_PIN_2;

        simEntStat.curCmd     = AT_CMD_CPWD;
        simEntStat.entOwn     = simShrdPrm.owner = srcId;

        if( psaSIM_ChangePIN() < 0 )  /* change PIN */
        {
          TRACE_EVENT( "FATAL RETURN psaSIM in +CPWD" );
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
          return( AT_FAIL );
        }
        retCd = AT_EXCT;
        break;

#ifdef SIM_PERS
      case( CPWD_FAC_Pn ):
      case( CPWD_FAC_Pu ):
      case( CPWD_FAC_Pc ):
      case( CPWD_FAC_Pp ):
      case( CPWD_FAC_Pf ):
      case( CPWD_FAC_Ps ):
      {
        T_SIMLOCK_TYPE slocktype;
        T_SIMLOCK_STATUS status;

        switch (fac)
        {
          case CLCK_FAC_Pn: slocktype = SIMLOCK_NETWORK;          break;
          case CLCK_FAC_Pu: slocktype = SIMLOCK_NETWORK_SUBSET;   break;
          case CLCK_FAC_Pp: slocktype = SIMLOCK_SERVICE_PROVIDER; break;
          case CLCK_FAC_Pc: slocktype = SIMLOCK_CORPORATE;        break;
          case CLCK_FAC_Ps: slocktype = SIMLOCK_SIM;              break;
          case CLCK_FAC_Pf: slocktype = SIMLOCK_FIRST_SIM;        break;
          default: slocktype = SIMLOCK_NETWORK;                   break;
        }

        status = aci_slock_change_password( slocktype, oldpwd, newpwd );
        if (status EQ OPER_SUCCESS)
          return(AT_CMPL);
        else if(status EQ OPER_FAIL )
        {
          ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_WrongPasswd );
          return( AT_FAIL );
        }
        else if (status EQ SIMLOCK_BLOCKED)
        {
          switch (fac)
          {
            case CLCK_FAC_Pn: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NetworkPersPukReq ); break;
            case CLCK_FAC_Pu: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NetworkSubsetPersPukReq ); break;
            case CLCK_FAC_Pp: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_ProviderPersPukReq ); break;
            case CLCK_FAC_Pc: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_CorporatePersPukReq ); break;
            case CLCK_FAC_Ps: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_PhoneFail ); break;
            case CLCK_FAC_Pf: ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_PhFSimPukReq ); break;
          }
          return( AT_FAIL );
        }
      }
      retCd = AT_CMPL;
      break;
#endif
    }
  }

/*
 *-------------------------------------------------------------------
 * 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_CPWD;
    cmdLog.cmdType              = CLOG_TYPE_Set;
    cmdLog.retCode              = retCd;
    cmdLog.cId                  = ACI_NumParmNotPresent;
    cmdLog.sId                  = (ssCd EQ NOT_PRESENT_8BIT)?
                                     ACI_NumParmNotPresent:/*lint -e(644)*/sId+1;
    cmdLog.cmdPrm.sCPWD.srcId   = srcId;
    cmdLog.cmdPrm.sCPWD.fac     = fac;
    cmdLog.cmdPrm.sCPWD.oldpwd  = oldpwd;
    cmdLog.cmdPrm.sCPWD.newpwd  = newpwd;
  
    rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( retCd );
}

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

  PURPOSE : This is the functional counterpart to the +CCWA AT command
            which is responsible to set the parameters for call
            waiting supplementary services.

            <mode>   : CW mode.
            <class_type>: class of call.
*/

GLOBAL T_ACI_RETURN sAT_PlusCCWA  ( T_ACI_CMD_SRC     srcId,
                                    T_ACI_CCWA_MOD    mode,
                                    T_ACI_CLASS       class_type)
{
  SHORT sId1, sId2;         /* holds service id */
  UBYTE bst1, bst2;         /* holds basic service type */
  UBYTE bs1,  bs2;          /* holds basic service */
  BOOL  mltyTrnFlg = FALSE; /* flags for multi transaction */

   T_ACI_RETURN   retVal;
 
  TRACE_FUNCTION ("sAT_PlusCCWA ()");

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

  if( cmhPrm[srcId].ssCmdPrm.mltyTrnFlg NEQ 0 )

    return( AT_BUSY );

/*
 *-------------------------------------------------------------------
 * check parameter <class>
 *-------------------------------------------------------------------
 */
  if( !cmhSS_CheckClass( class_type, &bs1, &bst1, &bs2, &bst2, &mltyTrnFlg ))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/* SIM TOOLKIT & FDN HANDLING */
  if (mode NEQ CCWA_MOD_NotInterrogate)  /* mode should be valid */
  {
    retVal = cmhSS_CW_SAT_Handle( srcId, mode, class_type);

    if( retVal NEQ AT_CMPL )
        return( retVal );
  }


/*
 *-------------------------------------------------------------------
 * get a new service table entry to interrogate SS
 *-------------------------------------------------------------------
 */
  sId1 = psaSS_stbNewEntry();

  if( sId1 EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
    return( AT_FAIL );
  }

  sId2 = NO_ENTRY;

  if( mltyTrnFlg )
  {
    ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;

    sId2 = psaSS_stbNewEntry();

    if( sId2 EQ NO_ENTRY )
    {
      ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
      return( AT_FAIL );
    }
  }

/*
 *-------------------------------------------------------------------
 * check parameter <mode>
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    /*
     *---------------------------------------------------------------
     * lock and unlock call barring service
     *---------------------------------------------------------------
     */
    case( CCWA_MOD_Disable ):
    case( CCWA_MOD_Enable  ):

      CCD_START;

      if( mode EQ CCWA_MOD_Disable )
        psaSS_asmDeactivateSS( SS_CD_CW, bst1, bs1 );

      else if( mode EQ CCWA_MOD_Enable )
        psaSS_asmActivateSS( SS_CD_CW, bst1, bs1 );

      ssShrdPrm.stb[sId1].ntryUsdFlg = TRUE;
      ssShrdPrm.stb[sId1].ssCode     = SS_CD_CW;
      ssShrdPrm.stb[sId1].srvOwn     = srcId;

      /* start first transaction */
      ssShrdPrm.stb[sId1].curCmd        = AT_CMD_CCWA;
      cmhSS_flagTrn( sId1, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
      psaSS_NewTrns(sId1);

      if( mltyTrnFlg )
      {
        if( mode EQ CCWA_MOD_Disable )
          psaSS_asmDeactivateSS( SS_CD_CW, bst2, bs2 );

        else if( mode EQ CCWA_MOD_Enable )
          psaSS_asmActivateSS( SS_CD_CW, bst2, bs2 );

        ssShrdPrm.stb[sId2].ntryUsdFlg = TRUE;
        ssShrdPrm.stb[sId2].ssCode     = SS_CD_CW;
        ssShrdPrm.stb[sId2].srvOwn     = srcId;

        /* start second transaction */
        ssShrdPrm.stb[sId2].curCmd = AT_CMD_CCWA;
        cmhSS_flagTrn( sId2, &(ssShrdPrm.mltyTrnFlg)); /* only for the second one */
        cmhSS_flagTrn( sId2, &(cmhPrm[srcId].ssCmdPrm.mltyTrnFlg));
        psaSS_NewTrns(sId2);
      }
      CCD_END;
      break;

    /*
     *---------------------------------------------------------------
     * unexpected mode
     *---------------------------------------------------------------
     */
    case( CCWA_MOD_NotInterrogate ):

      ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
      return( AT_CMPL );

    default:

      ssShrdPrm.stb[sId1].ntryUsdFlg = FALSE;
      if( sId2 NEQ NO_ENTRY ) ssShrdPrm.stb[sId2].ntryUsdFlg = FALSE;

      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
  {
  T_ACI_CLOG cmdLog;        /* holds logging info */

  cmdLog.atCmd                = AT_CMD_CCWA;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = sId1+1;
  cmdLog.cmdPrm.sCCWA.srcId   = srcId;
  cmdLog.cmdPrm.sCCWA.mode    = mode;
  cmdLog.cmdPrm.sCCWA.class_type = class_type;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( AT_EXCT );
}


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

  PURPOSE : This is the functional counterpart to the +CUSD AT command
            which is responsible to invoke an unstructured
            supplementary services.

            <str> : USSD string.
            <dcs> : data coding scheme.
*/
LOCAL T_ACI_RETURN ussd_call_control_by_sim(T_ACI_CMD_SRC    srcId,
                                            T_ACI_USSD_DATA *str,
                                            SHORT            dcs)
{
  T_ACI_RETURN retCd = AT_CMPL;   /* holds return code */

#ifdef SIM_TOOLKIT
  T_sat_ussd    SATussd; /* to hold USSD string in case of SAT Control */
  T_CLPTY_PRM   *sat_ss_cldPty;

  if(!psaSIM_ChkSIMSrvSup( SRV_CalCntrl ))   /* call control by SAT enabled */
  {
    return(AT_CMPL);
  }

  if (psaSIM_ChkSIMSrvSup(SRV_USSDsupportInCC))
  {
    SATussd.dcs        = (UBYTE)dcs;
    SATussd.c_ussd_str = str->len;
    SATussd.ussd_str   = str->data;

    retCd = cmhSAT_USSDCntrlBySIM( &SATussd, (UBYTE)srcId );
  }
  else       /* USSD structure not known by SAT */
  {
    MALLOC(sat_ss_cldPty, sizeof(T_CLPTY_PRM));
    cmhCC_init_cldPty( sat_ss_cldPty );

    if( !utl_cvtGsmIra ( str -> data,
                         str->len,
                         (UBYTE *)sat_ss_cldPty->num,
                         MAX_USSD_DATA,
                         CSCS_DIR_IraToGsm ) )
    {
      TRACE_EVENT("utl_cvtGsmIra( ) returned FALSE");
      MFREE(sat_ss_cldPty);
      return( AT_FAIL );
    }
    retCd = cmhSAT_SSCntrlBySIM( sat_ss_cldPty, (UBYTE)srcId );
    MFREE(sat_ss_cldPty);
  }
  return( retCd );
#else
  return( AT_CMPL);
#endif /* of SIM_TOOLKIT */
}

GLOBAL T_ACI_RETURN sAT_PlusCUSD  ( T_ACI_CMD_SRC    srcId,
                                    T_ACI_USSD_DATA *str,
                                    SHORT            dcs)
{
  SHORT sId;            /* holds service id */
  T_ACI_RETURN retCd = AT_CMPL;   /* holds return code */
  UBYTE ussdLen;
  UBYTE *ussdString;
  UBYTE src_len;

  TRACE_FUNCTION ("sAT_PlusCUSD ()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    TRACE_EVENT_P1("Wrong source: %d", srcId);
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check parameter str
 *-------------------------------------------------------------------
 */
  if( !str )
  {
    TRACE_EVENT("Empty string");
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check parameter dcs
 *-------------------------------------------------------------------
 */
  if( dcs EQ ACI_NumParmNotPresent )

    dcs = 0;

/*
 *-------------------------------------------------------------------
 * check if there is a USSD request pending
 *-------------------------------------------------------------------
 */
  sId = psaSS_stbFindUssdReq();

  if( sId EQ NO_ENTRY )
  {
    /* check if there is another service in progress */
    if( psaSS_stbFindActSrv( sId ) NEQ NO_ENTRY )
    {
      TRACE_EVENT("Parallel USSD Transaction not allowed");
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_ParallelUSSD );
      return( AT_FAIL );
    }

    /* get new service table entry */
    sId = psaSS_stbNewEntry();
    if( sId EQ NO_ENTRY )
    {
      TRACE_EVENT("Service table is full");
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
      return( AT_FAIL );
    }

    /* check ussd call control by sim */
    retCd = ussd_call_control_by_sim(srcId, str, dcs);
    if(retCd NEQ AT_CMPL)
    {
      TRACE_EVENT_P1("ussd_call_control_by_sim() returned with %d", retCd);

      return( retCd );
    }

    CCD_START;

    MALLOC(ussdString, MAX_USSD_STRING);

    if( utl_getAlphabetCb( (UBYTE)dcs ) EQ 0 ) /* 7bit alphabet */
    {
      src_len = (UBYTE)MINIMUM( MAX_USSD_STRING, str->len);
      ussdLen = utl_cvt8To7( str->data,
                             src_len,
                             ussdString, 0 );
      /* According to spec 23.038 section 6.1.2.3 for USSD packing, for bytes end with
       * (8*n)-1 i.e where n is 1,2,3....i.e byte 7, 15, 23 ... to be padded 
       * with carriage return <CR>(0xD) 
       */
      if ((src_len+1)%8 EQ 0)
      {
        ussdString[ussdLen-1] |= (0xD << 1);
      }
    }
    else
    {
      ussdLen = str->len;
      memcpy(ussdString, str->data, MAX_USSD_STRING);
    }

    psaSS_asmProcUSSDReq( (UBYTE)dcs, ussdString, ussdLen );

    MFREE(ussdString);

    /* start new transaction */
    ssShrdPrm.stb[sId].ntryUsdFlg = TRUE;
    ssShrdPrm.stb[sId].curCmd     = AT_CMD_CUSD;
    ssShrdPrm.stb[sId].srvOwn     = srcId;
    psaSS_NewTrns(sId);

    CCD_END;

    retCd = AT_CMPL;


  }
  else
  {
    CCD_START;

    psaSS_asmCnfUSSDReq( (UBYTE)dcs, str->data, str->len );

    ssShrdPrm.stb[sId].ussdReqFlg = FALSE;

    /* continue existing transaction */
    psaSS_CntTrns(sId);

    CCD_END;

    retCd = AT_CMPL;
  }

  ssShrdPrm.ussdLen = 0;

  /* save ussd string for possible version 1 retry */
  if( cmhSMS_getAlphabetCb( (UBYTE)dcs ) EQ 0 )
  {
    if( str->len <= MAX_USSD_STRING )
    {
      ssShrdPrm.ussdLen = str->len;
      memcpy( ssShrdPrm.ussdBuf, str->data, str->len );
    }
  }

/*
 *-------------------------------------------------------------------
 * 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_CUSD;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = retCd;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = sId+1;
  cmdLog.cmdPrm.sCUSD.srcId   = srcId;
  cmdLog.cmdPrm.sCUSD.dcs     = dcs;
  cmdLog.cmdPrm.sCUSD.str     = str;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( retCd );
}

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

  PURPOSE : This is the functional counterpart to the %CCBS AT command
            which is responsible to clear CCBS entries. Index value set
            to 0 indicates clear all entries.

            <idx>   : ccbs index
*/

GLOBAL T_ACI_RETURN sAT_PercentCCBS( T_ACI_CMD_SRC srcId,
                                     SHORT         idx  )
{
  SHORT sId;         /* holds service id */

  T_ACI_RETURN   retVal;
 
  TRACE_FUNCTION ("sAT_PercentCCBS ()");

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

/*
 *-------------------------------------------------------------------
 * check parameter idx
 *-------------------------------------------------------------------
 */
  if( idx EQ ACI_NumParmNotPresent OR idx > 5 OR idx < 0 )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/* SIM TOOLKIT & FDN HANDLING */
    retVal = cmhSS_CCBS_SAT_Handle( srcId, CCFC_MOD_Erasure, idx);

    if( retVal NEQ AT_CMPL )
        return( retVal );
  

/*
 *-------------------------------------------------------------------
 * get a new service table entry to interrogate SS
 *-------------------------------------------------------------------
 */
  sId = psaSS_stbNewEntry();

  if( sId EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_SrvTabFull );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * check parameter <mode>
 *-------------------------------------------------------------------
 */
  CCD_START;

  if( idx EQ 0 ) idx = KSD_IDX_NONE;

  psaSS_asmDeactivateCCBS((UBYTE)idx);

  ssShrdPrm.stb[sId].ntryUsdFlg = TRUE;
  ssShrdPrm.stb[sId].ssCode     = SS_CD_CCBS;
  ssShrdPrm.stb[sId].SSver      = SS_VERSION_3;

  ssShrdPrm.stb[sId].srvOwn     = srcId;

  ssShrdPrm.stb[sId].curCmd     = AT_CMD_CCBS;

  psaSS_NewTrns(sId);

  CCD_END;

/*
 *-------------------------------------------------------------------
 * 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_CCBS;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.cId                  = ACI_NumParmNotPresent;
  cmdLog.sId                  = sId+1;
  cmdLog.cmdPrm.sCCBS.srcId   = srcId;
  cmdLog.cmdPrm.sCCBS.idx     = idx;

  rAT_PercentCLOG( &cmdLog );
  }
#endif

  return( AT_EXCT );
}


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

  PURPOSE : This is the functional counterpart to the %CSCN AT command
            which is responsible to set the switches for debugging 
            mode at terminal interface.
*/
GLOBAL T_ACI_RETURN sAT_PercentCSCN ( T_ACI_CMD_SRC srcId,
                                   T_ACI_SS_CSCN_MOD_STATE     ss_switch,
                                   T_ACI_SS_CSCN_MOD_DIRECTION ss_direction,
                                   T_ACI_CC_CSCN_MOD_STATE     cc_switch,
                                   T_ACI_CC_CSCN_MOD_DIRECTION cc_direction )
{
  TRACE_FUNCTION ("sAT_PercentCSCN ()");

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

  if (ss_switch NEQ SS_CSCN_MOD_STATE_INVALID)
    cmhPrm[srcId].ssCmdPrm.CSCNss_mode.SsCSCNModeState     = ss_switch;

  if (ss_direction NEQ SS_CSCN_MOD_DIR_INVALID)
    cmhPrm[srcId].ssCmdPrm.CSCNss_mode.SsCSCNModeDirection = ss_direction;

  if (cc_switch NEQ CC_CSCN_MOD_STATE_INVALID)
    cmhPrm[srcId].ccCmdPrm.CSCNcc_mode.CcCSCNModeState     = cc_switch;

  if (cc_direction NEQ CC_CSCN_MOD_DIR_INVALID)
    cmhPrm[srcId].ccCmdPrm.CSCNcc_mode.CcCSCNModeDirection = cc_direction;

  return( AT_CMPL );
}

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

  PURPOSE : This is the functional counterpart to the %CUSDR AT command
            which is responsible for extended user/MMI response to n/w
            initaiated USSD.
*/
GLOBAL T_ACI_RETURN sAT_PercentCUSDR(T_ACI_CMD_SRC srcId, T_ACI_CUSDR_RES response)
{
  TRACE_FUNCTION ("sAT_PercentCUSDR()");

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

  if(cuscfgParams.Ext_USSD_Response EQ CUSCFG_STAT_Disabled)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  if(Ext_USSD_Res_Pending EQ CUSDR_EXT_USSD_RES_Not_Pending OR Ext_USSD_Res_Pending_sId EQ NOT_PRESENT_16BIT)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  switch(response)
  {
  case CUSDR_RES_Ok:
    if(Ext_USSD_Res_Pending NEQ CUSDR_EXT_USSD_RES_Request)
    {
      psaSS_asmEmptyRslt();
      psaSS_CntTrns(Ext_USSD_Res_Pending_sId);
    }
      Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Not_Pending;
      Ext_USSD_Res_Pending_sId = NOT_PRESENT_8BIT;
      return(AT_CMPL);

  case CUSDR_RES_Unknown_Alphabet:
    psaSS_asmErrorRslt( Ext_USSD_Res_Pending_sId, ERR_UNKNOWN_ALPHA );
    psaSS_CntTrns(Ext_USSD_Res_Pending_sId);
    ssShrdPrm.stb[Ext_USSD_Res_Pending_sId].ntryUsdFlg = FALSE;
    Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Not_Pending;
    Ext_USSD_Res_Pending_sId = NOT_PRESENT_8BIT;
    return(AT_CMPL);

  case CUSDR_RES_Busy:
    psaSS_asmErrorRslt( Ext_USSD_Res_Pending_sId, ERR_USSD_BUSY );
    psaSS_EndTrns(Ext_USSD_Res_Pending_sId);
    ssShrdPrm.stb[Ext_USSD_Res_Pending_sId].ntryUsdFlg = FALSE;
    Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Not_Pending;
    Ext_USSD_Res_Pending_sId = NOT_PRESENT_8BIT;
    return(AT_CMPL);

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

  }

}


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