view src/aci2/aci/cmh_sss.c @ 640:16eb1b9640dc

target gtm900 renamed to gtm900mgc2 This change reflects the fact that the build target in question supports MGC2GSMT hardware only, and will NOT work on other hw that confusing bears the same end user name of GTM900, neither the LoCosto-based GTM900-C nor the Calypso-based MG01GSMT that has a different and incompatible RFFE. If we ever get our hands on a piece of MG01GSMT hw and add support for it, that other target will be named gtm900mg01.
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 31 Jan 2020 00:46:07 +0000
parents 93999a60b835
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GSM-PS (6147)
|  Modul   :  CMH_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 ========================================================*/