view src/g23m-aci/aci/cmh_ssr.c @ 665:2795a11973b8

UART PS entity: added trace of line state changes
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 27 May 2020 22:46:55 +0000
parents 53929b40109c
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  Project :  GSM-PS (6147)
|  Modul   :  CMH_SSR
+----------------------------------------------------------------------------- 
|  Copyright 2002 Texas Instruments Berlin, AG 
|                 All rights reserved. 
| 
|                 This file is confidential and a trade secret of Texas 
|                 Instruments Berlin, AG 
|                 The receipt of or possession of this file does not convey 
|                 any rights to reproduce or disclose its contents or to 
|                 manufacture, use, or sell anything it may describe, in 
|                 whole, or in part, without the specific written consent of 
|                 Texas Instruments Berlin, AG. 
+----------------------------------------------------------------------------- 
|  Purpose :  This module defines the functions which are responsible
|             for the responses of the protocol stack adapter for
|             supplementary service.
+----------------------------------------------------------------------------- 
*/ 

#ifndef CMH_SSR_C
#define CMH_SSR_C
#endif

#include "aci_all.h"
/*==== INCLUDES ===================================================*/
#include "aci_cmh.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#include "aci_mem.h"

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

#include "ksd.h"
#include "aci.h"
#include "psa.h"
#include "psa_ss.h"
#include "psa_util.h"
#include "cmh.h"
#include "cmh_ss.h"

#include "psa_cc.h"
#ifdef SIM_TOOLKIT
#include "psa_sat.h"
#endif /* SIM_TOOLKIT */

#include "cmh_cc.h"

#ifdef FF_CPHS
#include "cphs.h"
#endif /* FF_CPHS */

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

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

/*==== PROTOTYPES =====================================================*/
/* Implements Measure 217 */
LOCAL void cmhSS_SSActDeact (SHORT sId, 
                             UBYTE opCd, 
                             T_ssInfo *ssInfo);
/* Implements Measure 215 */
LOCAL void cmhSS_SSRegistrated_Erased (SHORT sId,
                                       UBYTE opCd, 
                                       T_ssInfo *ssInfo);
/* Implements Measure 209, 210, 214 */
LOCAL void cmhSS_ksdCBCF_Res (SHORT sId,
                              T_ACI_KSIR  *ksStat,
                              T_ACI_KSD_CMD ksdCmd);
/* Implements Measure 76 */
LOCAL T_ACI_USSD_DATA* cmhSS_prepareUSSDRes(T_ussdArg *ussdArg, SHORT *dcs);
/* Used in Measure 217 */
LOCAL void cmhSS_processKSDCF (SHORT sId, UBYTE opCd, T_ssInfo *ssInfo);
/*==== VARIABLES ==================================================*/
EXTERN T_PCEER causeMod;
EXTERN SHORT causeCeer;

#define CF_LST_SIZE (sizeof(T_CF_FEAT)*MAX_CF_FEAT_NR)
#define CB_LST_SIZE (sizeof(T_CB_INFO)*MAX_CB_INFO_NR)
#define CW_LST_SIZE (sizeof(T_Cx_BSG) *MAX_CW_BSG_NR)
#define CC_LST_SIZE (sizeof(T_CC_FEAT)*MAX_CC_FEAT_NR)

#define MAX_LST_BUF (MAXIMUM(MAXIMUM(MAXIMUM(CF_LST_SIZE,CB_LST_SIZE),\
                                     CW_LST_SIZE),\
                             CC_LST_SIZE))

LOCAL ULONG ssLstBuf[MAX_LST_BUF/sizeof(ULONG)];
EXTERN T_ACI_CUSCFG_PARAMS cuscfgParams;
EXTERN SHORT Ext_USSD_Res_Pending_sId;
EXTERN T_CUSDR_EXT_USSD_RES Ext_USSD_Res_Pending;

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

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSResultFailure        |
+-------------------------------------------------------------------+

  PURPOSE : A result was received, that is corrupt.

*/

/* Check whether KSD returned with an error: TRUE if error, FALSE otherwise */
LOCAL BOOL check_ksd_error( T_OWN srcId, SHORT sId, T_ACI_KSIR * ksStat )
{
  UBYTE err = KSD_NO_ERROR;

  /* Check if this is a response generated by an error */
  switch ( ksStat -> ksdCmd )
  {
    case( KSD_CMD_CF ):
      err = ksStat->ir.rKSCF.ssErr;
      break;
    case( KSD_CMD_CW ):
      err = ksStat->ir.rKSCW.ssErr;
      break;
    case( KSD_CMD_CB ):
      err = ksStat->ir.rKSCB.ssErr;
      break;
    case( KSD_CMD_CL ):
      err = ksStat->ir.rKSCL.ssErr;
      break;
    case( KSD_CMD_PWD ):
      err = ksStat->ir.rKSPW.ssErr;
      break;
    case( KSD_CMD_USSD ):
      err = ksStat->ir.rKSUS.ssErr;
      break;

  }
  if( err NEQ KSD_NO_ERROR AND
      srcId NEQ ((T_OWN)CMD_SRC_LCL) )  /* MFW has its own implementation regarding errors in KSD */
  {
    TRACE_EVENT_P1( "SS error. Code error: %d", err);

    return(TRUE);
  }
  return(FALSE);
}

GLOBAL void cmhSS_SSResultFailure( SHORT sId )
{
  T_ACI_KSIR ksStat;      /* holds KS status */
  T_OWN      owner   = ssShrdPrm.stb[sId].srvOwn;
  T_ACI_AT_CMD      cmdBuf  = ssShrdPrm.stb[sId].curCmd;

  TRACE_FUNCTION ("cmhSS_SSResultFailure()");

  switch( cmdBuf )
  {
    case( AT_CMD_NONE ): break;
      /*lint -e{408} */ 
    case( KSD_CMD_CF ):
      /*lint -e{408} */
    case( KSD_CMD_CW ):
      /*lint -e{408} */
    case( KSD_CMD_CB ):
      /*lint -e{408} */
    case( KSD_CMD_CL ):
      /*lint -e{408} */
    case( KSD_CMD_PWD ):
      /*lint -e{408} */     
    case( KSD_CMD_USSD ):
      

      memset( &ksStat, 0, sizeof(ksStat));

      cmhSS_ksdBuildErrRslt( sId, &ksStat, KSD_NO_ERROR );

      if(!check_ksd_error( owner, sId, &ksStat ))
      {
          /*
          ** CQ12314 : NDH : 23/9/2003
          ** Added srcID field to ksStat to enable called entity to determine the originator of the command
          ** and take appropriate action.  (eg to Activate Call Forwarding Icon)
          */
          ksStat.srcId = (T_ACI_CMD_SRC)owner;
        
        #if defined (MFW)
          if (ksStat.srcId NEQ CMD_SRC_LCL)
          {
            R_AT( RAT_KSIR, CMD_SRC_LCL)( &ksStat );
          }
        #endif
        
        R_AT( RAT_KSIR, (T_ACI_CMD_SRC)owner )
          ( &ksStat );
      }

      /* NO BREAK HERE... Continue... */
      
       /*lint -fallthrough */       
    default:

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      if (owner > ((T_OWN)CMD_SRC_NONE) AND owner < OWN_SRC_MAX) /* Just to remove LINT warning */
      {
        cmhPrm[owner].ssCmdPrm.mltyTrnFlg = 0;
      }

      R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )
        ((T_ACI_AT_CMD)cmdBuf, CME_ERR_NotPresent );
      cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_CME,(T_ACI_AT_CMD)cmdBuf, -1, 
	  	                   BS_SPEED_NotPresent, CME_ERR_NotPresent );
  }

  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_CLIP_Interrogated      |
+-------------------------------------------------------------------+

  PURPOSE : Interrogation result is available.

*/

/* process result for +CLIP command */
LOCAL void cmhSS_CLIP_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_CLIP_STAT clip_status;
  
  TRACE_FUNCTION ("cmhSS_CLIP_Interrogated()");

  if( ! irgtSS->interrogateSSRes.v_ssStatus )
  {
    clip_status = CLIP_STAT_Unknown;    /* if no status is present */
  }
  else if( irgtSS->interrogateSSRes.ssStatus & SSS_P )
  {
    clip_status = CLIP_STAT_Prov;       /* if service is provisioned */
  }
  else
  {
    clip_status = CLIP_STAT_NotProv;    /* else service is not provisioned */
  }

  R_AT( RAT_CLIP, (T_ACI_CMD_SRC)owner )
    ( clip_status, NULL, NULL, MNCC_PRES_NOT_PRES, NULL, NULL, NULL );

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSInterrogated         |
+-------------------------------------------------------------------+

  PURPOSE : Interrogation result is available.
  Process result for +CDIP command
*/
LOCAL void cmhSS_CDIP_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
   TRACE_FUNCTION ("cmhSS_CDIP_Interrogated()");

 /* Following code of part is not using so it is commented but might be used in future 
   *  so it is not removed -Rachna 
   */ 

  /* 
    *  T_ACI_CDIP_STAT CDIP_status;
    * 
    * TRACE_FUNCTION ("cmhSS_CDIP_Interrogated()");
    *
    *if( ! irgtSS->interrogateSSRes.v_ssStatus )
    *{
    *CDIP_status = CDIP_STAT_Unknown;    / * if no status is present * /
    *}
    *else if( irgtSS->interrogateSSRes.ssStatus & SSS_P )
    *{
    *CDIP_status = CDIP_STAT_Prov;       / * if service is provisioned * /	
    *}
    *else
    *{
    *CDIP_status = CDIP_STAT_NotProv;    / * else service is not provisioned * /
    *}
    */
   R_AT( RAT_CDIP, (T_ACI_CMD_SRC)owner )
    ( NULL, NULL, NULL, NULL );

}

/* process result for +CLIR command */
LOCAL void cmhSS_CLIR_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_CC_CMD_PRM    *pCCCmdPrm;   /* points to CC command parameters */
  T_ACI_CLIR_STAT clir_status;
  T_OWN           owner;

  TRACE_FUNCTION ("cmhSS_CLIR_Interrogated()");

  owner = ssShrdPrm.stb[sId].srvOwn;
  pCCCmdPrm = &cmhPrm[owner].ccCmdPrm;

  if( irgtSS->interrogateSSRes.v_ssStatus )   /* if status is present */
  {
    if( irgtSS->interrogateSSRes.ssStatus & SSS_P )     /* if service is provisioned */
    {
      clir_status = CLIR_STAT_Permanent;
    }
    else                                                /* else service is not provisioned */
    {
      clir_status = CLIR_STAT_NotProv;
    }
  }
  else if( ! irgtSS->interrogateSSRes.v_cliRestrictionInfo          OR
           ! irgtSS->interrogateSSRes.cliRestrictionInfo.v_ssStatus )    /* if no status is present */
  {
    clir_status = CLIR_STAT_Unknown;
  }
  else if( irgtSS->interrogateSSRes.cliRestrictionInfo.ssStatus & SSS_P )  /* if service is provisioned */
  {
    /* check the restriction info */
    if( irgtSS->interrogateSSRes.cliRestrictionInfo.v_cliRestrictionOption )
    {
      switch( irgtSS->
                interrogateSSRes.cliRestrictionInfo.cliRestrictionOption )
      {
      case( CLIR_OPT_PERMANENT ):
        clir_status = CLIR_STAT_Permanent;
        break;
        
      case( CLIR_OPT_TEMPORARY ):
        clir_status = CLIR_STAT_RestrictTemp;
        break;
        
      case( CLIR_OPT_ALLOWED ):
        clir_status = CLIR_STAT_AllowTemp;
        break;
        
      default:
        clir_status = CLIR_STAT_Unknown;
      }
    }
    /* else no restriction info present */
    else
    {
      clir_status = CLIR_STAT_Unknown;
    }
  }
  else                                                                     /* else service is not provisioned */
  {
    clir_status = CLIR_STAT_NotProv;
  }

  /* sends indication to user */
  R_AT( RAT_CLIR, (T_ACI_CMD_SRC)owner )
        ( pCCCmdPrm -> CLIRmode, clir_status );
}


/* process result for +COLP command */
LOCAL void cmhSS_COLP_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_COLP_STAT colp_status;
  
  TRACE_FUNCTION ("cmhSS_COLP_Interrogated()");

  if( ! irgtSS->interrogateSSRes.v_ssStatus )             /* if no status is present */
  {
    colp_status = COLP_STAT_Unknown;
  }
  else if( irgtSS->interrogateSSRes.ssStatus & SSS_P )    /* if service is provisioned */
  {
    colp_status = COLP_STAT_Prov;
  }
  else                                                    /* else service is not provisioned */
  {
    colp_status = COLP_STAT_NotProv;
  }

  R_AT( RAT_COLP,(T_ACI_CMD_SRC)owner )
    ( colp_status, NULL, NULL, NULL, NULL, NULL );
}

/* process result for +COLR command */
LOCAL void cmhSS_COLR_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_COLR_STAT colr_status;
  
  TRACE_FUNCTION ("cmhSS_COLR_Interrogated()");

  if( ! irgtSS->interrogateSSRes.v_ssStatus )             /* if no status is present */
  {
    colr_status = COLR_STAT_Unknown;
  }
  else if( irgtSS->interrogateSSRes.ssStatus & SSS_P )    /* if service is provisioned */
  {
    colr_status = COLR_STAT_Prov;
  }
  else                                                    /* else service is not provisioned */
  {
    colr_status = COLR_STAT_NotProv;
  }

  R_AT( RAT_COLR, (T_ACI_CMD_SRC)owner )
    ( colr_status );
}


LOCAL void cmhSS_CLCK_CCWA_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS, T_ACI_AT_CMD cmdBuf )
{
  T_ACI_CLSSTAT   srvStat;     /* holds service status */
  USHORT          queried_classes = ssShrdPrm.stb[sId].ClassType; /* classes queried by the user */
  T_OWN           owner           = ssShrdPrm.stb[sId].srvOwn;
  
  srvStat.status     = STATUS_NotPresent; /* Lint */
  srvStat.class_type = CLASS_NotPresent;  /* Lint */

  srvStat.class_type = CLASS_NotPresent;

/* if status is present, service is provisioned but not active for
  any basic service type ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    srvStat.status = (irgtSS->interrogateSSRes.ssStatus & SSS_A)? 
              STATUS_Active : STATUS_NotActive;
    if ( cmdBuf EQ AT_CMD_CLCK )
      srvStat.class_type = CLASS_VceDatFaxSms;
    else
      srvStat.class_type = CLASS_VceDatFax;
  }
  
  /* if BS group list is present, the service is active for the
  containing BS/TS ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  else if( irgtSS->interrogateSSRes.v_basicServiceGroupList )
  {
    /* no basic services present */
    if( irgtSS->interrogateSSRes.basicServiceGroupList.c_basicServiceGroupList_value EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO BASIC SERVICES IN BASIC SERVICE LIST");
    }
    
    /* basic service list present */
    else
    {
      srvStat.status = STATUS_Active;
      srvStat.class_type =
        cmhSS_GetClassLst( &irgtSS->interrogateSSRes.basicServiceGroupList );

      TRACE_EVENT_P1("srvStat.class_type: %d",srvStat.class_type);
    }
  }

  /* filter answer before sending message */
  /* addition here because class values follow recommendation where each
  class is bit represented */

  TRACE_EVENT_P1("userClass: %d", queried_classes);

  if( (srvStat.class_type & queried_classes) EQ 0 )
  {
    /* means classes queried by user are not active !! */
    srvStat.status = STATUS_NotActive;
    srvStat.class_type = (T_ACI_CLASS)queried_classes;
  }
  else
  {
    srvStat.class_type = (T_ACI_CLASS)(srvStat.class_type &((T_ACI_CLASS)queried_classes));
  }

  switch( cmdBuf)
  {
  case( AT_CMD_CCWA ):
    R_AT( RAT_CCWA, (T_ACI_CMD_SRC)owner )
      ( &srvStat, NULL, NULL, MNCC_PRES_NOT_PRES, CLASS_NotPresent, NULL );
    break;
    
  case( AT_CMD_CLCK ):
    R_AT( RAT_CLCK, (T_ACI_CMD_SRC)owner )
      ( &srvStat );
    break;
  }
}

/* process result for +CLCK command */
LOCAL void cmhSS_CLCK_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  TRACE_FUNCTION ("cmhSS_CLCK_Interrogated()");

  cmhSS_CLCK_CCWA_Interrogated( sId, irgtSS, AT_CMD_CLCK );
}

/* process result for +CCWA command */
LOCAL void cmhSS_CCWA_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  TRACE_FUNCTION ("cmhSS_CCWA_Interrogated()");

  cmhSS_CLCK_CCWA_Interrogated( sId, irgtSS, AT_CMD_CCWA );
}

/* process result for +CCFC command */
LOCAL void cmhSS_CCFC_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_CCFC_SET  ccfcStat;    /* holds CCFC service status */
  UBYTE           idx;         /* holds list index */
  UBYTE           active_class_list = 0; /* list of active classes */
  USHORT          queried_classes = ssShrdPrm.stb[sId].ClassType; /* classes queried by the user */
  T_OWN           owner           = ssShrdPrm.stb[sId].srvOwn;

  TRACE_FUNCTION ("cmhSS_CCFC_Interrogated()");

  /* if status is present, service is provisioned but not active for
  any basic service type ref.GSM 04.82/x.6/Ver.5.0.0 */
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    ccfcStat.clsstat.status = (irgtSS->interrogateSSRes.ssStatus & SSS_A)?
           STATUS_Active:STATUS_NotActive;
    ccfcStat.number[0]  = 0x0;
    ccfcStat.type.npi   = NPI_NotPresent;
    ccfcStat.type.ton   = TON_NotPresent;
    ccfcStat.subaddr[0] = 0x0;
    ccfcStat.satype.tos = TOS_NotPresent;
    ccfcStat.satype.oe  = OE_NotPresent;
    ccfcStat.time       = ACI_NumParmNotPresent;

    ccfcStat.clsstat.class_type = (T_ACI_CLASS)(CLASS_VceDatFax & ((T_ACI_CLASS)queried_classes));

    R_AT( RAT_CCFC, (T_ACI_CMD_SRC)owner )
      ( &ccfcStat );

    return;

  }
  
  /* if forwarding feature list is present, decode the forwarding
  information */
  else if( irgtSS->interrogateSSRes.v_forwardingFeatureList )
  {
    /* no forwarding features present */
    if( irgtSS->interrogateSSRes.forwardingFeatureList.c_ff EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO BASIC SERVICES IN BASIC SERVICE LIST");
    }
    
    /* fowarding feature list present */
    else
    {
      for( idx=0;
      idx < irgtSS->interrogateSSRes.forwardingFeatureList.c_ff;
      idx++ )
      {
        ccfcStat.clsstat.class_type =
            cmhSS_GetClass( &irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
                              basicService );

        if( !irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].v_ssStatus )
        {
          ccfcStat.clsstat.status  = STATUS_NotPresent;
        }
        else if( irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].ssStatus
          & SSS_A )
        {
          ccfcStat.clsstat.status  = STATUS_Active;
        }
        else
        {
          ccfcStat.clsstat.status  = STATUS_NotActive;
        }
        
        if( irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          v_forwardedToNumber AND
          irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          forwardedToNumber.c_bcdDigit )
        {
          utl_BCD2DialStr
            (irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
            forwardedToNumber.bcdDigit,
            ccfcStat.number,
            irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
            forwardedToNumber.c_bcdDigit);
          
          ccfcStat.type.npi = (T_ACI_TOA_NPI)irgtSS->interrogateSSRes.forwardingFeatureList.
            ff[idx].forwardedToNumber.npi;
          ccfcStat.type.ton = (T_ACI_TOA_TON)irgtSS->interrogateSSRes.forwardingFeatureList.
            ff[idx].forwardedToNumber.noa;
        }
        else
        {
          ccfcStat.number[0]  = 0x0;
          ccfcStat.type.npi   = NPI_NotPresent;
          ccfcStat.type.ton   = TON_NotPresent;
        }
        
        if( irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          v_forwardedToSubaddress AND
          irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          forwardedToSubaddress.c_subadr_str)
        {
          utl_BCD2DialStr
            (irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
            forwardedToSubaddress.subadr_str,
            ccfcStat.subaddr,
            irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
            forwardedToSubaddress.c_subadr_str);
          
          ccfcStat.satype.tos = (T_ACI_TOS_TOS)irgtSS->interrogateSSRes.
            forwardingFeatureList.ff[idx].
            forwardedToSubaddress.tos;
          ccfcStat.satype.oe  = (T_ACI_TOS_OE)irgtSS->interrogateSSRes.
            forwardingFeatureList.ff[idx].
            forwardedToSubaddress.oei;
        }
        else
        {
          ccfcStat.subaddr[0] = 0x0;
          ccfcStat.satype.tos = TOS_NotPresent;
          ccfcStat.satype.oe  = OE_NotPresent;
        }
        
        if( irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          v_noReplyConditionTime)
          ccfcStat.time = irgtSS->interrogateSSRes.forwardingFeatureList.ff[idx].
          noReplyConditionTime;
        else
          ccfcStat.time = ACI_NumParmNotPresent;

        TRACE_EVENT_P1("network class: %d", ccfcStat.clsstat.class_type);
        TRACE_EVENT_P1("userClass: %d", queried_classes);
        TRACE_EVENT_P1("status: %d", ccfcStat.clsstat.status);
        
        if( ccfcStat.clsstat.status EQ STATUS_Active )
        {
          active_class_list += ccfcStat.clsstat.class_type;
          
          if( (ccfcStat.clsstat.class_type & queried_classes) NEQ 0 )
          /* filter what the user has queried */
          {
            R_AT( RAT_CCFC,(T_ACI_CMD_SRC)owner )
              ( &ccfcStat );
          }
        }
      }

      if( (active_class_list EQ 0)   /* means there are no active classes */
        OR
          ((active_class_list & queried_classes) EQ 0) /* means user querried unactive classes */ )
      {
        ccfcStat.clsstat.class_type = (T_ACI_CLASS)(CLASS_VceDatFax & (T_ACI_CLASS)queried_classes);
        ccfcStat.clsstat.status  = STATUS_NotActive;

        R_AT( RAT_CCFC, (T_ACI_CMD_SRC)owner )
          ( &ccfcStat );
      }
    }
  }
}

/* process result for %CCBS command */
LOCAL void cmhSS_CCBS_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_CCBS_STAT ccbsStat;    /* holds CCBS service status */
  UBYTE           idx;         /* holds list index */
  T_ACI_CCBS_SET  ccbsSet;     /* holds CCBS service status */

  TRACE_FUNCTION ("cmhSS_CCBS_Interrogated()");

  /* if present, decode the CCBS information */
  if( irgtSS->interrogateSSRes.v_cliRestrictionInfo )
  {
    if( !irgtSS->interrogateSSRes.cliRestrictionInfo.v_ssStatus )
      ccbsStat = CCBS_STAT_NotPresent;
    else
    {
      if(!(irgtSS->interrogateSSRes.cliRestrictionInfo.ssStatus
        & SSS_P))
        ccbsStat  = CCBS_STAT_NotProvisioned;
      else if( irgtSS->interrogateSSRes.cliRestrictionInfo.ssStatus
        & SSS_A )
        ccbsStat = CCBS_STAT_Active;
      else
        ccbsStat  = CCBS_STAT_Provisioned;
    }
    
    /* no CCBS features present */
    if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.c_ccbsf EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO FEATURES IN CCBS FEATURE LIST");
      
      cmhrat_ccbs( (UBYTE)owner, CCBS_IND_IrgtResult, ccbsStat, NULL );
    }
    
    /* CCBS feature list present */
    else
    {
      ccbsStat = CCBS_STAT_Active;
      
      for( idx=0;
      idx < irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.c_ccbsf;
      idx++ )
      {
        if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          v_b_subscriberNumber AND
          irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          b_subscriberNumber.c_bcdDigit )
        {
          utl_BCD2DialStr
            (irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
            b_subscriberNumber.bcdDigit,
            ccbsSet.number,
            irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
            b_subscriberNumber.c_bcdDigit);
          
          ccbsSet.type.npi = (T_ACI_TOA_NPI)irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.
            ccbsf[idx].b_subscriberNumber.npi;
          ccbsSet.type.ton = (T_ACI_TOA_TON)irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.
            ccbsf[idx].b_subscriberNumber.noa;
        }
        else
        {
          ccbsSet.number[0]  = 0x0;
          ccbsSet.type.npi   = NPI_NotPresent;
          ccbsSet.type.ton   = TON_NotPresent;
        }
        
        if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          v_b_subscriberSubaddress AND
          irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          b_subscriberSubaddress.c_subadr_str )
        {
          utl_BCD2DialStr
            (irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].b_subscriberSubaddress.subadr_str,
            ccbsSet.subaddr,
            irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].b_subscriberSubaddress.c_subadr_str);
          
          ccbsSet.satype.tos = (T_ACI_TOS_TOS)irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.
            ccbsf[idx].b_subscriberSubaddress.tos;
          ccbsSet.satype.oe  = (T_ACI_TOS_OE)irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.
            ccbsf[idx].b_subscriberSubaddress.oei;
        }
        else
        {
          ccbsSet.subaddr[0] = 0x0;
          ccbsSet.satype.tos = TOS_NotPresent;
          ccbsSet.satype.oe  = OE_NotPresent;
        }
        
        if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          v_ccbsIndex )
          ccbsSet.idx = irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.
          ccbsf[idx].ccbsIndex;
        else
          ccbsSet.idx = ACI_NumParmNotPresent;
        
        if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.ccbsf[idx].
          v_basicServiceGroup )
          ccbsSet.class_type =
          cmhSS_GetClass( (T_basicService*)&irgtSS->interrogateSSRes.cliRestrictionInfo.
          ccbsFeatureList.ccbsf[idx].basicServiceGroup );
        else
          ccbsSet.class_type = CLASS_NotPresent;
        
        ccbsSet.alrtPtn = ALPT_NotPresent;
        
        cmhrat_ccbs( (UBYTE)owner, CCBS_IND_IrgtResult, ccbsStat, &ccbsSet );
      }
    }
  }
}

/* process result for KSD CF command */
LOCAL void cmhSS_KSDCF_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_KSIR      ksStat;      /* holds KS status */
  T_CF_FEAT      *cfFeat;      /* points to CF feature list element */


  TRACE_FUNCTION ("cmhSS_KSDCF_Interrogated()");

  cfFeat = (T_CF_FEAT *)ssLstBuf;
  memset( &ksStat, 0, sizeof(ksStat));
  
  ksStat.ksdCmd = KSD_CMD_CF;
  ksStat.ir.rKSCF.opCd  = KSD_OP_IRGT;
  ksStat.ir.rKSCF.ssCd  = ssShrdPrm.stb[sId].ssCode;
  ksStat.ir.rKSCF.ssErr = KSD_NO_ERROR;
  
  /* if status is present, service is provisioned but not active for
  any basic service type ref.GSM 04.82/x.6/Ver.5.0.0 */
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    ksStat.ir.rKSCF.c_cfFeatLst = 1;
    ksStat.ir.rKSCF.cfFeatLst   = cfFeat;
    
    cfFeat->ssSt = irgtSS->interrogateSSRes.ssStatus;
    cfFeat->bsTp = KSD_BS_TP_None;
    cfFeat->bsCd = KSD_BS_TeleBearerUnknown;
    
    cfFeat->npi    = 0xFF;
    cfFeat->ton    = 0xFF;
    cfFeat->tos    = 0xFF;
    cfFeat->oe     = 0xFF;
    cfFeat->time   = 0xFF;
  }
  
  /* if forwarding number present, copy the number parameters */
  else if( irgtSS->interrogateSSRes.v_forwardedToNumber )
  {
    ksStat.ir.rKSCF.c_cfFeatLst = 1;
    ksStat.ir.rKSCF.cfFeatLst   = cfFeat;
    
    cfFeat->ssSt = KSD_ST_NOT_VALID;
    cfFeat->bsTp = KSD_BS_TP_None;
    cfFeat->bsCd = KSD_BS_TeleBearerUnknown;
    
    if( irgtSS->interrogateSSRes.forwardedToNumber.c_bcdDigit )
    {
      utl_BCD2DialStr
        (irgtSS->interrogateSSRes.forwardedToNumber.bcdDigit,
        (char*)cfFeat->num,
        irgtSS->interrogateSSRes.forwardedToNumber.c_bcdDigit);
      
      cfFeat->npi = irgtSS->interrogateSSRes.forwardedToNumber.npi;
      cfFeat->ton = irgtSS->interrogateSSRes.forwardedToNumber.noa;
    }
    else
    {
      cfFeat->npi = 0xFF;
      cfFeat->ton = 0xFF;
    }
    
    cfFeat->tos  = 0xFF;
    cfFeat->oe   = 0xFF;
    cfFeat->time = 0xFF;
  }
  
  /* if forwarding feature list is present, decode the forwarding
  information */
  else if( irgtSS->interrogateSSRes.v_forwardingFeatureList )
  {
    /* no forwarding features present */
    if( irgtSS->interrogateSSRes.forwardingFeatureList.c_ff EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO BASIC SERVICES IN BASIC SERVICE LIST");
    }
    
    /* fowarding feature list present */
    else
    {
      ksStat.ir.rKSCF.cfFeatLst   = cfFeat;
      
      ksStat.ir.rKSCF.c_cfFeatLst =
        cmhSS_ksdFillFwdFeatList( &irgtSS->interrogateSSRes.forwardingFeatureList,
        cfFeat );
    }
  }
  /* Implements Measure 209, 210, 214 */
   cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_NONE); 
}

/* process result for KSD CB command */
LOCAL void cmhSS_KSDCB_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_CB_INFO     * cbInfo;      /* points to CB information element */
  T_ACI_KSIR      ksStat;      /* holds KS status */
  UBYTE           lstSpce;     /* holds list space */
  UBYTE           idx;         /* holds list index */

  TRACE_FUNCTION ("cmhSS_KSDCB_Interrogated()");

  cbInfo = (T_CB_INFO *)ssLstBuf;
  memset( &ksStat, 0, sizeof(ksStat));
  
  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
  
  ksStat.ksdCmd = KSD_CMD_CB;
  ksStat.ir.rKSCB.opCd  = KSD_OP_IRGT;
  ksStat.ir.rKSCB.ssCd  = ssShrdPrm.stb[sId].ssCode;
  ksStat.ir.rKSCB.ssErr = KSD_NO_ERROR;
  
  /* if status is present, service is provisioned but not active for
  any basic service type ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    ksStat.ir.rKSCB.c_cbInfoLst = 1;
    ksStat.ir.rKSCB.cbInfoLst   = cbInfo;
    cbInfo->ssSt = irgtSS->interrogateSSRes.ssStatus;
    cbInfo->bsTp = KSD_BS_TP_None;
    cbInfo->bsCd = KSD_BS_TeleBearerUnknown;
  }
  
  /* if BS group list is present, the service is active for the
  containing BS/TS ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  else if( irgtSS->interrogateSSRes.v_basicServiceGroupList )
  {
    /* no basic services present */
    if( irgtSS->interrogateSSRes.basicServiceGroupList.c_basicServiceGroupList_value EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO BASIC SERVICES IN BASIC SERVICE LIST");
    }
    
    /* basic service list present */
    else
    {
      TRACE_EVENT("Basic service list is present: Status is SET for these services");
      
      ksStat.ir.rKSCB.cbInfoLst = cbInfo;
      
      lstSpce = MAX_CB_INFO_NR;
      
      for( idx=0;
      idx < irgtSS->interrogateSSRes.basicServiceGroupList.c_basicServiceGroupList_value
                   AND lstSpce;
      idx++ )
      {
        if (irgtSS->interrogateSSRes.basicServiceGroupList.
                   basicServiceGroupList_value[idx].v_teleservice)
        {
          cbInfo->bsCd = irgtSS->interrogateSSRes.basicServiceGroupList.
                basicServiceGroupList_value[idx].teleservice;
          cbInfo->bsTp = KSD_BS_TP_Tele; 
          cbInfo->ssSt = KSD_ST_A;
          cbInfo++;
          lstSpce--;
        }
        if (irgtSS->interrogateSSRes.basicServiceGroupList.
                   basicServiceGroupList_value[idx].v_bearerService)
        {
          cbInfo->bsCd = irgtSS->interrogateSSRes.basicServiceGroupList.
                 basicServiceGroupList_value[idx].bearerService;
          cbInfo->bsTp = KSD_BS_TP_Bearer;
          cbInfo->ssSt = KSD_ST_A;
          cbInfo++;
          lstSpce--;
        }
      }
      
      ksStat.ir.rKSCB.c_cbInfoLst = MAX_CB_INFO_NR - lstSpce;
    }
  }
  /* Implements Measure 209, 210, 214 */
   cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_NONE); 
}

/* process result for KSD CW command */
LOCAL void cmhSS_KSDCW_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_KSIR      ksStat;      /* holds KS status */
  T_Cx_BSG      * cxBSG;       /* points to Cx basic service group element */
  TRACE_FUNCTION ("cmhSS_KSDCW_Interrogated()");

  cxBSG = (T_Cx_BSG *)ssLstBuf;
  memset( &ksStat, 0, sizeof(ksStat));
  
  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
  
  ksStat.ksdCmd = KSD_CMD_CW;
  ksStat.ir.rKSCW.opCd  = KSD_OP_IRGT;
  ksStat.ir.rKSCW.ssCd  = ssShrdPrm.stb[sId].ssCode;
  ksStat.ir.rKSCW.ssErr = KSD_NO_ERROR;

  ksStat.ir.rKSCW.ssSt = KSD_ST_NOT_VALID;
  
  /* if status is present, service is provisioned but not active for
  any basic service type ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    ksStat.ir.rKSCW.ssSt = irgtSS->interrogateSSRes.ssStatus;
    ksStat.ir.rKSCW.c_cwBSGLst = 1;
    ksStat.ir.rKSCW.cwBSGLst   = cxBSG;
    cxBSG->bsTp = KSD_BS_TP_None;
    cxBSG->bsCd = KSD_BS_TeleBearerUnknown;
  }
  
  /* if BS group list is present, the service is active for the
  containing BS/TS ref.GSM 04.83/1.6/Ver.5.0.0 and
  ref.GSM 04.88/1.5/Ver.5.0.0 */
  else if( irgtSS->interrogateSSRes.v_basicServiceGroupList )
  {
    /* no basic services present */
    if( irgtSS->interrogateSSRes.basicServiceGroupList.c_basicServiceGroupList_value EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO BASIC SERVICES IN BASIC SERVICE LIST");
    }
    
    /* basic service list present */
    else
    {
      ksStat.ir.rKSCW.ssSt = KSD_ST_A;
      ksStat.ir.rKSCW.cwBSGLst = cxBSG;
      
      ksStat.ir.rKSCW.c_cwBSGLst =
        cmhSS_ksdFillBSGList ( &irgtSS->interrogateSSRes.basicServiceGroupList,
        cxBSG );
    }
  }
  /* Implements Measure 209, 210, 214 */
   cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_NONE); 
}

/* process result for KSD CL command */
LOCAL void cmhSS_KSDCL_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_KSIR      ksStat;      /* holds KS status */
  T_CC_CMD_PRM    *pCCCmdPrm;   /* points to CC command parameters */
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  TRACE_FUNCTION ("cmhSS_KSDCL_Interrogated()");

  pCCCmdPrm = &cmhPrm[owner].ccCmdPrm;

  ksStat.ir.rKSCL.mode = pCCCmdPrm -> CLIRmode;
  
  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
  
  ksStat.ksdCmd = KSD_CMD_CL;
  ksStat.ir.rKSCL.opCd  = KSD_OP_IRGT;
  ksStat.ir.rKSCL.ssCd  = ssShrdPrm.stb[sId].ssCode;
  ksStat.ir.rKSCL.ssErr = KSD_NO_ERROR;
  
  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    ksStat.ir.rKSCL.ssSt = irgtSS->interrogateSSRes.ssStatus;
  }
  
  if( irgtSS->interrogateSSRes.v_cliRestrictionInfo )
  {
    ksStat.ir.rKSCL.ssSt =
      (irgtSS->interrogateSSRes.cliRestrictionInfo.v_ssStatus)?
      irgtSS->interrogateSSRes.cliRestrictionInfo.ssStatus:
    (U8)KSD_ST_NOT_VALID;
    
    ksStat.ir.rKSCL.clirOpt =
      (irgtSS->interrogateSSRes.cliRestrictionInfo.v_cliRestrictionOption)?
      irgtSS->interrogateSSRes.cliRestrictionInfo.cliRestrictionOption:
    (U8)KSD_CO_NOT_VALID;
  }
  /* Implements Measure 209, 210, 214 */
   cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_NONE); 
}

/* process result for KSD CCBS command */
LOCAL void cmhSS_KSDCCBS_Interrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_KSIR      ksStat;      /* holds KS status */
  T_CC_FEAT     * ccFeat;      /* points to CC feature list element */
  TRACE_FUNCTION ("cmhSS_KSDCCBS_Interrogated()");

  ccFeat = (T_CC_FEAT *)ssLstBuf;
  memset( &ksStat, 0, sizeof(ksStat));
  
  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
  
  ksStat.ksdCmd = KSD_CMD_CCBS;
  ksStat.ir.rKSCF.opCd  = KSD_OP_IRGT;
  ksStat.ir.rKSCF.ssCd  = ssShrdPrm.stb[sId].ssCode;
  ksStat.ir.rKSCF.ssErr = KSD_NO_ERROR;
  
  /* if present, decode the CCBS information */
  if( irgtSS->interrogateSSRes.v_cliRestrictionInfo )
  {
    ksStat.ir.rKSCL.ssSt =
      (irgtSS->interrogateSSRes.cliRestrictionInfo.v_ssStatus)?
      irgtSS->interrogateSSRes.cliRestrictionInfo.ssStatus:
    (U8)KSD_ST_NOT_VALID;
    
    /* no CCBS features present */
    if( irgtSS->interrogateSSRes.cliRestrictionInfo.ccbsFeatureList.c_ccbsf EQ 0 )
    {
      TRACE_EVENT("UNEXP: NO FEATURES IN CCBS FEATURE LIST");
    }
    
    /* CCBS feature list present */
    else
    {
      ksStat.ir.rKSCC.ccFeatLst   = ccFeat;
      
      ksStat.ir.rKSCC.c_ccFeatLst =
        cmhSS_ksdFillCCBSFeatList( &irgtSS->interrogateSSRes.cliRestrictionInfo.
        ccbsFeatureList,
        ccFeat );
    }
  }
   /* Implements Measure 209, 210, 214 */
   cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_NONE);
}

LOCAL void cmhSS_CNAP_Interrogated( T_OWN owner, T_INTERROGATE_SS_RES *irgtSS )
{
  T_ACI_CNAP_STATUS status = CNAP_SERVICE_STATUS_UNKNOWN;
  
  TRACE_FUNCTION ("cmhSS_CNAP_Interrogated()");

  if( irgtSS->interrogateSSRes.v_ssStatus )
  {
    TRACE_EVENT("service status information present");
    status = (irgtSS->interrogateSSRes.ssStatus & SSS_P)? CNAP_SERVICE_PROVISIONED : CNAP_SERVICE_NOT_PROVISIONED;
  }

  R_AT( RAT_CNAP, (T_ACI_CMD_SRC)owner )
      ( NULL, status );
}
  
GLOBAL void cmhSS_SSInterrogated( SHORT sId, T_INTERROGATE_SS_RES *irgtSS )
{
  T_SS_CMD_PRM  *pSSCmdPrm;   /* points to SS command parameters */
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  USHORT          cmdBuf = ssShrdPrm.stb[sId].curCmd;

  TRACE_FUNCTION ("cmhSS_SSInterrogated()");

  pSSCmdPrm = &cmhPrm[owner].ssCmdPrm;

  /* check for command context */
  switch( cmdBuf )
  {
    case( AT_CMD_CLIP ):
      cmhSS_CLIP_Interrogated( owner, irgtSS );
      break;

    case( AT_CMD_CDIP ):
      cmhSS_CDIP_Interrogated( owner, irgtSS );
      break;

    case( AT_CMD_CLIR ):
      cmhSS_CLIR_Interrogated( sId, irgtSS );
      break;

    case( AT_CMD_COLP ):
      cmhSS_COLP_Interrogated( owner, irgtSS );
      break;

    case( AT_CMD_COLR ):
      cmhSS_COLR_Interrogated( owner, irgtSS );
      break;

    case( AT_CMD_CCWA ):
      /* if the service is not provisioned by the network, an error component was received.
         This is not handled here, see cmhSS_ErrorReturn() */
      cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm -> mltyTrnFlg)); 
      cmhSS_CCWA_Interrogated( sId, irgtSS );
      break;
    
    case( AT_CMD_CLCK ):
      /* if the service is not provisioned by the network, an error component was received.
         This is not handled here, see cmhSS_ErrorReturn() */
      cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm -> mltyTrnFlg)); 
      cmhSS_CLCK_Interrogated( sId, irgtSS );
      break;

    case( AT_CMD_CCFC ):
      cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm -> mltyTrnFlg)); 
      /* if the service is not provisioned by the network, an error component was received.
         This is not handled here, see cmhSS_ErrorReturn() */
      cmhSS_CCFC_Interrogated( sId, irgtSS );
      break;

    case( AT_CMD_CCBS ):
      cmhSS_CCBS_Interrogated( owner, irgtSS );
      break;
   
    /* process result for KSD CF command */
    case( KSD_CMD_CF ):
      cmhSS_KSDCF_Interrogated( sId, irgtSS );
      break;

    case( KSD_CMD_CB ):
      cmhSS_KSDCB_Interrogated( sId, irgtSS );
      break;

    case( KSD_CMD_CW ):
      cmhSS_KSDCW_Interrogated( sId, irgtSS );
      break;

    case( KSD_CMD_CL ):
      cmhSS_KSDCL_Interrogated( sId, irgtSS );
      break;

    case( KSD_CMD_CCBS ):
      cmhSS_KSDCCBS_Interrogated( sId, irgtSS );
      break;

    case( AT_CMD_CNAP ):
      cmhSS_CNAP_Interrogated( owner, irgtSS );
      break;
  }

  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

  R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
    ( (T_ACI_AT_CMD)cmdBuf );
  cmh_logRslt( (T_ACI_CMD_SRC)owner, RAT_OK,(T_ACI_AT_CMD)cmdBuf, -1, 
  	                  BS_SPEED_NotPresent,CME_ERR_NotPresent );

  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSRegistered           |
+-------------------------------------------------------------------+

  PURPOSE : SS registration result is available.

*/

GLOBAL void cmhSS_SSRegistrated( SHORT sId,
                                 T_REGISTER_SS_RES *regSS )
{
  /* Implements Measure 215 */
  TRACE_FUNCTION ("cmhSS_SSRegistrated()");
  cmhSS_SSRegistrated_Erased( sId, KSD_OP_REG, &regSS->ssInfo );
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSErased               |
+-------------------------------------------------------------------+

  PURPOSE : SS erasure result is available.

*/

GLOBAL void cmhSS_SSErased( SHORT sId,
                            T_ERASE_SS_RES *ersSS )
{
  /* Implements Measure 215 */

  TRACE_FUNCTION ("cmhSS_SSErased()");
  cmhSS_SSRegistrated_Erased( sId, KSD_OP_ERS, &ersSS->ssInfo );

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSActivated            |
+-------------------------------------------------------------------+

  PURPOSE : SS erasure result is available.

*/

GLOBAL void cmhSS_SSActivated( SHORT sId,
                               T_ACTIVATE_SS_RES *actSS )
{
  /* Implements Measure 217 */
  TRACE_FUNCTION ("cmhSS_SSActivated()");
  cmhSS_SSActDeact( sId, KSD_OP_ACT, &actSS->ssInfo );        
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSDeactivated          |
+-------------------------------------------------------------------+

  PURPOSE : SS erasure result is available.

*/

GLOBAL void cmhSS_SSDeactivated( SHORT sId,
                                 T_DEACTIVATE_SS_RES *deactSS )
{
  /* Implements Measure 217 */

  TRACE_FUNCTION ("cmhSS_SSDeactivated()");
  cmhSS_SSActDeact( sId, KSD_OP_DEACT, &deactSS->ssInfo );

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_getPassword            |
+-------------------------------------------------------------------+

  PURPOSE : get password guidance.

*/

GLOBAL void cmhSS_getPassword( SHORT sId,
                               T_GET_PWD_INV *getPWD )
{
  T_SS_CMD_PRM *pSSCmdPrm;   /* points to SS command parameters */
  T_OWN        owner  = ssShrdPrm.stb[sId].srvOwn;
  USHORT        cmdBuf = ssShrdPrm.stb[sId].curCmd; 

  TRACE_FUNCTION ("cmhSS_getPassword()");

  if(owner EQ OWN_SRC_SAT)
  {
    TRACE_EVENT("Owner SAT");
  }

/*
 *-------------------------------------------------------------------
 * check for mandatory info
 *-------------------------------------------------------------------
 */
  if( ! getPWD -> v_guidanceInfo  )
  {
    ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

    R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )
      ( (T_ACI_AT_CMD)cmdBuf, CME_ERR_NotPresent );
    cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_CME, (T_ACI_AT_CMD)cmdBuf, -1, 
		           BS_SPEED_NotPresent, CME_ERR_NotPresent );
    return;
  }
/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( cmdBuf )
  {
   /*
    *----------------------------------------------------------------
    * process result for +CPWD and +CLCK and KSD PWD and KSD CB command
    *----------------------------------------------------------------
    */
    case( AT_CMD_CPWD ):
    case( AT_CMD_CLCK ):
    case( KSD_CMD_PWD ):
    case( KSD_CMD_CB  ):

      if (owner > ((T_OWN)CMD_SRC_NONE)) /* Just to remove LINT warning */
      {
        pSSCmdPrm = &cmhPrm[owner].ssCmdPrm;
      

        switch( getPWD -> guidanceInfo )
        {
          case( GUI_ENTER_PW ):
/* Implements Measure#32: Row 1151 */
            if(strcmp((CHAR*)pSSCmdPrm->CXXXpwd, ffff_str) EQ 0)
            {
              /* remember sId to answer with password */
  #ifdef SIM_TOOLKIT            
              satShrdPrm.sId_pwd_requested = sId;
  #endif /* SIM_TOOLKIT */

              /* Password never given before ask for it */
              R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )
                ( AT_CMD_CPWD, CME_ERR_WrongPasswd );
              cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_CME, AT_CMD_CPWD, -1,
			  	                 BS_SPEED_NotPresent, CME_ERR_WrongPasswd );
              return;
            }
            else
            {
              psaSS_asmVerifyPWD( pSSCmdPrm -> CXXXpwd );
              psaSS_CntTrns(sId);
            }
            break;

          case( GUI_ENTER_NEW_PW ):

            psaSS_asmVerifyPWD( pSSCmdPrm -> CXXXnewPwd );
            psaSS_CntTrns(sId);
            break;

          case( GUI_ENTER_NEW_PW_AGAIN ):

            psaSS_asmVerifyPWD( pSSCmdPrm -> CXXXnewPwd2 );
            psaSS_CntTrns(sId);
            break;

          case( GUI_BAD_PW_RETRY ):
          case( GUI_BAD_PW_FORM ):

            ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
            ssShrdPrm.stb[sId].curCmd     = AT_CMD_NONE;

            R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )
              ( AT_CMD_CPWD, CME_ERR_WrongPasswd );
            cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_CME, AT_CMD_CPWD,
				        -1, BS_SPEED_NotPresent, CME_ERR_WrongPasswd );

           /* end of transaction */
            psaSS_asmEmptyRslt();
            psaSS_EndTrns(sId);

            ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
        }
        break;
      }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSPWDRegistrated       |
+-------------------------------------------------------------------+

  PURPOSE : Password registration result is available.

*/

GLOBAL void cmhSS_SSPWDRegistrated( SHORT sId,
                                    T_REGISTER_PWD_RES *regPWD )
{
  T_ACI_KSIR     ksStat;      /* holds KS status */
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;

  TRACE_FUNCTION ("cmhSS_SSPWDRegistrated()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( ssShrdPrm.stb[sId].curCmd )
  {
   /*
    *----------------------------------------------------------------
    * process result for +CPWD  command
    *----------------------------------------------------------------
    */
    case( AT_CMD_CPWD ):

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      /* terminate command */
      R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
        ( AT_CMD_CPWD );
      cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_OK, AT_CMD_CPWD, 
	  	                   -1,BS_SPEED_NotPresent,CME_ERR_NotPresent );
      break;

   /*
    *----------------------------------------------------------------
    * process result for KSD PWD command
    *----------------------------------------------------------------
    */
    /*lint -e{408}*/ 
    case( KSD_CMD_PWD ):

      memset( &ksStat, 0, sizeof(ksStat));

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      ksStat.ksdCmd = KSD_CMD_PWD;
      ksStat.ir.rKSPW.opCd  = KSD_OP_REG;
      ksStat.ir.rKSPW.ssCd  = ssShrdPrm.stb[sId].ssCode;
      ksStat.ir.rKSPW.ssErr = KSD_NO_ERROR;

      if( regPWD->v_newPassword )
      {
        memcpy( ksStat.ir.rKSPW.newPwd, regPWD->newPassword.digit,
                MAX_PWD_NUM );
      }
      /* Implements Measure 209, 210, 214 */
      cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_PWD); 

      break;
  }

/*
 *-------------------------------------------------------------------
 * set service table entry to unused
 *-------------------------------------------------------------------
 */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_CCNtryErased           |
+-------------------------------------------------------------------+

  PURPOSE : CC entry erased.

*/

GLOBAL void cmhSS_CCNtryErased( SHORT sId,
                                T_ERASE_CC_ENTRY_RES *ersCCNtry )
{
/*  T_ACI_KSIR     ksStat; */     /* holds KS status */
  T_OWN owner = ssShrdPrm.stb[sId].srvOwn;

  TRACE_FUNCTION ("cmhSS_CCNtryErased()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( ssShrdPrm.stb[sId].curCmd & 0xFFFF )
  {
   /* process result for %CCBS  command */
     case( AT_CMD_CCBS ):
      /* terminate command */
      R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
        ( AT_CMD_CCBS );
      cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_OK, AT_CMD_CCBS, 
	  	               -1, BS_SPEED_NotPresent,CME_ERR_NotPresent );
      break;

   /* process result for KSD CCBS command */
    case( (T_ACI_AT_CMD)KSD_CMD_CCBS ):

      /*  Should be removed...
      CLB: why should any status notification be sent to user ???
      SS has just been erased !! 
      05 Feb 2002
      
      memset( &ksStat, 0, sizeof(ksStat));

      ksStat.ksdCmd = KSD_CMD_CCBS;
      ksStat.ir.rKSCC.opCd  = KSD_OP_ERS;
      ksStat.ir.rKSCC.ssCd  = KSD_SS_NONE;
      ksStat.ir.rKSCC.ssSt  = KSD_ST_NOT_VALID;
      ksStat.ir.rKSCC.ssErr = KSD_NO_ERROR;

      ksStat.ir.rKSCC.c_ccFeatLst = 0;
      ksStat.ir.rKSCC.ccFeatLst   = NULL;

      if( ersCCNtry -> eraseCCEntryRes.v_ssCode )
      {
        ksStat.ir.rKSCC.ssCd  = ersCCNtry -> eraseCCEntryRes.ssCode;
      }

      if( ersCCNtry -> eraseCCEntryRes.v_ssStatus )
      {
        ksStat.ir.rKSCC.ssSt  = ersCCNtry -> eraseCCEntryRes.ssStatus;
      }

      R_AT( RAT_KSIR, owner )
        ( &ksStat );*/

      /* terminate command */
      R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
        ( KSD_CMD_CCBS );
      cmh_logRslt ((T_ACI_CMD_SRC)owner, RAT_OK, (T_ACI_AT_CMD)KSD_CMD_CCBS, 
	  	                                            -1, BS_SPEED_NotPresent,CME_ERR_NotPresent );
      break;
  }

/*
 *-------------------------------------------------------------------
 * set service table entry to unused
 *-------------------------------------------------------------------
 */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_USSDNotify             |
+-------------------------------------------------------------------+

  PURPOSE : Network initiated USSD notification received.

*/

GLOBAL void cmhSS_USSDNotify( SHORT sId,
                              T_USSD_NOTIFY_INV *ussdNtfy )
{
  UBYTE           idx;
  SHORT           dcs   = ACI_NumParmNotPresent;

  T_ACI_USSD_DATA *ussd = NULL;

  TRACE_FUNCTION ("cmhSS_USSDNotify()");

/*
 *-------------------------------------------------------------------
 * check for another service in progress
 *-------------------------------------------------------------------
 */
  if( psaSS_stbFindActSrv( sId ) NEQ NO_ENTRY )
  {
    psaSS_asmErrorRslt( sId, ERR_USSD_BUSY );

    psaSS_EndTrns(sId);

    ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

    return;
  }

/*
 *-------------------------------------------------------------------
 * send unsolicited result code
 *-------------------------------------------------------------------
 */
//TISH, patch for OMAPS00122402
//start
//  if( ussdNtfy -> v_ussdArg )
  if( ussdNtfy -> v_ussdArg && ussdNtfy -> ussdArg.ussdString.l_ussdString>>3)
//end
  {
    /* Implements Measure 76 */
    ussd = cmhSS_prepareUSSDRes(&ussdNtfy -> ussdArg, &dcs);
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CUSD, (T_ACI_CMD_SRC)idx )
        ( CUSD_MOD_NoActReq, ussd, dcs );
    }

    if (ussd NEQ NULL)
    {
      MFREE(ussd);
    }
  }

  ssShrdPrm.stb[sId].ussd_operation = TRUE;
  
/*
 *-------------------------------------------------------------------
 * confirm USSD notify receiption with empty result if Extended USSD Response feature is not enabled. 
 *-------------------------------------------------------------------
 */
  if(cuscfgParams.Ext_USSD_Response EQ CUSCFG_STAT_Disabled)
  {
  //TISH, patch for OMAPS00122402
  //start
  	if ((UBYTE)(ussdNtfy -> ussdArg.ussdString.l_ussdString>>3) EQ 0)
  		{
			  ssShrdPrm.stb[sId].failType = SSF_SS_ERR;
			  ssShrdPrm.stb[sId].errCd    = ERR_UNKNOWN_ALPHA;
			  ssShrdPrm.cmpType = CT_RET_ERR;  	
			  psaSS_CntTrns(sId);
  			return;
  		}
//end	
    psaSS_asmEmptyRslt();

    psaSS_CntTrns(sId);

  }
  else
  {
    Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Notify;
    Ext_USSD_Res_Pending_sId = sId;
  }
  
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_USSDRequest            |
+-------------------------------------------------------------------+

  PURPOSE : Network initiated USSD request received.

*/

GLOBAL void cmhSS_USSDRequest( SHORT sId,
                               T_USSD_REQ_INV *ussdReq )
{
  UBYTE           idx;
  SHORT           dcs   = ACI_NumParmNotPresent;
  T_ACI_USSD_DATA *ussd = NULL;
  T_ACI_KSIR      ksStat;

  TRACE_FUNCTION ("cmhSS_USSDRequest()");

  /* check for another service in progress */
  if( psaSS_stbFindActSrv( sId ) NEQ NO_ENTRY )
  {
    psaSS_asmErrorRslt( sId, ERR_USSD_BUSY );

    psaSS_EndTrns(sId);

    ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
    return;
  }

  /* send unsolicited result code */
  if( ussdReq -> v_ussdArg )
  {
    /* Implements Measure 76 */
    ussd = cmhSS_prepareUSSDRes(&ussdReq -> ussdArg, &dcs);
    if(ssShrdPrm.stb[sId].curCmd EQ AT_CMD_CUSD )
    {
      R_AT( RAT_CUSD, (T_ACI_CMD_SRC)ssShrdPrm.stb[sId].srvOwn )
        ( CUSD_MOD_YesActReq, ussd, dcs );
    }
    else if (ssShrdPrm.stb[sId].curCmd EQ ((T_ACI_AT_CMD)KSD_CMD_USSD))
    {
      ksStat.ksdCmd        = KSD_CMD_USSD;
      ksStat.ir.rKSUS.mode = CUSD_MOD_YesActReq;
      ksStat.ir.rKSUS.ussd = ussd->data;
      ksStat.ir.rKSUS.len  = ussd->len;
      ksStat.ir.rKSUS.dcs  = dcs;
      ksStat.ir.rKSUS.ssErr = KSD_NO_ERROR;

      R_AT( RAT_KSIR, (T_ACI_CMD_SRC)ssShrdPrm.stb[sId].srvOwn )
          ( &ksStat );     
    }
    else
    {
      for( idx = 0; idx < CMD_SRC_MAX; idx++ )
      {
        R_AT( RAT_CUSD, (T_ACI_CMD_SRC)idx )
          ( CUSD_MOD_YesActReq, ussd, dcs );
      }
    }
      
    if(ussd NEQ NULL)
    {
      MFREE(ussd);
    }
    ssShrdPrm.stb[sId].ussdReqFlg = TRUE;
  }

  ssShrdPrm.stb[sId].ussd_operation = TRUE;

  if(cuscfgParams.Ext_USSD_Response NEQ CUSCFG_STAT_Disabled)
  {
    Ext_USSD_Res_Pending = CUSDR_EXT_USSD_RES_Request;
    Ext_USSD_Res_Pending_sId = sId;
  }
  
  /* check command context */
  if(ssShrdPrm.stb[sId].curCmd EQ AT_CMD_CUSD )
  {
    ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
  }
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_USSDReqProcessed       |
+-------------------------------------------------------------------+

  PURPOSE : USSD request was processed.

*/

/* TRUE returned means operation has been processed by SAT:
function os to return immediatly */
LOCAL BOOL cmhss_sat_ussd_reqprocessed( SHORT sId,
                                        T_PROCESS_USSD_REQ_RES *prcUSSDReq )
{
#ifdef SIM_TOOLKIT
  BOOL            retvalue = FALSE;
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  T_ACI_AT_CMD           cmdBuf = ssShrdPrm.stb[sId].curCmd;

  T_text     USSD_resp;
  T_ACI_SAT_TERM_RESP resp_data;

  /* ACI-SPR-16433: temporaly used to hold incoming USSD string */ 
  UBYTE           additionalData[MAX_USSD_LEN];
  UBYTE           additionalDataLen = 0; /* max 183 Byte, see MAX_USSD_LEN */ 
  USHORT          index = 0;
  UBYTE           ussdAddLen = 0;
  
  psaSAT_InitTrmResp( &resp_data );

  TRACE_FUNCTION ("cmhss_sat_ussd_reqprocessed()");

  if( (cmdBuf NEQ AT_CMD_NONE) AND ( (owner NEQ OWN_SRC_SAT) OR      
      ((T_ACI_KSD_CMD)cmdBuf NEQ KSD_CMD_USSD) ) )

  {
    TRACE_EVENT_P1("cmhss_sat_ussd_reqprocessed(): ssShrdPrm.stb[sId].curCmd NEQ AT_CMD_NONE --> %d", 
                    ssShrdPrm.stb[sId].curCmd);
    retvalue = FALSE;
  }
  else if ( satShrdPrm.USSDterm )        /* response to a user defined termination */
  {
    psaSAT_SendTrmResp( RSLT_USER_TERM_SS, &resp_data );
    satShrdPrm.USSDterm = FALSE; /* reinitialize */
    retvalue = TRUE;
  }
  /* ACI-SPR-16433: USSD session might been started as SS command and KSD 
                    identified an USSD key sequence */
  else if ( sId EQ satShrdPrm.SentUSSDid AND 
          ( (satShrdPrm.cmdDet.cmdType EQ SAT_CMD_SEND_USSD) OR 
            (satShrdPrm.cmdDet.cmdType EQ SAT_CMD_SEND_SS  )    ))
  {
    /* Terminal response to SEND USSD when no error */
    
    if( prcUSSDReq -> v_ussdRes )
    {
      if ( prcUSSDReq -> ussdRes.v_ussdString )
      {
        USSD_resp.c_text_str = prcUSSDReq -> ussdRes.ussdString.l_ussdString>>3;

        memcpy( &(USSD_resp.text_str),
                &(prcUSSDReq -> ussdRes.ussdString.b_ussdString),
                USSD_resp.c_text_str);
      }
      else
        USSD_resp.c_text_str = 0;

      if ( prcUSSDReq -> ussdRes.v_ussdDataCodingScheme )
      {
        /*
          ACI: OMAPS00060422

          According to the 11.14 the USSD string Data Coding Scheme
          is coded as for Cell Broadcast defined in TS 23.038.
          So, we store the USSD Data Coding Scheme when we receive from SIM
          as a CBS Data coding Scheme.

          But, while seding the TERMINAL RESPONSE to the SIM we send the string
          as Text String. According to the 11.14 for Text String Data Coding
          Scheme is coded as for SMS Data Coding Scheme defined in 23.038
        */

        /*
          If we receive the DCS in USSD String from SIM as F0 (CBS DCS value:
          Means 7-Bit Default, with No Message Class.

          But, in the Text string while sending TERMINAL RESPONSE the DCS value
          we have to change according to the 11.14 Specification. So, in Text
          String the the DCS value of CBS will become 00(SMS DCS for text
          String which Means 7-Bit Default, with No Message Class.)

        */

        if ( prcUSSDReq -> ussdRes.ussdDataCodingScheme EQ 0xF0 )
        {
          /* This is a special case. The CBS DCS for F0 (Special case 7-bit 
             default GSM alphabet with No Message class) we can send SMS 
             value as 0x00. The CBS DCS for F1 (Special case 8-bit with No
             Message class) we can send SMS value as 0x01 as the if bit 4 
             is ZERO then message class has no meaning.
          */
          USSD_resp.dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme & 0x0f;
        }
        else if ( prcUSSDReq -> ussdRes.ussdDataCodingScheme >= 0x40 AND
                  prcUSSDReq -> ussdRes.ussdDataCodingScheme <= 0x7F )
        {
          /* Below are the mapping between CBS DCS -> SMS DCS values. 
             For any values of CBS from 40 - 7F we can send SMS DCS as 00 - 3F
          */
          USSD_resp.dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme & 0x3f;
        }
        else if ( prcUSSDReq -> ussdRes.ussdDataCodingScheme >= 0xF1 AND
                  prcUSSDReq -> ussdRes.ussdDataCodingScheme <= 0xF4 )
        {
          /* For CBS DCS 0xF1..0xF4 SMS DCS is sent as other than above we can
             send as it is */
          USSD_resp.dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme;
        }
        else
        {
          /* For any values for CBS DCS other than above we can send as it is */
          TRACE_EVENT_P1("Possible problem in converting CBS to SMS DCS: %d", prcUSSDReq -> ussdRes.ussdDataCodingScheme);
          USSD_resp.dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme;
        }
      }

      resp_data.text = &USSD_resp;

      /* ACI-SPR-16344: Prepare additional data for terminal response 
         as requested in GSM 11.14 section 12.12.1 */
      if ( satShrdPrm.cmdDet.cmdType EQ SAT_CMD_SEND_SS )
      {
        /* calculate length */
        if ( prcUSSDReq->ussdRes.v_ussdString )
        {
          ussdAddLen = prcUSSDReq->ussdRes.ussdString.l_ussdString>>3;
        }
        /* also consider the first byte */ 
        additionalDataLen = ussdAddLen + 8;

        /* START: reconstruct the operation component received */
        /* copy msg_type */
        additionalData[index++] = prcUSSDReq->msg_type;
        /* set sequence tag */
        additionalData[index++] = 0x30; /* sequence tag */
        /* length might be in one or 2 bytes representation (see GSM5_TLV) 
           (-2) because the first two bytes are not counted */
        if( (additionalDataLen-2) <= 0x7F ) 
        {
          additionalData[index++] = additionalDataLen-2;
        }
        else
        {
          additionalData[index++] = 0x81; /* prefix */ 
          additionalData[index++] = additionalDataLen-2;          
        }
        /* set dcs tag and dcs length and dcs */
        additionalData[index++] = 0x04; /* dcs tag */
        additionalData[index++] = 0x01; /* dcs length (always 1) */
        if ( prcUSSDReq->ussdRes.v_ussdDataCodingScheme )
        {
          additionalData[index++] = prcUSSDReq->ussdRes.ussdDataCodingScheme;
        }
        else 
        {
          TRACE_EVENT("cmhss_sat_ussd_req processed: DCS undef assuming 0x00");
          additionalData[index++] = 0x00; /* default value */
        }
        /* set ussd tag, length and string */
        additionalData[index++] = 0x04;  /* ussd tag */
        /* length might be one or 2 bytes (see GSM5_TLV) */
        if( (additionalDataLen-2) <= 0x7F ) 
        {
          additionalData[index++] = ussdAddLen;
        }
        else
        {
          additionalData[index++] = 0x81; /* prefix */
          additionalData[index++] = ussdAddLen;
        }
        /* copy ussd string */
        if ( prcUSSDReq->ussdRes.v_ussdString ) 
        {
          memcpy(additionalData+index, 
                 &(prcUSSDReq -> ussdRes.ussdString.b_ussdString),
                 ussdAddLen);
        }
        /* copy additional data to terminal response */        
        resp_data.add = additionalData;
        resp_data.addLen = additionalDataLen;        
      }
      /* End of ACI-SPR-16344: Prepare additional data for terminal response */
      
      psaSAT_SendTrmResp( RSLT_PERF_SUCCESS, &resp_data );

      satShrdPrm.SentUSSDid = NO_ENTRY; /* reinitialize */

      retvalue = TRUE;
    }
  }
  return retvalue; 
#else /* SIM_TOOLKIT */
  return FALSE;
#endif /* SIM_TOOLKIT */
}


GLOBAL void cmhSS_USSDReqProcessed( SHORT sId,
                                    T_PROCESS_USSD_REQ_RES *prcUSSDReq )
{
  SHORT           dcs = ACI_NumParmNotPresent;
  T_ACI_KSIR      ksStat;   /* holds KS status */
  T_ACI_USSD_DATA *ussd;
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  BOOL            end_of_process;

  TRACE_FUNCTION ("cmhSS_USSDReqProcessed()");

  /* Check whether this is a SAT action */
  end_of_process = cmhss_sat_ussd_reqprocessed( sId, prcUSSDReq );
  if(end_of_process)
  {
    /* set service table entry to unused */
    ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
    return;
  }
  
  /* check command context */
  switch( ssShrdPrm.stb[sId].curCmd )
  {
    case( AT_CMD_NONE ):
    case( AT_CMD_CUSD ):

      /* send unsolicited result code */
      if( prcUSSDReq -> v_ussdRes )
      {
        if( prcUSSDReq -> ussdRes.v_ussdDataCodingScheme )
          dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme;

        if( prcUSSDReq -> ussdRes.v_ussdString )
        {
          MALLOC(ussd, sizeof(T_ACI_USSD_DATA));

          /* SDU offset is assumed to be zero for ussd string */
          ussd->len = prcUSSDReq -> ussdRes.ussdString.l_ussdString>>3;
          /* Implements Measure 25 */
          /* This function is more correct than utl_getAlphabetCb as it takes care 
             of reserved codings */
          if( cmh_getAlphabetCb( (UBYTE)dcs ) EQ 0 ) /* 7bit alphabet */
          {
            ussd->len = utl_cvt7To8( prcUSSDReq -> ussdRes.ussdString.b_ussdString,
                                     ussd->len,
                                     ussd->data,
                                     0 );
          }
          else
            memcpy( ussd->data, 
                    prcUSSDReq -> ussdRes.ussdString.b_ussdString,
                    ussd->len );

          ussd->data[ussd->len]=0x00;

          R_AT( RAT_CUSD, (T_ACI_CMD_SRC)owner )
            ( CUSD_MOD_NoActReq, ussd, dcs );
          
          MFREE(ussd);
        }
      }
      else
      {
        R_AT( RAT_CUSD, (T_ACI_CMD_SRC)owner )
        ( CUSD_MOD_NoActReq, NULL, ACI_NumParmNotPresent );
      }

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
      break;
      /*lint -e{408}*/ 
    case ( KSD_CMD_USSD ) :

      MALLOC(ussd, sizeof(T_ACI_USSD_DATA));

      memset( &ksStat, 0, sizeof(ksStat));
      ksStat.ksdCmd        = KSD_CMD_USSD;
      ksStat.ir.rKSUS.mode = CUSD_MOD_NoActReq;
      ksStat.ir.rKSUS.ussd = ussd->data;
      ussd->len               = 0;
      ussd->data[0]      = 0x0;

      if( prcUSSDReq -> v_ussdRes )
      {
        if( prcUSSDReq -> ussdRes.v_ussdDataCodingScheme )
        {
          dcs                 = prcUSSDReq -> ussdRes.ussdDataCodingScheme;
          ksStat.ir.rKSUS.dcs = prcUSSDReq -> ussdRes.ussdDataCodingScheme;
        }
        else
        {
          ksStat.ir.rKSUS.dcs = ACI_NumParmNotPresent;
        }

        if( prcUSSDReq -> ussdRes.v_ussdString )
        {
          ussd->len = prcUSSDReq -> ussdRes.ussdString.l_ussdString>>3;
          /* Implements Measure 25 */
          /* This function is more correct than utl_getAlphabetCb as it takes care 
             of reserved codings */  
          if( cmh_getAlphabetCb( (UBYTE)dcs ) EQ 0 ) /* 7bit alphabet */
          {
            ussd->len = utl_cvt7To8( prcUSSDReq -> ussdRes.ussdString.b_ussdString,
                                     ussd->len,
                                     ussd->data,
                                     0 );
          }
          else
            memcpy( ussd->data, prcUSSDReq -> ussdRes.ussdString.b_ussdString,
                    ussd->len );

          if( !utl_cvtGsmIra ( ussd->data,
                               ussd->len,
                               ussd->data,
                               MAX_USSD_LEN,
                               CSCS_DIR_GsmToIra ))
          {
            TRACE_EVENT("utl_cvtGsmIra() could not be performed");
          }
        }
      }

      ksStat.ir.rKSUS.len = ussd->len;
      ussd->data[ussd->len] = 0x00;
      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      TRACE_EVENT_P2("cmhSS_USSDReqProcessed: sId: %d, owner: %d", sId, owner);
      /* Implements Measure 209, 210, 214 */
      cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_USSD);
      MFREE(ussd);
      break;
  }

  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_USSDDatProcessed       |
+-------------------------------------------------------------------+

  PURPOSE : USSD data was processed.

*/

GLOBAL void cmhSS_USSDDatProcessed( SHORT sId,
                                    T_PROCESS_USSD_RES *prcUSSDdat )
{
  T_ACI_KSIR      ksStat; /* holds KS status */
  T_ACI_USSD_DATA *ussd;
  T_OWN           owner = ssShrdPrm.stb[sId].srvOwn;
#ifdef SIM_TOOLKIT
  T_text     USSD_resp;
  T_ACI_SAT_TERM_RESP resp_data; 
  psaSAT_InitTrmResp( &resp_data );
#endif /* SIM_TOOLKIT */

  TRACE_FUNCTION ("cmhSS_USSDDatProcessed()");

/*
 *-------------------------------------------------------------------
 * check command context
 *-------------------------------------------------------------------
 */
  switch( ssShrdPrm.stb[sId].curCmd )
  {
    case( AT_CMD_NONE ):

#ifdef SIM_TOOLKIT
      if ( satShrdPrm.USSDterm )        /* response to a user defined termination */
      {
        psaSAT_SendTrmResp( RSLT_USER_TERM_SS, &resp_data );
        satShrdPrm.USSDterm = FALSE; /* reinitialize */
        break;
      }

      if ( sId EQ satShrdPrm.SentUSSDid                   AND 
           satShrdPrm.cmdDet.cmdType EQ SAT_CMD_SEND_USSD )
      {
        /* Terminal response to SEND USSD when no error */
        if( prcUSSDdat -> v_ssUserData )
        {
          USSD_resp.c_text_str = prcUSSDdat -> ssUserData.l_ssUserData>>3;
          memcpy( &(USSD_resp.text_str),&(prcUSSDdat -> ssUserData.b_ssUserData), USSD_resp.c_text_str);
        }
        else
        {
          USSD_resp.c_text_str = 0;
        }

        USSD_resp.dcs = 0xD4;

        resp_data.text = &USSD_resp;

        psaSAT_SendTrmResp( RSLT_PERF_SUCCESS, &resp_data );

        satShrdPrm.SentUSSDid = NO_ENTRY; /* reinitialize */

        break;
      }
#endif /* SIM_TOOLKIT */
      /* no break if NO SIM_TOOLKIT...
      or if it is an answer to another ss as the one initiated by SAT */
    /*lint -fallthrough */
    case( AT_CMD_CUSD ):

      /* prepare unsolicited result code */
      if( prcUSSDdat -> v_ssUserData )
      {
        MALLOC(ussd, sizeof(T_ACI_USSD_DATA));

        /* SDU offset is assumed to be zero for ussd string */
        ussd->len = prcUSSDdat -> ssUserData.l_ssUserData>>3;

        memcpy( ussd->data, prcUSSDdat -> ssUserData.b_ssUserData,
                MAX_USSD_LEN );

        if( utl_cvtGsmIra ( prcUSSDdat -> ssUserData.b_ssUserData,
                            ussd->len,
                            ussd->data,
                            MAX_USSD_LEN,
                            CSCS_DIR_IraToGsm ) )
        {
          ussd->data[ussd->len]=0x00;
        }

        R_AT( RAT_CUSD, (T_ACI_CMD_SRC)owner )
          ( CUSD_MOD_NoActReq, ussd, 0 );
        MFREE(ussd);
      }
      else
      {
        R_AT( RAT_CUSD, (T_ACI_CMD_SRC)owner )
          ( CUSD_MOD_NoActReq, NULL, ACI_NumParmNotPresent );
      }

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
      break;
      /*lint -e{408}*/ 
    case ( KSD_CMD_USSD ) :

      memset( &ksStat, 0, sizeof(ksStat));
      ksStat.ksdCmd = KSD_CMD_USSD;
      ksStat.ir.rKSUS.mode = CUSD_MOD_NoActReq;
      ksStat.ir.rKSUS.dcs  = ACI_NumParmNotPresent;
      ksStat.ir.rKSUS.len  = prcUSSDdat -> ssUserData.l_ssUserData>>3;


      if( prcUSSDdat -> v_ssUserData )
      {
        prcUSSDdat -> ssUserData.b_ssUserData
              [prcUSSDdat -> ssUserData.l_ssUserData] = 0x0;
        ksStat.ir.rKSUS.ussd = prcUSSDdat -> ssUserData.b_ssUserData;

      }

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;
     /* Implements Measure 209, 210, 214 */
      cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_USSD);
      break;
  }

/*
 *-------------------------------------------------------------------
 * set service table entry to unused
 *-------------------------------------------------------------------
 */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_FwdChckSS              |
+-------------------------------------------------------------------+

  PURPOSE : Forward check SS indication.

*/

GLOBAL void cmhSS_FwdChckSS( SHORT sId )
{  
  TRACE_FUNCTION ("cmhSS_FwdChckSS()");

  /* send unsolicited result code */
  send_CSSX_notification(NO_ENTRY,
                              CSSX_CODE_FwrdCheckSS,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

  
  /* end of transaction */
  psaSS_asmEmptyRslt();
  psaSS_EndTrns(sId);

  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : SSTransFail_default          |
+-------------------------------------------------------------------+

  PURPOSE : SS transaction failed.

*/
LOCAL void SSTransFail_default ( SHORT sId )
{
  T_ACI_CME_ERR error;
  T_ACI_AT_CMD         current_cmd = ssShrdPrm.stb[sId].curCmd; 
  T_ACI_CUSD_MOD    errCd;
  T_OWN         owner       = ssShrdPrm.stb[sId].srvOwn;
  USHORT        idx = 0;
  
  TRACE_FUNCTION ("SSTransFail_default()");

  cmhPrm[owner].ssCmdPrm.mltyTrnFlg = 0;

  if (ssShrdPrm.stb[sId].errCd EQ ERR_UNEXPECT_DATA)
  {
    error = CME_ERR_OpNotAllow;
  }
  else
  {
    error = CME_ERR_NotPresent;
  }

  if (current_cmd EQ ((T_ACI_AT_CMD)KSD_CMD_USSD) OR current_cmd EQ AT_CMD_CUSD )
  {
    switch (ssShrdPrm.stb[sId].errCd)
    {
      case ERR_UNEXPECT_DATA:
        errCd  = CUSD_MOD_OperationNotSupported;
        break;
      default:
        errCd  = CUSD_MOD_TerminatedByNetwork;
        break;
    }
    for (idx = 0; idx < CMD_SRC_MAX; idx++)
    {
      R_AT( RAT_CUSD, (T_ACI_CMD_SRC)idx  )( errCd, NULL, 
                                ACI_NumParmNotPresent);
    }
  }
  else
  {
    R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )( current_cmd, error );
    cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_CME, current_cmd, -1, BS_SPEED_NotPresent, error );
  }
  
}


T_ACI_CME_ERR mapSSerrorCME(UBYTE SSerrCode)
{
  /*SRM 04/12/2003 Added decode function to map out SS error returns to CME errors*/
  /*It may be neccessary to map out other codes in the FAC.DOC sec 6.4 Error Codes*/
  T_ACI_CME_ERR mapped_SS2cme = CME_ERR_Unknown;
  
  TRACE_FUNCTION ("mapSSerrorCME(): map SS err to CME err");

  switch(SSerrCode)
  {
  case ERR_NEG_PWD_CHECK:
    mapped_SS2cme = CME_ERR_WrongPasswd;
    break;
    
  case ERR_TELE_SVC_NOT_PROV:
    mapped_SS2cme = CME_ERR_OpNotSupp;
    break;
  default:
    mapped_SS2cme = CME_ERR_Unknown;
    break;
  }
  return mapped_SS2cme;
      
}


GLOBAL SHORT cmhSS_TransFail( SHORT sId )
{
  T_ACI_KSIR     ksStat;      /* holds KS status */
  T_SS_CMD_PRM  *pSSCmdPrm;   /* points to SS command parameters */
  T_CC_CMD_PRM  *pCCCmdPrm;   /* points to CC command parameters */
  T_OWN          current_owner  = ssShrdPrm.stb[sId].srvOwn;
  USHORT         cmdBuf         = ssShrdPrm.stb[sId].curCmd;
  USHORT         idx            = 0;

  TRACE_FUNCTION ("cmhSS_TransFail()");

  pSSCmdPrm = &cmhPrm[current_owner].ssCmdPrm;

  /* an error occured: kill pending transactions... */
  pSSCmdPrm->mltyTrnFlg &= ~ssShrdPrm.mltyTrnFlg;
  psaSS_KillAllPendingTrn( );

  /* Marcus: Issue 1640: 27/01/2003: ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE; */
  
#ifdef SIM_TOOLKIT
  /* if SIM TOOLKIT initiated action send terminal response to SAT */
  if( current_owner EQ OWN_SRC_SAT )
  {
    /* send error message to SAT if not sent previously. Check has 
       been added to avoid sending multiple terminal response */
    if ((ssShrdPrm.stb[sId].failType EQ SSF_SS_ENT) OR
        (ssShrdPrm.stb[sId].failType EQ SSF_CCD_DEC))
    {
      psaSAT_SSRejComp(RSLT_NTW_UNAB_PROC);
    }

    /* free SS Entry */
    
    cmhPrm[current_owner].ssCmdPrm.mltyTrnFlg = 0;
        
    ssShrdPrm.stb[sId].ntryUsdFlg   = FALSE;
    ssShrdPrm.stb[sId].srvOwn       = OWN_SRC_INV;
    ssShrdPrm.stb[sId].curCmd       = AT_CMD_NONE;  /* Marcus: Issue 1640: 27/01/2003 */
    /* that should be enough to free the SS entry */
    return 0;
  }
#endif /* SIM_TOOLKIT */

  switch( cmdBuf )
  {
    case( AT_CMD_NONE ):
    {
      if ( ssShrdPrm.stb[sId].opCode EQ OPC_UNSTRUCT_SS_REQ )
      {
        for( idx = 0; idx < CMD_SRC_MAX; idx++ )
        {
          R_AT( RAT_CUSD, (T_ACI_CMD_SRC)idx ) ( CUSD_MOD_TerminatedByNetwork, NULL, 0 );
        }     
      }
      break;
    }
    case( AT_CMD_COLP ):
    {
      R_AT( RAT_COLP, (T_ACI_CMD_SRC)current_owner )
        ( COLP_STAT_Unknown, NULL, NULL, NULL, NULL, NULL);
      
      R_AT( RAT_OK, (T_ACI_CMD_SRC)current_owner )
        ( AT_CMD_COLP);
      break;
    }
    case( AT_CMD_CLIP ):
    {
      R_AT( RAT_CLIP, (T_ACI_CMD_SRC)current_owner )
        ( CLIP_STAT_Unknown, NULL, NULL, MNCC_PRES_NOT_PRES, NULL, NULL, NULL);

      R_AT( RAT_OK, (T_ACI_CMD_SRC)current_owner )
        ( AT_CMD_CLIP);
      break;
    }
  /* Following case added to fix issue ACI-SPR-23109 */
    case( AT_CMD_CPWD ):
    {
     /* To avoid two response being sent to the terminal, the error code
         has been mapped to the corresponding CME error and it is displayed
         to the terminal */
      T_ACI_CME_ERR mapped_SS2cme = mapSSerrorCME(ssShrdPrm.stb[sId].errCd);
      R_AT( RAT_CME, (T_ACI_CMD_SRC)current_owner )((T_ACI_AT_CMD) cmdBuf, mapped_SS2cme );
      cmh_logRslt ( (T_ACI_CMD_SRC)current_owner, RAT_CME,(T_ACI_AT_CMD) cmdBuf, -1, BS_SPEED_NotPresent, mapped_SS2cme );
      break;
    }
    case( AT_CMD_CLIR ):
    {
      pCCCmdPrm = &cmhPrm[current_owner].ccCmdPrm;

      R_AT( RAT_CLIR, (T_ACI_CMD_SRC)current_owner )
        ( pCCCmdPrm -> CLIRmode, CLIR_STAT_Unknown);

      R_AT( RAT_OK, (T_ACI_CMD_SRC)current_owner )
        ( AT_CMD_CLIR);
      break;
    }
    case( AT_CMD_CCFC ):
    case( AT_CMD_CCWA ):
    case( AT_CMD_CLCK ):
    {
      if (ssShrdPrm.stb[sId].failType EQ SSF_SS_ENT)
      {
        SSTransFail_default( sId );
      }
      else if( cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm->mltyTrnFlg))) /*test service flag and clear it*/
      {
        if( pSSCmdPrm -> mltyTrnFlg EQ 0 )  /* if no other service flags remaining*/
        {
          T_ACI_CME_ERR mapped_SS2cme = mapSSerrorCME(ssShrdPrm.stb[sId].errCd);

          R_AT( RAT_CME, (T_ACI_CMD_SRC)current_owner )( cmdBuf, mapped_SS2cme );
          cmh_logRslt ( (T_ACI_CMD_SRC)current_owner, RAT_CME, (T_ACI_AT_CMD)cmdBuf, 
		  	                     -1, BS_SPEED_NotPresent, mapped_SS2cme );
        }
      }
      else
      { 
        /* do nothing */ 
      }
      break;
    }
    case( KSD_CMD_CF ):
    case( KSD_CMD_CW ):
    case( KSD_CMD_CB ):
    case( KSD_CMD_CL ):
    case( KSD_CMD_PWD ):
    case( KSD_CMD_CCBS ):
    case( KSD_CMD_USSD ):
    {
      memset( &ksStat, 0, sizeof(ksStat));

      cmhSS_ksdBuildErrRslt( sId, &ksStat, KSD_NO_ERROR );

      if(check_ksd_error( current_owner, sId, &ksStat ))
      {
        /* Marcus: Issue 1640: 27/01/2003: ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE; */

        cmhPrm[current_owner].ssCmdPrm.mltyTrnFlg = 0;
      }
      else
      {
        /*
        ** CQ12314 : NDH : 23/9/2003
        ** Added srcID field to ksStat to enable called entity to determine the originator of the command
        ** and take appropriate action.  (eg to Activate Call Forwarding Icon)
        */
        ksStat.srcId = (T_ACI_CMD_SRC)current_owner;

#if defined (MFW)
        if (ksStat.srcId NEQ CMD_SRC_LCL)
        {
          R_AT( RAT_KSIR, CMD_SRC_LCL)( &ksStat );
        }
#endif
        R_AT( RAT_KSIR, (T_ACI_CMD_SRC)current_owner )( &ksStat );
      }

      SSTransFail_default( sId );
      break;
    }
    default:
    {
      SSTransFail_default( sId );
      break;
    }
  }

  /* Set extended error cause for KSD  and AT commands */
  if (ssShrdPrm.stb[sId].errCd)
  {
    causeMod  = P_CEER_ss;      /* Set the module for ceer cause */
    causeCeer = (SHORT)ssShrdPrm.stb[sId].errCd;
  }
  
  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
  ssShrdPrm.stb[sId].curCmd     = AT_CMD_NONE;  /* Marcus: Issue 1640: 27/01/2003 */
  return 0;
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_sendFie                |
+-------------------------------------------------------------------+

  PURPOSE : forward unsolicited facility responses from SS to terminal

*/
GLOBAL T_ACI_RETURN cmhSS_sendFie( T_ACI_FAC_DIR        tDirection,
                                  T_ACI_FAC_TRANS_TYPE tType,
                                  T_fac_inf           *fie )
{
  T_ACI_CMD_SRC tSrc;

  TRACE_EVENT( "cmhSS_sendFie()" );

  for( tSrc=CMD_SRC_LCL; tSrc<CMD_SRC_MAX; tSrc++ )  /* try over all sources */
  {
    if( cmhPrm[tSrc].ssCmdPrm.CSCNss_mode.SsCSCNModeState EQ SS_CSCN_MOD_STATE_ON )
    {
      switch (cmhPrm[tSrc].ssCmdPrm.CSCNss_mode.SsCSCNModeDirection)
      {
        case SS_CSCN_MOD_DIR_BOTH:
          break; /* printout regardless of direction */

        case SS_CSCN_MOD_DIR_IN:
          if( tDirection NEQ CSCN_FACILITY_DIRECTION_IN)
            continue; /* settings for source don't match, advance to next source */
          break;

        case SS_CSCN_MOD_DIR_OUT:
          if( tDirection NEQ CSCN_FACILITY_DIRECTION_OUT )
            continue; /* settings for source don't match, advance to next source */
          break;

        default:
          continue; /* illegal setting, advance to next source */
      }
      R_AT( RAT_CSSN, tSrc )( tDirection, tType, fie );
    }
  }
  return( AT_CMPL );
}


/* Used in Measure 217 */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_processKSDCF           |
+-------------------------------------------------------------------+
  PARAMETERS  : sId     - Index into ssShrdPrm.stb
                opCd    - KSD operation code
                ssInfo  - SS Information
  RETURN      : None

  PURPOSE : Process KSD CF. This is common code in cmhSS_SSActDeact and 
            cmhSS_SSRegistrated_Erased

*/

LOCAL void cmhSS_processKSDCF (SHORT sId, UBYTE opCd, T_ssInfo *ssInfo)
{
  T_CF_FEAT    *cfFeat;      /* points to CF feature list element */
  T_ACI_KSIR   ksStat;       /* holds KS status */

  cfFeat = (T_CF_FEAT *)ssLstBuf;
  memset( &ksStat, 0, sizeof(ksStat));

  ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

  ksStat.ksdCmd = KSD_CMD_CF;
  ksStat.ir.rKSCF.opCd  = opCd;
  ksStat.ir.rKSCF.ssErr = KSD_NO_ERROR;

  if( ssInfo->v_forwardingInfo )
  {
    cmhSS_ksdFillFwdRes( &ssInfo->forwardingInfo,
                         &ksStat, cfFeat );
#if defined(MFW) OR defined(FF_MMI_RIV)
    if (ksStat.ir.rKSCF.ssCd EQ KSD_SS_NONE)
      ksStat.ir.rKSCF.ssCd = ssShrdPrm.stb[sId].ssCode;   /* 1a 1b) help the BMI about the last code  (o2 - de) */
#endif
  }
#if defined(MFW) OR defined(FF_MMI_RIV)
  else 
  {
    ksStat.ir.rKSCF.ssCd = ssShrdPrm.stb[sId].ssCode;   /* 2a 2b) help the BMI about the last code (e+ - de) */
  }
#endif

  cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_CF);
}

/* Implements Measure 217 */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSActDeact             |
+-------------------------------------------------------------------+
  PARAMETERS  : sId     - Index into ssShrdPrm.stb
                opCd    - KSD operation code
                ssInfo  - SS Information
  RETURN      : None

  PURPOSE : Handles the SS Activate or Deactivate result.

*/

LOCAL void cmhSS_SSActDeact ( SHORT sId, UBYTE opCd, T_ssInfo *ssInfo )
{
  T_SS_CMD_PRM * pSSCmdPrm;   /* points to SS command parameters */
  T_ACI_KSIR     ksStat;      /* holds KS status */
  T_CB_INFO    * cbInfo;      /* points to CB feature list element */
  T_Cx_BSG     * cwBSG;       /* points to CW basic service list element */
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  USHORT          cmdBuf = ssShrdPrm.stb[sId].curCmd;

  TRACE_FUNCTION ("cmhSS_SSActDeact()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( cmdBuf )
  {
   /*
    *----------------------------------------------------------------
    * process result for +CCFC, +CLCK and +CCWA command
    *----------------------------------------------------------------
    */
    case( AT_CMD_CCFC ):
    case( AT_CMD_CLCK ):
    case( AT_CMD_CCWA ):

      pSSCmdPrm = &cmhPrm[owner].ssCmdPrm;

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      /* terminate command */
      if( cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm -> mltyTrnFlg)))
      {
        if( pSSCmdPrm -> mltyTrnFlg EQ 0 )  /* if last service */
        {

          R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
            ( (T_ACI_AT_CMD)cmdBuf );
          cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_OK, (T_ACI_AT_CMD)cmdBuf, 
                        -1, BS_SPEED_NotPresent,CME_ERR_NotPresent );
        }
      }
      break;

   /*
    *----------------------------------------------------------------
    * process result for KSD CF command
    *----------------------------------------------------------------
    */
    case( KSD_CMD_CF ):
      cmhSS_processKSDCF ( sId, opCd, ssInfo);
      break;

   /*
    *----------------------------------------------------------------
    * process result for KSD CB command
    *----------------------------------------------------------------
    */
    case( KSD_CMD_CB ):

      cbInfo = (T_CB_INFO *)ssLstBuf;
      memset( &ksStat, 0, sizeof(ksStat));

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      ksStat.ksdCmd = KSD_CMD_CB;
      ksStat.ir.rKSCF.opCd  = opCd;
      ksStat.ir.rKSCF.ssErr = KSD_NO_ERROR;

      if( ssInfo->v_callBarringInfo )
      {
        cmhSS_ksdFillCbRes( &ssInfo->callBarringInfo,
                            &ksStat, cbInfo );
      }

      cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_CB);
      break;

   /*
    *----------------------------------------------------------------
    * process result for KSD CW command
    *----------------------------------------------------------------
    */
    case( KSD_CMD_CW ):

      cwBSG = (T_Cx_BSG *)ssLstBuf;
      memset( &ksStat, 0, sizeof(ksStat));

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      ksStat.ksdCmd = KSD_CMD_CW;
      ksStat.ir.rKSCW.opCd  = opCd;
      ksStat.ir.rKSCW.ssErr = KSD_NO_ERROR;

      if( ssInfo->v_ssData )
      {
        cmhSS_ksdFillCwRes( &ssInfo->ssData,
                            &ksStat, cwBSG );
      }
      else if (opCd EQ KSD_OP_ACT)
      {
        ksStat.ir.rKSCW.ssCd  = KSD_SS_NONE;
        ksStat.ir.rKSCW.ssSt  = KSD_ST_NONE;
      }

      cmhSS_ksdCBCF_Res (sId, &ksStat, KSD_CMD_CW);
      break;
  }

/*
 *-------------------------------------------------------------------
 * set service table entry to unused
 *-------------------------------------------------------------------
 */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;

}

/* Implements Measure 215 */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_SSRegistrated_Erased   |
+-------------------------------------------------------------------+
  PARAMETERS  : sId     - Index into ssShrdPrm.stb
                opCd    - KSD operation code
                ssInfo  - SS Information
  RETURN      : None

  PURPOSE : Handle SS registration or erasure result.

*/

LOCAL void cmhSS_SSRegistrated_Erased (SHORT sId,
                                       UBYTE opCd, 
                                       T_ssInfo *ssInfo)
{
  T_SS_CMD_PRM *pSSCmdPrm;   /* points to SS command parameters */
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;

  TRACE_FUNCTION ("cmhSS_SSRegistrated_Erased()");

  /* check for command context */
  switch( ssShrdPrm.stb[sId].curCmd )
  {
    /* process result for +CCFC command */
    case( AT_CMD_CCFC ):

      pSSCmdPrm = &cmhPrm[owner].ssCmdPrm;

      ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

      
      TRACE_EVENT_P2( "SS_INFO_VALIDITY:%d During operation %d", 
                                ssInfo->v_forwardingInfo, opCd);
      
      /* terminate command */
      if( cmhSS_tstAndUnflagTrn( sId, &(pSSCmdPrm -> mltyTrnFlg)))
      {
        if( pSSCmdPrm -> mltyTrnFlg EQ 0 )  /* if last service */
        {
          R_AT( RAT_OK, (T_ACI_CMD_SRC)owner )
            ( AT_CMD_CCFC );
          cmh_logRslt ((T_ACI_CMD_SRC)owner, RAT_OK, AT_CMD_CCFC, -1,
                       BS_SPEED_NotPresent,CME_ERR_NotPresent );
        }
      }
      break;

    /* process result for KSD CF command */
      /*lint -e{408}*/ 
    case ( KSD_CMD_CF ) :
      cmhSS_processKSDCF ( sId, opCd, ssInfo);      
      break;
  }

  /* set service table entry to unused */
  ssShrdPrm.stb[sId].ntryUsdFlg = FALSE;
}

/* Implements Measure 209, 210, 214 */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_ksdCBCF_Res            |
+-------------------------------------------------------------------+
  PARAMETERS  : sId     - Index into ssShrdPrm.stb
                ksStat  - holds KS status 
                ksdCmd  - KSD command identifier
  RETURN      : None

  PURPOSE : Sends result for for KSD CB or CFcommand.

*/

LOCAL void cmhSS_ksdCBCF_Res (SHORT sId, T_ACI_KSIR  *ksStat, T_ACI_KSD_CMD ksdCmd)
{
  T_OWN           owner  = ssShrdPrm.stb[sId].srvOwn;
  USHORT          cmdBuf = ssShrdPrm.stb[sId].curCmd;

  if(check_ksd_error( owner, sId, ksStat ))
  {
    ssShrdPrm.stb[sId].curCmd = AT_CMD_NONE;

    cmhPrm[owner].ssCmdPrm.mltyTrnFlg = 0;

    R_AT( RAT_CME, (T_ACI_CMD_SRC)owner )
      ( (T_ACI_AT_CMD)cmdBuf, CME_ERR_NotPresent );
  }
  else
  {
      /*
      ** CQ12314 : NDH : 23/9/2003
      ** Added srcID field to ksStat to enable called entity to determine the originator of the command
      ** and take appropriate action.  (eg to Activate Call Forwarding Icon)
      */
      ksStat->srcId = (T_ACI_CMD_SRC)owner;
    
    #if defined (MFW)
      if (ksStat->srcId NEQ CMD_SRC_LCL)
      {
        R_AT( RAT_KSIR, CMD_SRC_LCL)( ksStat );
      }
    #endif
        
    R_AT( RAT_KSIR, (T_ACI_CMD_SRC)owner ) ( ksStat );

    if(ksdCmd NEQ KSD_CMD_NONE)
    {
      /* terminate command */
      R_AT( RAT_OK, (T_ACI_CMD_SRC)owner ) (ksdCmd);
      cmh_logRslt ( (T_ACI_CMD_SRC)owner, RAT_OK, (T_ACI_AT_CMD)KSD_CMD_CF, -1,
                    BS_SPEED_NotPresent,CME_ERR_NotPresent );
    }
  }
}
/* Implements Measure 76 */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_SSR                      |
|                            ROUTINE : cmhSS_prepareUSSDRes         |
+-------------------------------------------------------------------+
  PARAMETERS  : ussdArg - USSD argument
                dcs - Data Coding Scheme        
  RETURN      : Filled T_ACI_USSD_DATA structure

  PURPOSE : prepares USSD Response.

*/
LOCAL T_ACI_USSD_DATA* cmhSS_prepareUSSDRes(T_ussdArg *ussdArg, SHORT *dcs)
{
  T_ACI_USSD_DATA   *ussd = NULL;

  TRACE_FUNCTION ("cmhSS_prepareUSSDRes()");

  if( ussdArg->v_ussdDataCodingScheme )
  {
    *dcs = ussdArg->ussdDataCodingScheme;
  }

  if( ussdArg->v_ussdString )
  {
    MALLOC(ussd, sizeof(T_ACI_USSD_DATA));
    
    /* SDU offset is assumed to be zero for ussd string */
    ussd->len = ussdArg->ussdString.l_ussdString>>3;
    if( cmh_getAlphabetCb( (UBYTE)*dcs ) EQ 0 ) /* 7bit alphabet */
    {
      ussd->len = utl_cvt7To8( ussdArg->ussdString.b_ussdString,
                              ussd->len,
                              ussd->data,
                              0 );
    }
    else
    {
      memcpy( ussd->data, ussdArg->ussdString.b_ussdString,
              ussd->len );
    }

    TRACE_EVENT_P1("USSD str len: %d", ussd->len);
    ussd->data[ussd->len]=0x00;
  }
  return ussd;
}
/*==== EOF ========================================================*/