view src/aci2/aci/cmh_ccr.c @ 581:a0a45c5eb3ef

gsmcomp.c: bumping trace partition size to 220 like in gprscomp.c This change is safe in terms of RAM usage because all of these partition pools have already been moved from XRAM to IRAM earlier, and our IRAM usage in VO configs is currently quite low - the one near the limit is XRAM on C11x.
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 29 Jan 2019 03:52:49 +0000
parents 93999a60b835
children
line wrap: on
line source

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

#ifndef CMH_CCR_C
#define CMH_CCR_C
#endif

/*==== INCLUDES ===================================================*/

#include "aci_all.h"
#include "aci_cmh.h"
#include "ati_cmd.h"
#include "aci_cmd.h"
#include "aci_mem.h"
#include "phb.h"
#include "l4_tim.h"
#include "aci_lst.h"


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

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

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

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

#ifdef FAX_AND_DATA

#include "psa_ra.h"
#include "cmh_ra.h"
#include "psa_l2r.h"
#include "cmh_l2r.h"
#include "psa_tra.h"

#ifdef FF_FAX
#include "psa_t30.h"
#include "cmh_t30.h"
#endif /* FF_FAX */

#endif /* FAX_AND_DATA */

#ifdef SIM_TOOLKIT
#include "psa_sat.h"
#include "cmh_sat.h"
#include "psa_sim.h"
#endif    /* of #ifdef SIM_TOOLKIT */

#include "aoc.h"
#include "audio.h"

#if defined (FF_WAP) || defined (FF_TCP_IP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E)
#include "wap_aci.h"
#include "psa_ppp_w.h"
#include "cmh_ppp.h"
#endif /* of FF_WAP or FF_TCP_IP || FF_GPF_TCPIP FF_SAT_E */

#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
#include "psa_tcpip.h"
#include "cmh_ipa.h"
#endif /* CO_UDP_IP || FF_GPF_TCPIP */

#ifdef FF_GPF_TCPIP
#include "dcm_utils.h"
#include "dcm_state.h"
#include "dcm_env.h"
#endif
#include "dcm_f.h"
#ifdef UART
#include "psa_uart.h"
#include "cmh_uart.h"
#endif /*UART*/

#ifdef FF_PSI
#include "psa_psi.h"
#include "cmh_psi.h"
#endif /*FF_PSI*/

#include "cmh_phb.h"

#include "psa_sim.h"
#include "cmh_sim.h"

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

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

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

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

#if defined (FF_WAP) || defined (FF_TCP_IP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E)
ULONG ipAddress;

GLOBAL SHORT cmhCC_PPP_Established (ULONG ip_address,USHORT max_receive_unit,
                                    ULONG dns1, ULONG dns2);
GLOBAL SHORT cmhCC_PPP_Terminated (void);
#endif

#ifdef CO_UDP_IP 
GLOBAL SHORT cmhCC_IPA_Configurated (void);
GLOBAL SHORT cmhCC_UDPA_Configurated (void);
GLOBAL SHORT cmhCC_UDPA_Deconfigurated (void);
#endif /* CO_UDP_IP */


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

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallAlerted            |
+-------------------------------------------------------------------+

  PURPOSE : called party is alerted

*/

GLOBAL void cmhCC_CallAlerted ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  UBYTE idx;

  TRACE_FUNCTION ("cmhCC_CallAlerted()");

/*
 *-------------------------------------------------------------------
 * process event
 *-------------------------------------------------------------------
 */
  if (ctb->prgDesc EQ PROG_NOT_PRES)
  {
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CPI, idx )
        ( cId+1,
          CPI_MSG_Alert,
          (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
          (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
          ctb->curCs);
    }
  }
  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallProceeding         |
+-------------------------------------------------------------------+

  PURPOSE : call proceed indication

*/

GLOBAL void cmhCC_CallProceeding ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_ACI_CPI_MSG msgType;
  SHORT idx;

  TRACE_FUNCTION ("cmhCC_CallProceeding()");

/*
 *-------------------------------------------------------------------
 * process event
 *-------------------------------------------------------------------
 */
  switch( ccShrdPrm.msgType )
  {
  case( MT_SETUP ): msgType = CPI_MSG_Setup; break;
  case( MT_DISC  ):
    switch (ctb->calStat)
    {
    case NO_VLD_CS:
    case CS_ACT_REQ:
    case CS_CPL_REQ:
    case CS_DSC_REQ:
      break;
    default:
      return;
    }
    msgType = CPI_MSG_Disc;
    break;
  case( MT_ALRT  ): msgType = CPI_MSG_Alert; break;
  case( MT_PROC  ): msgType = CPI_MSG_Proc;  break;
  case( MT_PROGR ): msgType = CPI_MSG_Progr; break;
  /* case( MT_CONN  ): msgType = CPI_MSG_Conn;  break; */
  case( MT_CONN  ): return; /* CPI is generated in cmhCC_CallConnected */
  default:          TRACE_EVENT("UNEXP MSG TYPE IN CC SHRD PARM");
                    return;
  }

/*  ctb->curCs = MNCC_CAUSE_NO_MS_CAUSE; */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT( RAT_CPI, idx )
      ( cId+1,
        msgType,
        (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
        (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
        ctb->curCs);
  }

  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallConnected          |
+-------------------------------------------------------------------+

  PURPOSE : call is connected

*/

GLOBAL void cmhCC_CallConnected ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  CHAR numBuf[MAX_CC_CALLING_NUMBER+1]; /* buffers calling number + '\0' */
  CHAR subBuf[SUB_LENGTH+1];  /* buffers subaddress 'subaddress\0' */
  T_ACI_TOA toaBuf;           /* buffers type of address */
  T_ACI_TOS tosBuf;           /* buffers type of subaddress */
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */
  SHORT idx;
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_CallConnected()");

  /* check for command context */
  switch(ctb->curCmd)
  {
  case(AT_CMD_D):
  case(AT_CMD_A):
  case(AT_CMD_CHLD):
    break;

  default:
    TRACE_EVENT_P1("cmhCC_CallConnected(): wrong command context %d", ctb->curCmd);
    return;
  }

  /* call progress information */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT( RAT_CPI, idx )
      (cId+1,
       CPI_MSG_Conn,
       (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
       (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
       ctb->curCs);
  }

  /* process event for D, A and +CHLD command */
  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;

  if (ctb->curCmd EQ AT_CMD_D)
  {
    /* Check if user allows Connected Line Presentation: FTA 31.1.3.1 */
    switch (ctb->clgPty.present)
    {
      case (PRES_PRES_ALLOW): /* presentation allowed FTA 31.1.3.1 */
        TRACE_EVENT ("cmhCC_CallConnected(): presentation allowed !");
        break;

      case (PRES_NOT_PRES):
        TRACE_EVENT ("cmhCC_CallConnected(): presentation not present !");
        break;

      case (PRES_PRES_REST): /* presentation restricted FTA 31.1.4.2 procedure 1 */
        TRACE_EVENT ("cmhCC_CallConnected(): presentation restricted !");
        /*
         * R_AT( RAT_COLR, ccShrdPrm.???.???.??? )
         *  ( COLR_STAT_??? );
         */
        break;

      case (PRES_NUMB_NOT_AVAIL): /* number not available due to interworking FTA 31.1.4.2 procedure 2 */
        TRACE_EVENT ("cmhCC_CallConnected(): number not available due to interworking !");
        /*
         * R_AT( RAT_COLR, ccShrdPrm.???.???.??? )
         *  ( COLR_STAT_??? );
         */
        break;

      default:
        TRACE_EVENT ("[ERR] cmhCC_CallConnected(): pCtbNtry->clgPty.present = UNKNOWN");
        return;

    }

    if ((ctb->clgPty.present NEQ PRES_NOT_PRES)  /* any .present indicator received from MSC? */
    AND (ctb->clgPty.c_num EQ 0) )               /* but no number available? */
    {
      ;   /* do nothig */
    }
    else
    {
      /*
       * This function call (rAT_PlusCOLP) informs MWF/BMI about
       * presentation of the called number on display.
       * If MFW did not receive this function call, then it should
       * not display the number after querying the call state with
       * qAT_PercentCAL() where it gets the typed in called number, unfortunately
       */
      R_AT( RAT_COLP, ctb->curSrc )
        ( COLP_STAT_NotPresent,
          psaCC_ctbClrAdr2Num( cId, numBuf, sizeof (numBuf) ),
          cmhCC_ctbGetClrNumTyp( cId, &toaBuf ),
          psaCC_ctbClrAdr2Sub( cId, subBuf ),
          cmhCC_ctbGetClrSubTyp( cId, &tosBuf ),
          psaCC_ctbGetAlpha( cId) );
    }
  }


  /* reset CMOD to single mode */
  ccShrdPrm.CMODmode = CMOD_MOD_Single;

  switch(calltype)
  {
  /* Speech Call */
  case( VOICE_CALL ):
    cmdBuf = ctb->curCmd;
    srcBuf = ctb->curSrc;

    /* reset CMOD to single mode */
    if( ctb->BC[1].bearer_serv NEQ BEARER_SERV_NOT_PRES )
    {
      ccShrdPrm.CMODmode = CMOD_MOD_Single;
    }

    /*
     *  check if connect is expected
     */
    if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
    {
      if( pCCCmdPrm -> mltyCncFlg EQ 0 )  /* if last call */
      {

#ifdef SIM_TOOLKIT
        if( ctb->SATinv )
        {
          cmhSAT_CallCncted();
          ctb->SATinv = FALSE; /* unsent */
        }
#endif /* SIM_TOOLKIT */
        if(!cmhCC_atdsendok(cId)) /* if OK hasn't been sent right after MNCC_SETUP_REQ, then send it now */
        {
          /* needed for RAT_OK in MFW... Temp until tasks are separated */
          cmhCC_PrepareCmdEnd (cId, NULL, NULL);

          R_AT( RAT_OK, srcBuf ) ( cmdBuf );
        }

        /* log result */
        cmh_logRslt ( srcBuf, RAT_OK, cmdBuf, (SHORT)(cId+1), -1, -1 );
      }
    }
    cmhCC_PrepareCmdEnd (cId, NULL, NULL);
    break;

#if defined (FAX_AND_DATA) AND defined (DTI)

  /* in case of a supported data call */
  case(TRANS_CALL):
  case(NON_TRANS_CALL):
  case(FAX_CALL):
#ifdef FF_TCP_IP
  /* PPP call initialisation (AAA - PPP - L2R) */
  case(PPP_CALL):
#endif /* FF_TCP_IP */
   /* wait for TCH if not assigned */
    if( ccShrdPrm.TCHasg )
    {
      /* activate RA connection: in case of failure clear call ! */
      ccShrdPrm.datStat = DS_ACT_REQ;

      if (cmhRA_Activate( ctb->curSrc, ctb->curCmd, cId ) NEQ AT_EXCT)
      {
        TRACE_EVENT("RA ACTIVATION FAILURE -> DISC CALL");
        ccShrdPrm.datStat = DS_IDL;
        ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
        psaCC_ClearCall (cId);
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
          /* check impact for SAT commands */
        cmhSAT_OpChnCSDDown( cId, TPL_NONE );
#endif /* SIM TOOLKIT AND FF_SAT_E */
      }
    }
    break;

#if defined(CO_UDP_IP) OR defined(FF_GPF_TCPIP)
#ifdef CO_UDP_IP
  case(UDPIP_CALL):
#endif
#ifdef FF_GPF_TCPIP
  case(TCPIP_CALL):
#endif
    /* wait for TCH if not assigned */
    if( ccShrdPrm.TCHasg )
    {
      if (wap_state NEQ Wap_Not_Init) /* release call */
      {
        TRACE_EVENT("FATAL ERROR in cmhCC_CallConnected: WAP Call already in process");
        ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
        psaCC_ClearCall (cId);
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)  
        cmhSAT_OpChnCSDDown( cId, UDP );
#endif /* SIM TOOLKIT AND FF_SAT_E */
        break;
      }
      else
      {
        TRACE_EVENT("WAP call initialisation");
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
        if( cmhSAT_OpChnChckCSD(UDP) )
        {
          psaTCPIP_Activate(ctb->curSrc, 0,
                            cId,
                            TCPIP_ACT_OPTION_V4 | TCPIP_ACT_OPTION_UDP,
                            TCPIP_CONNECTION_TYPE_CSD_WAP,
                            cmhSAT_OpChnUDPActiveCsd) ;
        }
        else
#endif /* SIM TOOLKIT AND FF_SAT_E */
        {
          if(is_gpf_tcpip_call())
          {
            psaTCPIP_Activate(ctb->curSrc, 0 /* Change this! */,
                            cId,
                              TCPIP_ACT_OPTION_V4 | TCPIP_ACT_OPTION_TCPIP,
                            TCPIP_CONNECTION_TYPE_CSD_WAP,
                            psaTCPIP_act_csd_callback) ;
        }
          else
          {
            psaTCPIP_Activate(ctb->curSrc, 0 /* Change this! */,
                              cId,
                              TCPIP_ACT_OPTION_V4 | TCPIP_ACT_OPTION_UDP,
                              TCPIP_CONNECTION_TYPE_CSD_WAP,
                              psaTCPIP_act_csd_callback) ;
          }
        }
      }
    }
    break;
#endif /* defined(WAP) OR defined(FF_GPF_TCPIP) */

 /* in case of an unsupported data call */
  case(UNSUP_DATA_CALL):
    TRACE_EVENT("UNSUPPORTED DATA CALL -> DISC CALL");
    ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
    psaCC_ClearCall (cId);
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E) 
    /* check impact for SAT commands */
    cmhSAT_OpChnCSDDown( cId, TPL_NONE );
#endif /* SIM TOOLKIT AND SAT_SAT_E */
    break;

#endif  /* of #ifdef FAX_AND_DATA */

  default:
    TRACE_ERROR("Wrong call type");
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : process_CHLDaddInfo          |
+-------------------------------------------------------------------+

  PURPOSE : Local function: processes parameter CHLDaddInfo (continue action that
            had to wait for a call to be connected first).
*/
/* Held call is being disconnected */
#define DISCONNECT_HELD (0)
/* Call is being put on hold */
#define CALL_HELD       (1)
/* Multyparty call is being put on hold */
#define MTPTY_HELD      (2)

LOCAL void process_CHLDaddInfo( UBYTE srcId, UBYTE context )
{
  /* param context allows to differentiate some special case */
  SHORT addId;
  T_CC_CMD_PRM *pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  TRACE_FUNCTION("process_CHLDaddInfo( )");

  for( addId = 0; !((pCCCmdPrm -> mltyCncFlg >> addId) & 0x01); addId++ )
    ;

  switch( CHLDaddInfo )
  {
    case( CHLD_ADD_INFO_ACC_CAL ):
      cmhCC_AcceptCall(addId, srcId, AT_CMD_CHLD);
      return;

    case (CHLD_ADD_INFO_DIAL_CAL):
      cmhCC_NewCall(addId, srcId, AT_CMD_D);
      return;

    case( CHLD_ADD_INFO_RTV_CAL ):
      if(context NEQ CALL_HELD)
      {
        cmhCC_RetrieveCall(addId, srcId);
        return;
      }
      break;

    case (NO_CHLD_ADD_INFO):
      if(context EQ DISCONNECT_HELD)
      {
        return; /* May happen for CCBS recall, disconnecting the active call */
      }
      break;
  }

  TRACE_EVENT("UNEXP ADD CHLD INFO");
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallDisconnected       |
+-------------------------------------------------------------------+

  PURPOSE : call is disconnected: process event for D and A command, abort command or no command
*/

#ifdef SIM_TOOLKIT
LOCAL void cmhCC_CallDisc_whiledialling_sat(SHORT cId, BOOL *send_atresult)
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  UBYTE         network_cause;

  if( !ctb->SATinv )
  {
    return;
  }

  TRACE_FUNCTION("cmhCC_CallDisc_whiledialling_sat");

  switch(ctb->curCmd)
  {
  case( AT_CMD_A ):
    /* if connect is expected */
    if( cmhPrm[ctb->curSrc].ccCmdPrm.mltyCncFlg NEQ 0 )
    {
      if( ctb->SATinv & SAT_REDIAL )
      {
        ctb->calStat = CS_SAT_REQ;
        return;
      }

      /* return network error cause GSM 11.14 / 12.12.3 */
      if(GET_CAUSE_VALUE(ctb->nrmCs) EQ NOT_PRESENT_8BIT)
      {
        network_cause = ADD_NO_CAUSE;
      }
      else
        network_cause = GET_CAUSE_VALUE(ctb->nrmCs)|0x80;

      *send_atresult = cmhSAT_NtwErr(network_cause);
    }
    break;

  case( AT_CMD_ABRT ):
    /* if disconnect is expected */
    if( cmhPrm[ctb->curSrc].ccCmdPrm.mltyDscFlg NEQ 0 )
    {
      cmhSAT_UserClear();
    }
    break;
#ifdef FF_SAT_E
  default:
    cmhSAT_OpChnCSDDown( cId, TPL_DONT_CARE );
    break;
#endif /* FF_SAT_E */
  }
}
#endif /*#ifdef SIM_TOOLKIT*/
/*
+------------------------------------------------------------------------------
|   Function    :  cmhCC_CallDisc_connectingphase
+------------------------------------------------------------------------------
|   Description :  This function checks on call type and disconnects the
|                  different calltypes.
|
|   Parameters  :  call id
|
|   Return      :
|
+------------------------------------------------------------------------------
*/

LOCAL void cmhCC_CallDisc_connectingphase ( SHORT cId )
{
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  T_CC_CALL_TBL  *ctb     = ccShrdPrm.ctb[cId];
  BOOL           atRslt   = TRUE;        /* flags to send a AT result code */

  TRACE_FUNCTION("cmhCC_CallDisc_connectingphase");

  /* reset CMOD to single mode */
  ccShrdPrm.CMODmode = CMOD_MOD_Single;

#ifdef SIM_TOOLKIT
  /* handling of SAT invoked call */
  cmhCC_CallDisc_whiledialling_sat(cId, &atRslt);
#endif /* SIM_TOOLKIT */

  /* Unflag Multiconnect/disconnect Flags */
  if( ctb->curSrc NEQ CMD_SRC_NONE )
  {
    cmhCC_tstAndUnflagCall( cId,
                            &cmhPrm[ctb->curSrc].ccCmdPrm.mltyCncFlg );
    cmhCC_tstAndUnflagCall( cId,
                            &cmhPrm[ctb->curSrc].ccCmdPrm.mltyDscFlg );
  }

  /* CCBS handling */
  if( ctb->curCmd EQ AT_CMD_D      AND
      ctb->CCBSstat EQ CCBSS_PSSBL )
  {
    cmhrat_ccbs( CMD_SRC_MAX, CCBS_IND_Possible,
                 CCBS_STAT_NotPresent, NULL );
  }

  switch( calltype )
  {
    case( VOICE_CALL ): /* voice call */
      /* CSSU indications handling */
      if( ctb->calStat EQ CS_HLD )
      {
        if( ctb->curCmd NEQ AT_CMD_NONE )
        {
           send_CSSX_notification(cId,
                              CSSX_CODE_HeldCallRel,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);
        }
      }
      break;

#if defined (FAX_AND_DATA) AND defined (DTI)
    case(TRANS_CALL):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhTRA_Deactivate ();
        return;
      }
      break;

    case(NON_TRANS_CALL):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhL2R_Deactivate ();
        return;
      }
      break;

#ifdef FF_FAX
    case( FAX_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhT30_Deactivate ();
        return;
      }
      break;
#endif /* FF_FAX */

#ifdef CO_UDP_IP 
    case(UDPIP_CALL):
    /* check if a UDP/IP call is in process... If yes then end call */
      if (ccShrdPrm.datStat NEQ DS_IDL)
      {
        ccShrdPrm.datStat = DS_STOP_REQ;

        /* Check command context to know if lower layers of PPP already are down or not */
        if(ctb->curCmd EQ AT_CMD_NONE OR
           ctb->curCmd EQ AT_CMD_D )
        {
          /* If PPP connected - send terminate request to PPP */
          if(pppShrdPrm.state EQ PPP_ESTABLISHED)
          {
            cmhPPP_Terminate(DWN);
          }
          return;
        }
      }
      break;
#endif  /* CO_UDP_IP */

#endif /* of #ifdef FAX_AND_DATA */
  }

  /* Command is done: send response to user if not suppressed */
  /* if(atRslt) cmhCC_SndDiscRsn( cId ); */  /* to pass 26.8.1.2.8.1 */
}

LOCAL void call_disconnected_data_call(T_CC_CALL_TYPE calltype, SHORT cId)
{
  TRACE_FUNCTION("call_disconnected_data_call");

  /* Local disconnection for PPP if peer shuts down the line
     instead of normal PPP shutdown */
  switch( calltype )
  {
#if defined (FAX_AND_DATA) AND defined (DTI)
 /* check if a WAP call is in process... If yes then end call */
#if defined(CO_UDP_IP) || defined(FF_TCP_IP)

#ifdef CO_UDP_IP
  case(UDPIP_CALL):
#endif /* CO_UDP_IP */

#if defined(FF_GPF_TCPIP)
  case (TCPIP_CALL):
#endif /* FF_GPF_TCPIP */

#ifdef FF_TCP_IP
  case PPP_CALL:
  pppShrdPrm.is_PPP_CALL = FALSE;
  TRACE_EVENT ("is_PPP_CALL resetted");
#endif /* FF_TCP_IP */

    if (ccShrdPrm.datStat NEQ DS_IDL)
    {
      ccShrdPrm.datStat = DS_STOP_REQ;

      /* Only local disconnection is possible in this case, the call is already disconnected !
      if(pppShrdPrm.state EQ PPP_ESTABLISHED)
        cmhPPP_Terminate(UP); */

      if((pppShrdPrm.state EQ PPP_ESTABLISHED) OR
         (pppShrdPrm.state EQ PPP_ESTABLISH)   OR
         (pppShrdPrm.state EQ PPP_TERMINATE))
      {
        cmhPPP_Terminate(DWN);
      }
      else if (wap_state > Wap_Not_Init      AND
               wap_state <= UDPA_Deactivation)
      {
        cmhPPP_Terminated();   /* Trigger termination of TCPIP if PPP did not yet start (ACI-FIX-9317)*/
      }
    }
    break;
#endif  /* of WAP || FF_TCP_IP || SAT E */

  case(TRANS_CALL):
  case(NON_TRANS_CALL):
    if( ccShrdPrm.datStat NEQ DS_IDL )
    {
      ccShrdPrm.datStat = DS_STOP_REQ;
      if(calltype EQ TRANS_CALL)
      {
        cmhTRA_Deactivate ();
      }
      else
      {
        cmhL2R_Deactivate ();
      }
    }
    break;
#endif /* FAX_AND_DATA */

  default:
    break;
  } /* end switch */
} /* end switch */

LOCAL void cmhCC_CallDisc_userinitiated ( SHORT cId )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  T_CC_CALL_TBL  *ctb     = ccShrdPrm.ctb[cId];
#ifdef FF_PSI
  T_ACI_DTI_PRC_PSI  *src_infos = NULL;
#endif /*FF_PSI*/
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */

  TRACE_FUNCTION("cmhCC_CallDisc_userinitiated");

  /* process event for H and +CHUP command */
  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;

  /* reset CMOD to single mode */
  ccShrdPrm.CMODmode = CMOD_MOD_Single;

  call_disconnected_data_call(calltype, cId);

  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  /* if ATH before the call is connected, the flag must be cleared */
  cmhCC_tstAndUnflagCall (cId, &(pCCCmdPrm -> mltyCncFlg));

  /* check if disconnect is expected */
  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyDscFlg)))
  {
#if defined (FF_WAP) || defined (FF_SAT_E)
    /* Check if the WAP stack is down  */
    if((pCCCmdPrm -> mltyDscFlg EQ 0)               AND
       (ccShrdPrm.wapStat       EQ CC_WAP_STACK_DOWN))
#else
    if( pCCCmdPrm -> mltyDscFlg EQ 0 )
#endif /* WAP || SAT E */
    /****************/
    /* if last call */
    /****************/
    {
#ifdef SIM_TOOLKIT
      if( ctb->SATinv )
      {
        cmhSAT_StartPendingCall( );
      }
      else
#endif  /* SIM_TOOLKIT */
      {
        if (cmdBuf EQ AT_CMD_Z)
        {
          cmh_Reset ( srcBuf, TRUE );
          R_AT(RAT_Z, srcBuf)();
        }
#if defined (FF_PSI) AND defined (DTI)
        src_infos = find_element (psi_src_params, srcBuf, cmhPSItest_srcId);
        if (src_infos EQ NULL)
#endif /*FF_PSI*/
#ifdef UART
        {
           if (uartShrdPrm.dtr_clearcall EQ TRUE)
           {
              uartShrdPrm.dtr_clearcall = FALSE;
              R_AT( RAT_NO_CARRIER, srcBuf ) ( cmdBuf, cId+1 );
              cmh_logRslt ( srcBuf,
              RAT_NO_CARRIER, cmdBuf, (SHORT)(cId+1), -1, -1 );
           }
           else
           {
              R_AT( RAT_OK, srcBuf ) ( cmdBuf );

              /* log result */
              cmh_logRslt ( srcBuf,
              RAT_OK, cmdBuf, (SHORT)(cId+1), -1, -1 );
          }
        }
#endif /*UART*/
#if defined (FF_PSI) AND defined (DTI)
        else
        {
           if (psiShrdPrm.dtr_clearcall EQ TRUE)
           {
              psiShrdPrm.dtr_clearcall = FALSE;
              R_AT( RAT_NO_CARRIER, srcBuf ) ( cmdBuf, cId+1 );
              cmh_logRslt ( srcBuf,
              RAT_NO_CARRIER, cmdBuf, (SHORT)(cId+1), -1, -1 );
           }
           else
           {
              R_AT( RAT_OK, srcBuf ) ( cmdBuf );

              /* log result */
              cmh_logRslt ( srcBuf,
              RAT_OK, cmdBuf, (SHORT)(cId+1), -1, -1 );
          }
         }
#endif /*FF_PSI*/
        }
      }
   }

  /* inform call owner about disconnect */
  if( srcBuf EQ ctb->calOwn
#ifdef SIM_TOOLKIT
    AND
      !ctb->SATinv )
#else
    )
#endif
  {
    /* do nothing: owner knows already... */
    /* EXCEPT if !ctb->SATinv: a SAT call setup has been started, and all previous
    calls had to be disconnected (because of SAT command qualifer) */
  }
  else
  {
    R_AT( RAT_NO_CARRIER, ctb->calOwn ) ( AT_CMD_NONE, cId+1 );
    cmh_logRslt ( srcBuf, RAT_NO_CARRIER, cmdBuf,
                  (SHORT)(cId+1), -1, -1 );
  }
}

/* process disconnection of an held call: +CHLD command context */
LOCAL void cmhCC_CallDisc_heldcall ( SHORT cId )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  T_CC_CALL_TBL  *ctb     = ccShrdPrm.ctb[cId];
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */

  TRACE_FUNCTION("cmhCC_CallDisc_heldcall");

  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;

  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  if( pCCCmdPrm -> mltyDscFlg EQ 0 AND
      pCCCmdPrm -> mltyCncFlg EQ 0     )  /* if last call */
  {
    R_AT( RAT_OK, srcBuf ) ( cmdBuf );

    /* log result */
    cmh_logRslt ( srcBuf, RAT_OK,
                  cmdBuf, (SHORT)(cId+1), -1, -1 );
  }
  /* check if disconnect is expected */
  else if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyDscFlg)))
  {
    if( pCCCmdPrm -> CHLDmode EQ CHLD_MOD_RelActAndAcpt AND
        pCCCmdPrm -> mltyCncFlg AND pCCCmdPrm -> mltyDscFlg EQ 0 )
    {
      process_CHLDaddInfo( srcBuf, DISCONNECT_HELD );
    }
    else if( pCCCmdPrm -> CHLDmode EQ CHLD_MOD_Ect )
    {
      cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)); /* now disconnected */
    }

    if( pCCCmdPrm -> mltyDscFlg EQ 0 AND
        pCCCmdPrm -> mltyCncFlg EQ 0     )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }
  /* check if disconnect is unexpected */
  else if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    pCCCmdPrm -> mltyCncFlg = 0;        /* unflag calls */

    R_AT( RAT_CME, srcBuf ) ( cmdBuf, CME_ERR_NotPresent );

    /* log result */
    cmh_logRslt ( srcBuf, RAT_CME, cmdBuf,
                  -1, -1, CME_ERR_NotPresent );
  }

  /* inform call owner about disconnect */
  if( srcBuf NEQ (UBYTE)CMD_SRC_NONE       AND
      srcBuf NEQ ctb->calOwn )
  {
    R_AT( RAT_NO_CARRIER, ctb->calOwn ) ( AT_CMD_NONE, cId+1 );
  }
}

/* process event for the +CTFR command.*/
LOCAL void cmhCC_CallDisc_transferedcall ( SHORT cId )
{
  T_CC_CMD_PRM   *pCCCmdPrm;   /* points to CC command parameters */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  T_CC_CALL_TBL  *ctb     = ccShrdPrm.ctb[cId];
  UBYTE          cmdBuf;       /* buffers current command */
  UBYTE          srcBuf;       /* buffers current command source */
  RAT_ID         rat_id;
  T_ACI_CME_ERR  cme_err;

  TRACE_FUNCTION("cmhCC_CallDisc_transferedcall");

  /* Get a pointer to the appropriate CC call table entry */
  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;

  /* End of command execution here */
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  (void)cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyDscFlg));

  switch (ctb->CDStat)
  {
    case CD_Succeeded:
      rat_id  = RAT_OK;
      cme_err = -1;
      break;

    case CD_Requested: /* No answer from the network */
      rat_id  = RAT_CME;
      cme_err = CME_ERR_Timeout;
      break;

    case CD_Failed: /* SS transaction failed */
      rat_id  = RAT_CME;
      cme_err = CME_ERR_OpNotSupp;
      break;

    default: /* Unexpected here */
      rat_id  = RAT_CME;
      cme_err = CME_ERR_Unknown;
      break;
  }

  if(rat_id EQ RAT_OK)
  {
    R_AT( RAT_OK, srcBuf ) ( cmdBuf );
  }
  else if(rat_id EQ RAT_CME)
  {
    R_AT( RAT_CME, srcBuf ) ( cmdBuf, cme_err );
  }
  cmh_logRslt( srcBuf,         rat_id, cmdBuf,
               (SHORT)(cId+1), -1,     cme_err );

  ctb->CDStat = NO_VLD_CD;
}

GLOBAL void cmhCC_CallDisconnected ( SHORT cId )
{
  UBYTE          idx;
  #if defined(FF_GPF_TCPIP)
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  #endif /* FF_GPF_TCPIP */
  T_CC_CALL_TBL  *ctb = ccShrdPrm.ctb[cId];
  UBYTE callId = 0;
  UBYTE i = 0;
  UBYTE mptyId = 0;

  TRACE_FUNCTION ("cmhCC_CallDisconnected()");

  /* inform advice of charge module */
  aoc_info (cId, AOC_STOP_TIME);

#if defined(FF_GPF_TCPIP)
  /* Needed if user stops call setup before app got connection conf */
 if (calltype EQ TCPIP_CALL)
 {
    T_DCM_STATUS_IND_MSG msg;
    msg.hdr.msg_id = DCM_NEXT_CMD_STOP_MSG;
    msg.result     = DCM_PS_CONN_BROKEN;
    dcm_send_message(msg, DCM_SUB_WAIT_SATDN_CNF);
 }
#endif /* FF_GPF_TCPIP */

  /*
   *----------------------------------------------------------------
   * call progress information
   *----------------------------------------------------------------
   */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT( RAT_CPI, idx )
      ( cId+1,
        CPI_MSG_Disc,
        (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
        (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
        ctb->curCs);
  }

  /*************************
  call was not serviced yet
  ***************************/
  if( ctb->calOwn EQ OWN_NONE    AND
      ctb->curCmd EQ AT_CMD_NONE )
  {
    psaCC_phbAddNtry ( LMN, cId, CT_MTC, NULL );  /* add call to LMN PB */

#ifdef FF_ATI
    io_setRngInd (IO_RING_OFF, CRING_TYP_NotPresent, CRING_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif

    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, idx )( cId+1 );
    }
    return;
  }

  /*************************
   check for command context
  ***************************/
  switch( ctb->curCmd )
  {
    case( AT_CMD_NONE ):
    case( AT_CMD_A ):
    case( AT_CMD_D ):
    case( AT_CMD_ABRT ):
      cmhCC_CallDisc_connectingphase(cId);
      break;

    case( AT_CMD_H ):
    case( AT_CMD_Z ):
    case( AT_CMD_CHUP ):

#ifdef FF_FAX
    case( AT_CMD_FKS ):
    case( AT_CMD_FDT ):
    case( AT_CMD_FDR ):
#endif /* FF_FAX */

      cmhCC_CallDisc_userinitiated(cId);
      break;

    case( AT_CMD_CHLD ):
      cmhCC_CallDisc_heldcall(cId);
      break;

    case( AT_CMD_CTFR ):
      cmhCC_CallDisc_transferedcall(cId);
      break;
  } /* switch */

  if ( ctb NEQ NULL AND ctb->mptyStat NEQ CS_IDL)
  {
    for(;callId < MAX_CALL_NR; callId++)
    {
      if (psaCC_ctb(callId) NEQ NULL AND
          psaCC_ctb(callId)->mptyStat EQ CS_ACT )
      {
        i++;
        if (callId NEQ cId)
        {
          mptyId = callId;
        }
      }
    }
    if (i EQ 2)
    {
      psaCC_ctb(mptyId)->mptyStat = CS_IDL;
    }
  }

/* PATCH BE 03.07.00
 * DO NOT declare the call table entry as unused:
  do not free call table at this time then every second MTC will fail if early
  assignment is used. */

  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallReleased           |
+-------------------------------------------------------------------+

  PURPOSE : call is released

*/

GLOBAL void cmhCC_CallReleased ( SHORT cId )
{
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */
  T_CC_CMD_PRM   *pCCCmdPrm;   /* points to CC command parameters */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  T_CC_CALL_TBL  *ctb = ccShrdPrm.ctb[cId];
  UBYTE idx;
  UBYTE callId = 0;
  UBYTE i = 0;
  UBYTE mptyId = 0;

  TRACE_FUNCTION ("cmhCC_CallReleased()");

  /* inform advice of charge module */
  aoc_info (cId, AOC_STOP_TIME);

#if defined(FF_GPF_TCPIP)
  /* This will happen if network got lost during a CSD call */
  if (calltype EQ TCPIP_CALL)
  {
    T_DCM_STATUS_IND_MSG msg;
    msg.hdr.msg_id = DCM_ERROR_IND_MSG;
    msg.result     = DCM_PS_CONN_BROKEN;
    dcm_send_message(msg, DCM_SUB_WAIT_SATDN_CNF);
  }
#endif /* FF_GPF_TCPIP */

  /* check for command context */
  switch( ctb->curCmd )
  {
  case( AT_CMD_A ):
  case( AT_CMD_D ):
  case( AT_CMD_NONE ):
    /* process event for A, D or no command */

    /* handling for CCBS prolonged session */

    if( ctb->curSrc NEQ CMD_SRC_NONE )
    {
    cmhCC_tstAndUnflagCall( cId, &cmhPrm[ctb->curSrc].ccCmdPrm.mltyCncFlg );
    cmhCC_tstAndUnflagCall( cId, &cmhPrm[ctb->curSrc].ccCmdPrm.mltyDscFlg );
    }
      
    if (ctb->CCBSstat EQ CCBSS_PSSBL )
    {
      cmhrat_ccbs (CMD_SRC_MAX, CCBS_IND_PossibilityTimedOut,
        CCBS_STAT_NotPresent, NULL );
      break;  /* skip the rest */
    }
    if (ctb->CCBSstat EQ CCBSS_REQ)
    {
      break;  /* skip the rest */
    }
    if (ctb->calType EQ CT_NI_MOC)
    {
      cmhrat_ccbs( CMD_SRC_MAX, CCBS_IND_RecallTimedOut,
        CCBS_STAT_NotPresent, NULL );
      break;  /* skip the rest */
    }

    /*  call clean up */
    switch( calltype )
    {
    case( VOICE_CALL ):
      ;
      break;

#ifdef FF_GPF_TCPIP
    case( TCPIP_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        pppShrdPrm.state = PPP_UNDEFINED; /* Otherwise PPP and TCPIP doesn't go down well */
        cmhPPP_Terminate(DWN);
        ctb->curCmd = AT_CMD_NONE;
      }
      break;
#endif /* FF_GPF_TCPIP */

#if defined (FAX_AND_DATA) AND defined (DTI)
    case( TRANS_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhTRA_Deactivate ();
      }
      break;

    case( NON_TRANS_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhL2R_Deactivate ();
      }
      break;

#ifdef CO_UDP_IP
    case( UDPIP_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhPPP_Terminate(DWN);
        ctb->curCmd = AT_CMD_NONE;
      }
      break;
#endif  /* CO_UDP_IP */

#ifdef FF_FAX
    case( FAX_CALL ):
      if( ccShrdPrm.datStat NEQ DS_IDL )
      {
        ccShrdPrm.datStat = DS_STOP_REQ;
        cmhT30_Deactivate ();
      }
#endif /* FF_FAX */
#endif /* FAX_AND_DATA */

    }
    cmhCC_SndDiscRsn( cId );
    break;

    case( AT_CMD_H ):
    case( AT_CMD_Z ):
    case( AT_CMD_CHUP ):
    case( AT_CMD_ABRT ):
    case( AT_CMD_CHLD ):

#ifdef FF_FAX
    case( AT_CMD_FKS ):
    case( AT_CMD_FDT ):
    case( AT_CMD_FDR ):
#endif
    /*
    *----------------------------------------------------------------
    * process event for H, Z and +CHUP command
    *----------------------------------------------------------------
      */
      /*
      * Bugfix for DISCONNECT_IND in CC U3 with PROGRESS_IND #8
      */
      cmdBuf = ctb->curCmd;
      srcBuf = ctb->curSrc;
      pCCCmdPrm = &cmhPrm[srcBuf].ccCmdPrm;

      cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm->mltyCncFlg) );
      cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm->mltyDscFlg) );

      if ( cmdBuf EQ AT_CMD_Z           AND
        pCCCmdPrm -> mltyDscFlg EQ 0 )
      {
        cmh_Reset ( srcBuf, TRUE );
        R_AT( RAT_Z, srcBuf)();
      }

      cmhCC_PrepareCmdEnd (cId, NULL, NULL);

      if (ctb->curCmd NEQ AT_CMD_CHLD)      /* Do not emmit OK for CHLD since this would
                                               occour in multiple OKs for a multi-party call */
      {
        R_AT( RAT_OK, srcBuf ) ( cmdBuf );
      }

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK, cmdBuf, (SHORT)(cId+1), -1, -1 );
      break;
  }

  /* call progress information */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT(RAT_CPI, idx)( cId+1,
      CPI_MSG_Rls,
      (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
      (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
      ctb->curCs);
  }
  if ( ctb NEQ NULL AND ctb->mptyStat NEQ CS_IDL)
  {
    for(;callId < MAX_CALL_NR; callId++)
    {
      if (psaCC_ctb(callId) NEQ NULL AND
          psaCC_ctb(callId)->mptyStat EQ CS_ACT )
      {
        i++;
        if (callId NEQ cId)
        {
          mptyId = callId;
        }
      }
    }
    if (i EQ 2)
    {
      psaCC_ctb(mptyId)->mptyStat = CS_IDL;
    }
  }

  if (rdlPrm.rdlcId NEQ cId)
  { /* if redialling is active no clean cId entry */
    /* declare the call table entry as unused */
    psaCC_FreeCtbNtry (cId);
  }
  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                  |
| ROUTINE : cmhCC_CallReleaseIndication                                |
+-------------------------------------------------------------------+

  PURPOSE : call release indication to give out correct call process information
                 interface so that psa function can report a release ind
*/

GLOBAL void cmhCC_CPIReleaseMsg ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  UBYTE idx;

  TRACE_FUNCTION ("cmhCC_CPIReleaseMsg()");

  /* call progress information */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT(RAT_CPI, idx)( cId+1,
      CPI_MSG_Rls,
      (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
      (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
      ctb->curCs);
  }

  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CPIrejectMsg           |
+-------------------------------------------------------------------+

  PURPOSE : interface so that psa function can report a reject ind.

*/
GLOBAL void cmhCC_CPIrejectMsg ( SHORT cId )
{

  UBYTE idx;
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];

  TRACE_FUNCTION ("cmhCC_CPIrejectMsg()");

  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT(RAT_CPI, idx)( cId+1,
      CPI_MSG_Rjct,
      (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
      (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
      ctb->curCs);
  }
    /*************************
  call was not serviced yet
  ***************************/
  if( ctb->calOwn EQ OWN_NONE    AND
      ctb->curCmd EQ AT_CMD_NONE )
  {
    psaCC_phbAddNtry ( LMN, cId, CT_MTC, NULL );  /* add call to LMN PB */

#ifdef AT_INTERPRETER
    io_setRngInd (IO_RING_OFF, CRING_TYP_NotPresent, CRING_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif

    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, idx )( cId+1 );
    }
    return;
  }

  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CallModified           |
+-------------------------------------------------------------------+

  PURPOSE : call was modified

*/

GLOBAL void cmhCC_CallModified ( SHORT cId )
{
#if defined (FAX_AND_DATA)
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */

  TRACE_FUNCTION ("cmhCC_CallModified()");

  /* check for command context */
  switch (ctb->curCmd )
  {
    case( AT_CMD_D ):
    case( AT_CMD_A ):
    case( AT_CMD_H ):
      /* process event for D, A and H command */
      cmdBuf = ctb->curCmd;
      srcBuf = ctb->curSrc;
      break;

    default:
      cmdBuf = AT_CMD_NONE;
      srcBuf = ctb->calOwn;
      break;
  }

  /* determine modifaction status */
  switch (ctb->rslt)
  {
    /* successful modification */
    case( MNCC_CAUSE_MODIFY_SUCCESS ):

      switch( calltype )
      {
        /* modified to speech call */
        case( VOICE_CALL ):
          cmhCC_PrepareCmdEnd (cId, NULL, NULL);

          R_AT( RAT_OK, srcBuf ) ( cmdBuf );

          /* log result */
          cmh_logRslt ( srcBuf, RAT_OK,
                        cmdBuf, (SHORT)(cId+1), -1, -1 );
          break;

        /*  modified to transparent or non-transparent or fax data call */
        case( TRANS_CALL ):
        case( NON_TRANS_CALL ):
        case( FAX_CALL ):
          ccShrdPrm.datStat = DS_ACT_REQ;

          if( cmhRA_Activate  ( srcBuf, cmdBuf, cId ) NEQ AT_EXCT )
          {
            ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
            psaCC_ClearCall (cId);
          }
          break;
      }
      break;

    /* unsuccessful modification */
    case( MNCC_CAUSE_MS_TIMER ):
    default: /* network can send any cause */

      TRACE_EVENT_P1 ("MODIFICATION FAILURE: cause=%d",ctb->rslt);


      R_AT( RAT_CME, srcBuf ) ( cmdBuf, CME_ERR_NotPresent );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_CME, cmdBuf, -1, -1,
                    CME_ERR_NotPresent );

      if( calltype EQ TRANS_CALL     OR
          calltype EQ NON_TRANS_CALL OR
          calltype EQ FAX_CALL )
      {
        /* back to transparent or non-transparent or fax data call */
        ccShrdPrm.datStat = DS_REST_REQ;

        if( cmhRA_Activate  ( srcBuf, cmdBuf, cId ) NEQ AT_EXCT )
        {
          ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
          psaCC_ClearCall (cId);
        }
      }
      break;
  }
#endif /* FAX_AND_DATA */
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_DTMFsent               |
+-------------------------------------------------------------------+

  PURPOSE : confirmation for sent DTMF

*/

LOCAL void dtmf_sent_after_vts ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  UBYTE current_cmd_source = ctb->dtmfSrc; /* buffers current command source */

  TRACE_FUNCTION ("dtmf_sent_after_vts()");

  ctb->dtmfCmd = AT_CMD_NONE;
  ctb->dtmfSrc = CMD_SRC_NONE;

  ccShrdPrm.dtmf.cId = NO_ENTRY;
  ccShrdPrm.dtmf.cnt = 0;

  if ((GET_CAUSE_VALUE(ctb->nrmCs) NEQ NOT_PRESENT_8BIT) AND
      (ctb->nrmCs NEQ MNCC_CAUSE_DTMF_START_SUCCESS) AND
      (ctb->nrmCs NEQ MNCC_CAUSE_DTMF_STOP_SUCCESS))
  {
    TRACE_EVENT_P1("DTMF response cause value: %d", ctb->nrmCs);
    R_AT( RAT_CME, current_cmd_source ) ( AT_CMD_VTS, CME_ERR_NotPresent );
    return;
  }

  R_AT( RAT_OK, current_cmd_source ) ( AT_CMD_VTS );
}

LOCAL void dtmf_sent_within_number ( SHORT cId )
{
  BOOL  dtmf_sent;    /* result of sending of next DTMF char */

  TRACE_FUNCTION ("dtmf_sent_within_number()");

  if ((ccShrdPrm.dtmf.cId NEQ cId) OR
      !is_call_ok_for_dtmf(cId))
  {
    TRACE_EVENT_P2("Wrong cId for send DTMF. ccShrdPrm.dtmf.cId: %d, cId: %d", ccShrdPrm.dtmf.cId, cId);
    return;
  }

  while( ccShrdPrm.dtmf.cnt                      AND
         ccShrdPrm.dtmf.cur < ccShrdPrm.dtmf.cnt )
  {
    dtmf_sent = cmhCC_SendDTMFdig ( AT_CMD_NONE,
                                    cId,
                                    ccShrdPrm.dtmf.dig[ccShrdPrm.dtmf.cur],
                                    DTMF_MOD_AUTO );
    ccShrdPrm.dtmf.cur++;
    if( dtmf_sent )
    {
      return;
    }
  }

  TRACE_EVENT_P1("End of sending DTMF tones: %d", ccShrdPrm.dtmf.dig[ccShrdPrm.dtmf.cur]);
  ccShrdPrm.dtmf.cnt = ccShrdPrm.dtmf.cur = 0;
  ccShrdPrm.dtmf.cId = NO_ENTRY;
}

GLOBAL void cmhCC_DTMFsent ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];

  TRACE_FUNCTION ("cmhCC_DTMFsent()");

  switch( ctb->dtmfCmd )
  {
    case( AT_CMD_VTS ):
      dtmf_sent_after_vts(cId);
      return;

    case( AT_CMD_NONE ):
      dtmf_sent_within_number(cId);
      return;

    default:
      TRACE_EVENT_P1("Unexpected DTMF command value: %d", ctb->dtmfCmd);
      break;
  }
}


/*
    This will be called when the call was disconnected while sending DTMF tones

*/
GLOBAL void cmhCC_DTMFstopped ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];

  TRACE_FUNCTION ("cmhCC_DTMFstopped()");

  switch( ctb->dtmfCmd )
  {
  case( AT_CMD_VTS ):
    TRACE_EVENT ("DTMF stopped within VTS");
    R_AT( RAT_CME, ctb->dtmfSrc )
            ( AT_CMD_VTS, CME_ERR_Unknown );
    return;

  case( AT_CMD_NONE ):
    TRACE_EVENT ("DTMF stopped within NONE");

    return;

  default:
    TRACE_EVENT_P1("Unexpected DTMF command value: %d", ctb->dtmfCmd);
    break;
  }
}


#if 0 // HM 11-May-2005: Dead code
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_DisconnectCall         |
+-------------------------------------------------------------------+

  PURPOSE : request to disconnect the call (in-band tones available)

*/

GLOBAL void cmhCC_DisconnectCall ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM  *pCCCmdPrm;   /* points to CC command parameters */
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */

  TRACE_FUNCTION ("cmhCC_DisconnectCall()");

  /* check for command context */
  switch (ctb->curCmd)
  {
    case( AT_CMD_NONE ):
    case( AT_CMD_D ):
    case( AT_CMD_A ):
     /*
      *----------------------------------------------------------------
      * process event for D, A and no command
      *----------------------------------------------------------------
      */
      /* for data calls proceed with call completion */
      if( cmhCC_getcalltype(cId) NEQ VOICE_CALL )
      {
        psaCC_ClearCall (cId);
      }
      break;

    case( AT_CMD_H ):
    case( AT_CMD_Z ):
    case( AT_CMD_CHUP ):

     /*
      *----------------------------------------------------------------
      * process event for H, Z and +CHUP command
      *----------------------------------------------------------------
      */
      cmdBuf = ctb->curCmd;
      srcBuf = ctb->curSrc;

      psaCC_ClearCall (cId);

      cmhCC_PrepareCmdEnd (cId, NULL, NULL);

      pCCCmdPrm = &cmhPrm[srcBuf].ccCmdPrm;

      if(cmdBuf EQ AT_CMD_Z           AND
         pCCCmdPrm -> mltyDscFlg EQ 0 )
      {
        cmh_Reset ( srcBuf, TRUE );
        R_AT( RAT_Z, srcBuf)();
      }

      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
      break;
  }

  return;
}
#endif /* #if 0 */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_IncomingCall           |
+-------------------------------------------------------------------+

  PURPOSE : indication of a mobile terminated call

*/

GLOBAL void cmhCC_IncomingCall ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  SHORT idx;                            /* holds index  counter */
  T_ACI_CRING_MOD mode;                 /* holds mode of call */
  T_ACI_CRING_TYP type1, type2;         /* holds types of bearer services */
  CHAR numBuf[MAXIMUM(MAX_CC_CALLING_NUMBER, MAX_CC_REDIR_NUMBER)+1];
                                        /* buffers calling number + '\0' */
  CHAR subBuf[SUB_LENGTH+1];            /* buffers subaddress 'subaddress\0' */
  T_ACI_TOA toaBuf;                     /* buffers type of address */
  T_ACI_TOS tosBuf;                     /* buffers type of subaddress */
  USHORT listcounter;
  T_ACI_LIST *msg2send;

  TRACE_FUNCTION ("cmhCC_IncomingCall()");

/*
 *-------------------------------------------------------------------
 * ring for call, if no call is in use
 *-------------------------------------------------------------------
 */
  if( ! psaCC_ctbCallInUse() )
  {

    switch (ctb->rptInd) /* determine call mode */
    {
      case( RI_NOT_PRES ):
      case( RI_SEQUENTIAL ):
        mode = CRING_MOD_Direct;
        break;
      case( RI_CIRCULAR ):
        mode = CRING_MOD_Alternate;
        break;

      default:
        TRACE_EVENT("UNEXP REPEAT INDICATOR IN CTB");
        mode = CRING_MOD_NotPresent;
        break;
    }

    /* determine 1st service */
    type1 = cmhCC_GetCallType_from_bearer( &ctb->BC[0] );

    /* determine 2nd service */
    type2 = cmhCC_GetCallType_from_bearer( &ctb->BC[1] );

#ifdef FF_ATI
    io_setRngInd (IO_RING_ON, type1, type2); /* V.24 Ring Indicator Line */
#endif

    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      if (ctb->prgDesc EQ PROG_NOT_PRES)
      {
        R_AT( RAT_CPI, idx )
          ( cId+1,
            CPI_MSG_Setup,
            (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
            (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
            ctb->curCs );
      }
      R_AT( RAT_CRING, idx )( mode, type1, type2 );

      /* calling line presentation, if no call is in use */

      /* check of presentation indicator removed, due to the fact that
       * other mobiles show the same behaviour.
      if( ctb->clgPty.present NEQ PRES_NUMB_NOT_AVAIL ){} */

      R_AT( RAT_CLIP, idx )
        ( CLIP_STAT_NotPresent,
          psaCC_ctbClrAdr2Num( cId, numBuf, sizeof (numBuf) ),
          cmhCC_ctbGetClrNumTyp( cId, &toaBuf ),
          ctb->clgPty.present,
          psaCC_ctbClrAdr2Sub( cId, subBuf ),
          cmhCC_ctbGetClrSubTyp( cId, &tosBuf ),
          psaCC_ctbGetAlpha( cId ) );

      R_AT ( RAT_CDIP, idx )
           (psaCC_ctbCldAdr2Num( cId, numBuf, sizeof (numBuf) ),
            cmhCC_ctbGetCldNumTyp( cId, &toaBuf ),
          	psaCC_ctbCldAdr2Sub( cId, subBuf ),
          	cmhCC_ctbGetCldSubTyp( cId, &tosBuf ));
      
    } /* for */

    if (ctb->CDStat EQ CD_Notified)
    {
      send_CSSX_notification(cId,
          CSSX_CODE_DeflectedCall,
          ACI_NumParmNotPresent,
          psaCC_ctbRdrAdr2Num( cId, numBuf, sizeof (numBuf) ),
          cmhCC_ctbGetRdrNumTyp( cId, &toaBuf ),
          psaCC_ctbRdrAdr2Sub( cId, subBuf ),
          cmhCC_ctbGetRdrSubTyp( cId, &tosBuf));
    }

    if (ctb->CDStat EQ CD_Notified)
    {
      psaCC_FreeRdrPty (cId);
      ctb->CDStat = NO_VLD_CD;
    }
    /* check for TTY service */
    cmhCC_TTY_Control ( cId, TTY_START );

    /* Find out if there is any MNCC_FACILITY_IND stored */
    listcounter  = 0;
    if ((listcounter = get_list_count(ccShrdPrm.facility_list)) > 0)
    {
      for (;listcounter > 0 ; listcounter --)
      {
        msg2send = remove_first_element(ccShrdPrm.facility_list);

        /* Send  MNCC_FACILITY_IND */
        psa_mncc_facility_ind((T_MNCC_FACILITY_IND *)msg2send);
      }
    }

  } /* endif */


/*
 *-------------------------------------------------------------------
 * call waiting indication, if a call is in use
 *-------------------------------------------------------------------
 */
  else
  {
    /* check of presentation indicator removed, due to the fact that
       other mobiles show the same behaviour.
    if( ctb->clgPty.present NEQ PRES_NUMB_NOT_AVAIL ) {} */

    if (ctb->CDStat EQ CD_Notified)
    {
      send_CSSX_notification( cId,
                              CSSX_CODE_DeflectedCall,
                              ACI_NumParmNotPresent,
                              psaCC_ctbRdrAdr2Num( cId, numBuf, sizeof (numBuf) ),
                              cmhCC_ctbGetRdrNumTyp( cId, &toaBuf ),
                              psaCC_ctbRdrAdr2Sub( cId, subBuf ),
                              cmhCC_ctbGetRdrSubTyp( cId, &tosBuf ));
    }

    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      if (ctb->prgDesc EQ PROG_NOT_PRES)
      {
        R_AT( RAT_CPI, idx )
          ( cId+1,
            CPI_MSG_Setup,
            (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
            (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
            ctb->curCs );
      }

      R_AT( RAT_CCWA, idx )
        ( NULL,
          psaCC_ctbClrAdr2Num( cId, numBuf, sizeof (numBuf) ),
          cmhCC_ctbGetClrNumTyp( cId, &toaBuf ),
          ctb->clgPty.present,
          cmhCC_GetCallClass( cId ),
          psaCC_ctbGetAlpha( cId ) );
    }
    if (ctb->CDStat EQ CD_Notified)
    {
      psaCC_FreeRdrPty (cId);
      ctb->CDStat = NO_VLD_CD;
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : psaCC_Synchronized           |
+-------------------------------------------------------------------+

  PURPOSE : channel mode has changed or
            call reestablishment event received.
            If a channel mode change is indicated cId needs not
            to be valid.

*/

GLOBAL void cmhCC_Synchronized ( SHORT cId ) 
{
  SHORT act_cId;      /* holds call identifier */
  UBYTE idx;          /* holds index */
#if defined (FAX_AND_DATA) AND defined (DTI)
  T_CC_CALL_TYPE calltype;
#endif    /* of #ifdef FAX_AND_DATA */

  TRACE_FUNCTION ("cmhCC_Synchronized()");

  /* process event */
  switch( ccShrdPrm.syncCs )
  {
    case( MNCC_CAUSE_CHANNEL_SYNC ):   /* change of TCH state */

      if( ccShrdPrm.TCHasg EQ TRUE )
      {
        /* search for an active call */
        if((act_cId = psaCC_ctbFindCall( NO_VLD_OWN, CS_ACT, NO_VLD_CT ))
            NEQ NO_ENTRY )
        {
#if defined (FAX_AND_DATA) AND defined (DTI)
          calltype = cmhCC_getcalltype(act_cId);

          switch( calltype )
          {
#ifdef FF_FAX
          case( FAX_CALL ):
              switch( ccShrdPrm.datStat )
              {
                case( DS_ACT ):
                case( DS_TCH_MDF ):
                  ccShrdPrm.datStat = DS_TCH_MDF;
                  /*
                   * use entity owner instead of current source, because
                   * command is out of scope for CC
                   */
                  if( cmhRA_Modify ( raEntStat.entOwn, act_cId ) NEQ AT_EXCT )
                  {
                    ccShrdPrm.datStat = DS_IDL;
                    cmhT30_Deactivate();
                    psaCC_ctb(act_cId)->nrmCs = MNCC_CAUSE_CALL_CLEAR;
                    psaCC_ClearCall (act_cId);
                  }
                  break;

                case( DS_IDL ):
                  ccShrdPrm.datStat = DS_ACT_REQ;
                  if( cmhRA_Activate  ( psaCC_ctb(act_cId)->curSrc,
                                        psaCC_ctb(act_cId)->curCmd,
                                        act_cId )
                      NEQ AT_EXCT )
                  {
                    ccShrdPrm.datStat = DS_IDL;
                    psaCC_ctb(act_cId)->nrmCs = MNCC_CAUSE_CALL_CLEAR;
                    psaCC_ClearCall (act_cId);
                  }
            }
            break;
#endif /* FF_FAX */  

            case( TRANS_CALL ):    /* activate RA */
            case( NON_TRANS_CALL ):    /* activate RA */
              switch( ccShrdPrm.datStat )
              {
                case( DS_IDL ):
                  ccShrdPrm.datStat = DS_ACT_REQ;
                  if( cmhRA_Activate  ( psaCC_ctb(act_cId)->curSrc,
                                        psaCC_ctb(act_cId)->curCmd,
                                        act_cId )
                      NEQ AT_EXCT )
                  {
                    ccShrdPrm.datStat = DS_IDL;
                    psaCC_ctb(act_cId)->nrmCs = MNCC_CAUSE_CALL_CLEAR;
                    psaCC_ClearCall (act_cId);
                  }
                  break;

                default:
                  TRACE_EVENT("modify data call ignored");
                  break;
            }
            break;

            case( UNSUP_DATA_CALL  ):
              TRACE_EVENT("UNSUPPORTED DATA CALL -> DISC CALL");
              psaCC_ctb(act_cId)->nrmCs = MNCC_CAUSE_CALL_CLEAR;
              psaCC_ClearCall (act_cId);
              break;
          }
#endif /* FAX_AND_DATA */
        }
      }

      /* Information about Traffic Channel Assignment should be sent
      for all existing act_cIds */
      for( act_cId = 0; act_cId < MAX_CALL_NR; act_cId++ )
      {
        if (ccShrdPrm.ctb[act_cId] NEQ NULL)
        {
          for( idx = 0; idx < CMD_SRC_MAX; idx++ )
          {
            R_AT( RAT_CPI, idx )
              ( act_cId+1,
                CPI_MSG_Sync,
                (psaCC_ctb(act_cId)->inBndTns)? CPI_IBT_True: CPI_IBT_False,
                (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
                psaCC_ctb(act_cId)->curCs );
          }
        }
      }
      break;

    case( MNCC_CAUSE_REEST_STARTED ):                /* call reestablishment */
    case( MNCC_CAUSE_REEST_FINISHED ):
      TRACE_EVENT_P1("SYNC -> CALL REESTABLISHMENT %s", 
        (ccShrdPrm.syncCs  EQ MNCC_CAUSE_REEST_STARTED ? "STARTED" : "FINISHED"));
      if (psaCC_ctbIsValid (cId))
      {
      /* Send %CPI notification for call reestablishment */
      for( idx = 0; idx < CMD_SRC_MAX; idx++ )
      {
        R_AT( RAT_CPI, idx )
          ( cId+1,
            CPI_MSG_Sync,
              (psaCC_ctb(cId)->inBndTns)? CPI_IBT_True: CPI_IBT_False,
            (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False, 
              psaCC_ctb(cId)->curCs );
        }
      }
      else
      {
        TRACE_ERROR ("No call table entry");
      }
      break;
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : psaCC_CallHeld               |
+-------------------------------------------------------------------+

  PURPOSE : call hold result

*/

GLOBAL void cmhCC_CallHeld ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */
  SHORT addId;                /* holds additional call id */
  UBYTE  idx;

  TRACE_FUNCTION ("cmhCC_CallHeld()");

  /* check for command context */
  switch (ctb->curCmd )
  {
    case( AT_CMD_D    ):
    case( AT_CMD_A    ):
    case( AT_CMD_CHLD ):
      break;

    default:
      TRACE_EVENT_P1("Error: wrong command context: %d", ctb->curCmd);
      return;  /* wrong command context */
  }

  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);
  pCCCmdPrm = &cmhPrm[srcBuf].ccCmdPrm;

  /* check result of hold request */
  TRACE_EVENT_P1("Hold CNF cause value: %04X", ctb->rslt);
  switch( ctb->rslt )
  {
    case( MNCC_CAUSE_HOLD_SUCCESS ):
    case( MNCC_CAUSE_SUCCESS ):
    case( MNCC_CAUSE_NO_MS_CAUSE ):

      /* Held information displayed if call is on hold */
      for( idx = 0; idx < CMD_SRC_MAX; idx++ )
      {
        R_AT( RAT_CPI, idx )
          ( cId+1,
            CPI_MSG_Hld,
            (ctb->inBndTns)? CPI_IBT_True: CPI_IBT_False,
            (ccShrdPrm.TCHasg)? CPI_TCH_True: CPI_TCH_False,
             ctb->rslt);
      }

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {
        if((pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActExc OR
            pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActAndAcpt OR
            pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActDial) AND
            pCCCmdPrm -> mltyCncFlg )
        {
          process_CHLDaddInfo( srcBuf, CALL_HELD );
        }

        if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
            pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
        {
#ifdef SIM_TOOLKIT
          if (ctb->SATinv )
          {
            cmh_logRslt ( srcBuf, RAT_OK,
                          cmdBuf, (SHORT)(cId+1), -1, -1 );

            cmhSAT_StartPendingCall( );
          }
          else
#endif /* SIM_TOOLKIT */
          {
            R_AT( RAT_OK, srcBuf ) ( cmdBuf );

            /* log result */
            cmh_logRslt ( srcBuf, RAT_OK,
                          cmdBuf, (SHORT)(cId+1), -1, -1 );
          }
        }
      }
      break;

    default: /* no positive result, i.e. negative result of Hold operation */

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {

#ifdef SIM_TOOLKIT
        if (ctb->SATinv)
        {
          psaCC_ctb(ccShrdPrm.cIdMPTY)->SATinv = FALSE;
          /* return network error cause GSM 11.14 / 12.12.3 */
          cmhSAT_NtwErr( ADD_NO_CAUSE );
        }
#endif
        if( pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActDial AND
            pCCCmdPrm -> mltyCncFlg )
        {
          for( addId = 0; !((pCCCmdPrm -> mltyCncFlg >> addId) & 0x01); addId++ )
            ;

          if( CHLDaddInfo EQ CHLD_ADD_INFO_DIAL_CAL )
          {
              CHLDaddInfo = NO_CHLD_ADD_INFO;
              psaCC_FreeCtbNtry (addId);
          }
        }

        pCCCmdPrm -> mltyCncFlg = 0;        /* unflag calls */
        CHLDaddInfo = NO_CHLD_ADD_INFO;

        R_AT( RAT_CME, srcBuf ) ( cmdBuf, CME_ERR_OpNotAllow );

        /* log result */
        cmh_logRslt ( srcBuf, RAT_CME,
                      cmdBuf, -1, -1, CME_ERR_OpNotAllow );
      }
      break;
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : psaCC_CallRetrieved          |
+-------------------------------------------------------------------+

  PURPOSE : call retrieve result

*/

GLOBAL void cmhCC_CallRetrieved ( SHORT cId )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */

  TRACE_FUNCTION ("cmhCC_CallRetrieved()");

  /* check for command context */
  if (ctb->curCmd NEQ AT_CMD_CHLD)
  {
    return;
  }

  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  /*
   *  check result of retrieve request
   */
  switch (ctb->rslt)
  {
    case( MNCC_CAUSE_RETRIEVE_SUCCESS ):

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {
        if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
            pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
        {
          R_AT( RAT_OK, srcBuf ) ( cmdBuf );

          /* log result */
          cmh_logRslt ( srcBuf, RAT_OK,
                        cmdBuf, (SHORT)(cId+1), -1, -1 );
        }
      }
      break;

    default: /* no positive result of retrieve operation */

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {
        pCCCmdPrm -> mltyCncFlg = 0;        /* unflag calls */

        R_AT( RAT_CME, srcBuf ) ( cmdBuf, CME_ERR_OpNotAllow );

        /* log result */
        cmh_logRslt ( srcBuf, RAT_CME,
                      cmdBuf, -1, -1, CME_ERR_OpNotAllow );
      }
      break;
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_RA_Activated           |
+-------------------------------------------------------------------+

  PURPOSE : RA entity activated, data path established

*/
#ifdef DTI
GLOBAL void cmhCC_RA_Activated ( SHORT cId )
{
#ifdef FAX_AND_DATA

  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE cmdBuf;               /* buffers current command */
  UBYTE srcBuf;               /* buffers current command source */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_RA_Activated()");

  srcBuf = psaCC_ctb(cId)->curSrc;
  cmdBuf = psaCC_ctb(cId)->curCmd;
  pCCCmdPrm = &cmhPrm[srcBuf].ccCmdPrm;

  switch( ccShrdPrm.datStat )
  {
  case( DS_ACT_REQ ):
  case( DS_REST_REQ ):
    switch( calltype )
    {
    /* transparent data call */
    case( TRANS_CALL ):
      psaTRA_Activate( );
      break;

    /* non-transparent data call */
    case( NON_TRANS_CALL ):
    /* a WAP call is a non-transparent data call */
#ifdef CO_UDP_IP 
    case( UDPIP_CALL ):
#endif /* CO_UDP_IP */

#ifdef FF_TCP_IP
    case( PPP_CALL ):
#endif /* FF_TCP_IP */

#if defined(FF_GPF_TCPIP)
    case (TCPIP_CALL):
#endif /* FF_GPF_TCPIP */

      if( cmhL2R_Activate(srcBuf, cmdBuf, cId) NEQ AT_EXCT )
      {
        ccShrdPrm.datStat = DS_DSC_REQ;
        cmhRA_Deactivate ();
      }
      break;

#ifdef FF_FAX
    case( FAX_CALL ):
      if( cmhT30_Activate(srcBuf, cmdBuf, cId) NEQ AT_EXCT )
      {
        ccShrdPrm.datStat = DS_DSC_REQ;
        cmhRA_Deactivate ();
      }
      break;
#endif /* FF_FAX */

   /* in case of other types of call */
    default:
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhRA_Deactivate ();
      break;
    }
    break;
  }
#endif    /* of #ifdef FAX_AND_DATA */
}
#endif /* DTI */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_RA_Deactivated         |
+-------------------------------------------------------------------+

  PURPOSE : RA entity deactivated, data path disconnected

*/
#ifdef DTI
GLOBAL void cmhCC_RA_Deactivated ( SHORT cId )
{
#ifdef FAX_AND_DATA
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);
  UBYTE cmdBuf;               /* buffers current command */

  TRACE_FUNCTION ("cmhCC_RA_Deactivated()");

  cmdBuf = ctb->curCmd;

  switch( calltype )
  {
    case( TRANS_CALL ):
     /* transparent data call */
      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT ):
        case( DS_ACT_REQ ):
        case( DS_DSC_REQ ):
        case( DS_TCH_MDF ):

          ccShrdPrm.datStat = DS_IDL;
          ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
          psaCC_ClearCall (cId);
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
              /* check impact for SAT commands */
              cmhSAT_OpChnCSDDown( cId, TPL_NONE );
#endif /* SIM TOOLKIT AND FF_SAT_E */
          break;

        case( DS_MDF_REQ ):

          ccShrdPrm.datStat = DS_IDL;
          psaCC_ModifyCall(cId);
          break;

        case( DS_STOP_REQ ):

          ccShrdPrm.datStat = DS_IDL;
          cmhCC_CallDisconnected(cId);
          break;
      }
      break;

     /* non-transparent data call */
    case( NON_TRANS_CALL ):
#ifdef CO_UDP_IP
    case( UDPIP_CALL ):
#endif /* CO_UDP_IP */

#ifdef FF_TCP_IP
    case( PPP_CALL ):
#endif /* FF_TCP_IP */

#ifdef FF_GPF_TCPIP
    case (TCPIP_CALL):
#endif /* FF_GPF_TCPIP */

      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT ):
        case( DS_ACT_REQ ):
        case( DS_DSC_REQ ):
        case( DS_REST_REQ ):
        case( DS_TCH_MDF ):

          ccShrdPrm.datStat        = DS_IDL;
          ctb->nrmCs        = MNCC_CAUSE_CALL_CLEAR;

#if defined(CO_UDP_IP) OR defined(FF_GPF_TCPIP)
          /* WAP STACK is down */

          /* The following statements check which configuration is active,
             because there are three possibilities:
             1. UDP/IP only - WAP1.x and SAT_E
             2. TCP/IP only - WAP2.x and higher and App's
             3. UDP/IP and TCP/IP - WAP2.x and higher and App's and SAT_E 
          */
#if defined(FF_GPF_TCPIP) AND !defined(CO_UDP_IP)
          if(calltype EQ TCPIP_CALL)
#elif !defined(FF_GPF_TCPIP) AND defined(CO_UDP_IP)
          if(calltype EQ UDPIP_CALL)
#elif defined(FF_GPF_TCPIP) AND defined(CO_UDP_IP)
          if(calltype == UDPIP_CALL OR calltype == TCPIP_CALL)
#endif
          {
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
            /* check impact for SAT commands */
            cmhSAT_OpChnCSDDown( cId, UDP );
#endif /* SIM TOOLKIT AND FF_SAT_E */
            /* Have CC disconnected before ? */
            if (ctb->calStat EQ CS_ACT)
            {
              psaCC_ClearCall (cId);
            }
            else
            {
               /* Message to MMI */
              R_AT( RAT_OK, ctb->calOwn ) ( AT_CMD_NONE, cId+1 );

#ifdef FF_ATI
              io_setDCD (ctb->calOwn, IO_DCD_OFF); /* V.24 DCD Line */
#endif
              /* log result */
              cmh_logRslt (ctb->calOwn, RAT_OK,
                        (T_ACI_AT_CMD)cmdBuf, (SHORT)(cId+1), -1, -1 );
            }
            break;
          }
#endif /* CO_UDP_IP || FF_GPF_TCPIP */

          psaCC_ClearCall (cId);
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E) 
          /* check impact for SAT commands */
          cmhSAT_OpChnCSDDown( cId, TPL_NONE );
#endif /* SIM TOOLKIT AND FF_SAT_E */
          break;

        case( DS_STOP_REQ ):

          ccShrdPrm.datStat = DS_IDL;
          cmhCC_CallDisconnected(cId);
#if defined (FF_WAP) || defined (FF_SAT_E)
          /* WAP STACK is down */
          ccShrdPrm.wapStat = CC_WAP_STACK_DOWN;
#endif /* FF_WAP || SAT E */
          break;

        case( DS_ABO_REQ ):   /* during modification */
          switch( ctb->rptInd )
          {
            case( RI_SEQUENTIAL ):      /* no way back */

              ccShrdPrm.datStat = DS_IDL;
              ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
              psaCC_ClearCall (cId);
              break;

            case( RI_CIRCULAR ):

              ccShrdPrm.datStat = DS_IDL;
              psaCC_ModifyCall(cId);  /* back to former service */
              break;
          }
          break;

        case( DS_MDF_REQ ):
          ccShrdPrm.datStat = DS_IDL;
          psaCC_ModifyCall(cId);
          break;
      }
      break;

    /* in case of a fax call */
    case( FAX_CALL ):
      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT ):
        case( DS_ACT_REQ ):
        case( DS_DSC_REQ ):
        case( DS_REST_REQ ):
        case( DS_TCH_MDF ):
          ccShrdPrm.datStat = DS_IDL;
          ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
          psaCC_ClearCall (cId);
          break;

        case( DS_STOP_REQ ):
          ccShrdPrm.datStat = DS_IDL;
          cmhCC_CallDisconnected(cId);
          break;

        case( DS_ABO_REQ ):   /* abort during modification */
          switch (ctb->rptInd)
          {
            case( RI_SEQUENTIAL ):      /* no way back */

              ccShrdPrm.datStat = DS_IDL;
              ctb->nrmCs = MNCC_CAUSE_CALL_CLEAR;
              psaCC_ClearCall (cId);
              break;

            case( RI_CIRCULAR ):

              ccShrdPrm.datStat = DS_IDL;
              psaCC_ModifyCall(cId);  /* back to former service */
              break;
          }
          break;

        case( DS_MDF_REQ ):
          ccShrdPrm.datStat = DS_IDL;
          psaCC_ModifyCall(cId);
          break;
      }
      break;
  }
#endif    /* of #ifdef FAX_AND_DATA */
}
#endif /* DTI */

#ifdef FF_FAX
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_RA_Modified            |
+-------------------------------------------------------------------+

  PURPOSE : RA entity modified after CMM

*/
#ifdef DTI
GLOBAL void cmhCC_RA_Modified ( SHORT cId )
{
#ifdef FAX_AND_DATA

  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_RA_Modified()");

  if( calltype EQ FAX_CALL )
  {
   /* only in case of a fax call */
    if( ccShrdPrm.datStat EQ DS_TCH_MDF )
    {
      ccShrdPrm.datStat = DS_ACT;

      if( cmhT30_Modify() NEQ AT_EXCT )
      {
        ccShrdPrm.datStat = DS_DSC_REQ;
        cmhRA_Deactivate ();
      }
    }
  }
#endif    /* of #ifdef FAX_AND_DATA */
}
#endif /* DTI */
#endif /* FF_FAX */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_L2R_or_TRA_Activated   |
+-------------------------------------------------------------------+

  PURPOSE : L2R entity activated, data path established

*/
#ifdef DTI
GLOBAL void cmhCC_L2R_or_TRA_Activated ( T_DTI_ENTITY_ID activated_module, SHORT cId )
{
#ifdef FAX_AND_DATA
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;    /* points to CC command parameters */
  UBYTE cmdBuf;                /* buffers current command */
  UBYTE srcBuf;                /* buffers current command source */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_L2R_or_TRA_Activated()");

  if (!psaCC_ctbIsValid (cId))
  {
    /*
     * If for some no good reason we got a L2R_CONNECT_CNF, L2R_CONNECT_IND
     * or TRA_ACTIVATE_CNF without having a valid entry in the call table,
     * we do here the same as for the FAX case where those events are also 
     * unexpected. We send the respective deativation request.
     */
    TRACE_ERROR ("Call table entry disappeared");
    ccShrdPrm.datStat = DS_DSC_REQ;
    switch( activated_module )
    {
      case( DTI_ENTITY_TRA ):
        psaTRA_Deactivate();
        break;
      case( DTI_ENTITY_L2R ):
        cmhL2R_Deactivate();
        break;
      default: /* Unexpected to happen */
        break;
    }
    return;
  }

  cmdBuf = ctb->curCmd;
  srcBuf = ctb->curSrc;
  pCCCmdPrm = &cmhPrm[srcBuf].ccCmdPrm;

  switch( calltype )
  {
    case( TRANS_CALL ):
    case( NON_TRANS_CALL ):

#ifdef CO_UDP_IP
case( UDPIP_CALL ):
#endif /* CO_UDP_IP */

#ifdef FF_TCP_IP
    case( PPP_CALL ):
#endif

#if defined(FF_GPF_TCPIP)
    case (TCPIP_CALL):
#endif /* FF_GPF_TCPIP */

      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT_REQ ):

          ccShrdPrm.datStat = DS_ACT;
          cmhCC_PrepareCmdEnd (cId, NULL, NULL);

          /* reset CMOD to single mode */
          ccShrdPrm.CMODmode = CMOD_MOD_Single;

          /* check if connect is expected */
          if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
          {
            if( pCCCmdPrm -> mltyCncFlg EQ 0 )  /* if last call */
            {
              R_AT( RAT_CR, srcBuf )
                (cmhCC_GetSrvType (&ctb->BC[ctb->curBC]));

              R_AT( RAT_ILRR, srcBuf )
                (cmhCC_GetDataRate (&ctb->BC[ctb->curBC]),
                 cmhCC_GetFormat (&ctb->BC[ctb->curBC]),
                 cmhCC_GetParity (&ctb->BC[ctb->curBC]));
#if defined (CO_UDP_IP) AND defined (FF_GPF_TCPIP)
              if ( (calltype NEQ UDPIP_CALL) AND (calltype NEQ TCPIP_CALL) )
#endif
#if defined (CO_UDP_IP) AND !defined(FF_GPF_TCPIP)
              if (calltype NEQ UDPIP_CALL)
#endif
#if defined (FF_GPF_TCPIP) AND !defined(CO_UDP_IP)
              if (calltype NEQ TCPIP_CALL)
#endif

#ifdef FF_TCP_IP
              if (calltype NEQ PPP_CALL)
#endif /* FF_TCP_IP */
              {
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
                if (!cmhSAT_OpChnChckCSD( TPL_NONE))
#endif /* of SIM_TOOLKIT AND FF_SAT_E*/
                {
                  R_AT( RAT_CONNECT, srcBuf )
                    (cmdBuf, cmhCC_GetDataRate(&ctb->BC[ctb->curBC]), cId+1, FALSE);
                }
              }

              /* log result */
              cmh_logRslt ( srcBuf, RAT_CONNECT,
                            cmdBuf, (SHORT)(cId+1),
                            cmhCC_GetDataRate(&ctb->BC[ctb->curBC]), -1 );

              switch( activated_module )
              {
                case( DTI_ENTITY_TRA ):
                  if (IS_SRC_BT(srcBuf))
                  {
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_BLUETOOTH, DTI_ENTITY_TRA};
                    UBYTE dti_id = dti_cntrl_new_dti(DTI_DTI_ID_NOTPRESENT);
                    dti_cntrl_est_dpath ( dti_id,
                                          entity_list,
                                          2,
                                          SPLIT,
                                          TRA_connect_dti_cb);
                  }
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
                  if (cmhSAT_OpChnChckCSD( TPL_NONE))
                  {
                    cmhSAT_OpChnSIMCnctReq( DTI_ENTITY_TRA );
                  }
#endif /* of SIM_TOOLKIT AND FF_SAT_E */
                  else
                  {
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_TRA};

                    dti_cntrl_est_dpath_indirect ( srcBuf,
                                                   entity_list,
                                                   1,
                                                   SPLIT,
                                                   TRA_connect_dti_cb,
                                                   DTI_CPBLTY_SER,
                                                   DTI_CID_NOTPRESENT);
                  }
                  break;

                case( DTI_ENTITY_L2R ):
#ifdef CO_UDP_IP
                  if ( calltype EQ UDPIP_CALL )
                  {
                    UBYTE dti_id;
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_IP, DTI_ENTITY_PPPC, DTI_ENTITY_L2R};
#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E) 
                    if ( satShrdPrm.opchStat EQ OPCH_EST_REQ )
                      dti_id = simShrdPrm.sat_class_e_dti_id;
                    else
#endif /* SIM_TOOLKIT AND FF_SAT_E */
                      dti_id = wap_dti_id;

                    dti_cntrl_est_dpath ( dti_id,
                                          entity_list,
                                          3,
                                          APPEND,
                                          IP_UDP_connect_dti_cb);
                    break;
                  }
#endif /* CO_UDP_IP */

#if defined (FF_TCP_IP) AND defined (DTI)
                  if ( calltype EQ PPP_CALL )
                  {
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_PPPC, DTI_ENTITY_L2R};
                    dti_cntrl_est_dpath_indirect ( srcBuf,
                                                   entity_list,
                                                   2,
                                                   SPLIT,
                                                   L2R_connect_dti_cb,
                                                   DTI_CPBLTY_PKT,
                                                   DTI_CID_NOTPRESENT);
                    break;
                  }
#endif /* FF_TCP_IP */

#ifdef FF_GPF_TCPIP
                  if ( calltype EQ TCPIP_CALL )
                  {
                    UBYTE dti_id;
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_TCPIP, DTI_ENTITY_PPPC, DTI_ENTITY_L2R};
                    /* create a WAP DTI if not present */
                    if (wap_dti_id EQ DTI_DTI_ID_NOTPRESENT)
                    {
                       wap_dti_id = dti_cntrl_new_dti (DTI_DTI_ID_NOTPRESENT);
                       TRACE_EVENT_P1("tcpip_wap_dti_id = %d", wap_dti_id);
                    }
                    dti_id = wap_dti_id;
                    dti_cntrl_est_dpath ( dti_id,
                                          entity_list,
                                          3,
                                          SPLIT,
                                          TCPIP_connect_dti_cb);
                    break;
                  }
#endif /* FF_GPF_TCPIP */

#if defined (SIM_TOOLKIT) AND defined (FF_SAT_E)
                  if (cmhSAT_OpChnChckCSD( TPL_NONE))
                  {
                    cmhSAT_OpChnSIMCnctReq( DTI_ENTITY_L2R );
                  }
#endif /* of SIM_TOOLKIT AND FF_SAT_E */

#ifdef DTI
                  if (IS_SRC_BT(srcBuf))
                  {
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_BLUETOOTH, DTI_ENTITY_L2R};
                    UBYTE dti_id = dti_cntrl_new_dti(DTI_DTI_ID_NOTPRESENT);
                    dti_cntrl_est_dpath ( dti_id,
                                          entity_list,
                                          2,
                                          SPLIT,
                                          L2R_connect_dti_cb);
                  }
                  else
                  {
                    T_DTI_ENTITY_ID entity_list[] = {DTI_ENTITY_L2R};
                    dti_cntrl_est_dpath_indirect ( srcBuf,
                                                   entity_list,
                                                   1,
                                                   SPLIT,
                                                   L2R_connect_dti_cb,
                                                   DTI_CPBLTY_SER,
                                                   DTI_CID_NOTPRESENT);
                  }
#endif /* DTI */
                  break;
              } /* switch( activated_module ) */
            } /* if( pCCCmdPrm -> mltyCncFlg EQ 0 ) */
          } /* if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg))) */
          break;

        case( DS_REST_REQ ):
          ccShrdPrm.datStat = DS_ACT;
          break;
        }
        break;
    /* in case of a fax call */
    case( FAX_CALL  ):

      TRACE_EVENT( "UNEXP BEARER SERV FAX" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      switch( activated_module )
      {
      case( DTI_ENTITY_TRA ):
        psaTRA_Deactivate();
        break;
      case( DTI_ENTITY_L2R ):
        cmhL2R_Deactivate();
        break;
      }
      break;
    }
#endif    /* of #ifdef FAX_AND_DATA */
}
#endif /* UART */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_L2R_or_TRA_Deactivated |
+-------------------------------------------------------------------+

  PURPOSE : L2R entity deactivated, data path disconnected

*/
#ifdef UART
GLOBAL void cmhCC_L2R_or_TRA_Deactivated ( SHORT cId )
{
#ifdef FAX_AND_DATA

  UBYTE srcBuf; 
#ifdef DTI
  T_DTI_CNTRL dti_cntrl_info;
#endif /* DTI */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  /* if there is a redirection get proper source */
#ifdef DTI
  if (dti_cntrl_get_info_from_dti_id(raShrdPrm.dti_id, &dti_cntrl_info))
  {
    srcBuf = dti_cntrl_info.src_id;
  }
  else /* if it is not a valid dti_id - take stored src_id */
  {
    TRACE_EVENT_P2("No valid dti_id:%d taking owner:%d",
                   raShrdPrm.dti_id,
                   raShrdPrm.owner);
#endif /* DTI */
    srcBuf = raShrdPrm.owner;
#ifdef DTI
  }
  /* reset ra dti_id storage */
  raShrdPrm.dti_id = NOT_PRESENT_8BIT;
#endif /* DTI */

  TRACE_FUNCTION ("cmhCC_L2R_or_TRA_Deactivated()");

  io_setDCD (srcBuf, IO_DCD_OFF);

  switch( calltype )
  {
    case( TRANS_CALL ):
    case( NON_TRANS_CALL ):

#ifdef CO_UDP_IP
    case( UDPIP_CALL ):
#endif /* CO_UDP_IP */

#ifdef FF_TCP_IP
    case( PPP_CALL ):
#endif

#if defined(FF_GPF_TCPIP)
    case (TCPIP_CALL):
#endif /* FF_GPF_TCPIP */

      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT ):
        case( DS_ACT_REQ ):
        case( DS_DSC_REQ ):
        case( DS_MDF_REQ ):
        case( DS_STOP_REQ ):

          cmhRA_Deactivate ();
          break;
      }
      break;

    case( FAX_CALL ):
      TRACE_EVENT( "UNEXP BEARER SERV FAX" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhRA_Deactivate();
      break;
  }
#endif    /* of #ifdef FAX_AND_DATA */
}
#endif /* UART */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_L2R_Failed             |
+-------------------------------------------------------------------+

  PURPOSE : L2R entity failure

*/

GLOBAL void cmhCC_L2R_Failed ( void )
{
#ifdef FAX_AND_DATA
  SHORT          cId = raShrdPrm.cId;  /* holds call identifier */
  T_CC_CALL_TYPE calltype;

  TRACE_FUNCTION ("cmhCC_L2R_Failed()");

  calltype = cmhCC_getcalltype(cId);

  switch( calltype )
  {
    case( NON_TRANS_CALL ):
      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT_REQ ):
          if( psaCC_ctbIsValid (cId) AND
              psaCC_ctb(cId)->calStat EQ CS_MDF_REQ )
          {
            ccShrdPrm.datStat = DS_ABO_REQ;
          }
          /*lint -fallthrough*/
        case( DS_ACT ):
        case( DS_REST_REQ ):
            cmhL2R_Deactivate ();
          break;
      }
      break;


    case( FAX_CALL  ):

      TRACE_EVENT( "UNEXP BEARER SERV FAX" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhL2R_Deactivate();
      break;
    }

#endif    /* of #ifdef FAX_AND_DATA */
}

#ifdef FF_FAX
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_T30_Activated          |
+-------------------------------------------------------------------+

  PURPOSE : T30 entity activated, data path established

*/

GLOBAL void cmhCC_T30_Activated ( void )
{
#if defined (FAX_AND_DATA) AND defined (DTI)

  T_CC_CMD_PRM * pCCCmdPrm;    /* points to CC command parameters */
  UBYTE cmdBuf;                /* buffers current command */
  SHORT cId = t30ShrdPrm.cId;  /* holds call identifier */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_T30_Activated()");

  pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->calOwn].ccCmdPrm;
  cmdBuf = psaCC_ctb(cId)->curCmd;

  switch( calltype )
  {
    case( FAX_CALL ):
      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT_REQ ):

          ccShrdPrm.datStat = DS_ACT;

          /* reset CMOD to single mode */
          ccShrdPrm.CMODmode = CMOD_MOD_Single;

          if( psaCC_ctb(cId)->calType EQ CT_MTC )
          {
            cmhT30_SendCaps( psaCC_ctb(cId)->curSrc, FRT_DIS );
          }
          break;
      }
      break;

   /* in case of a asynchronous call */
    case( TRANS_CALL ):
    case( NON_TRANS_CALL ):
      TRACE_EVENT( "UNEXP BEARER SERV ASYNC" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhT30_Deactivate();
      break;
    }

#endif    /* of #ifdef FAX_AND_DATA */
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_T30_Deactivated        |
+-------------------------------------------------------------------+

  PURPOSE : T30 entity deactivated, data path disconnected

*/

GLOBAL void cmhCC_T30_Deactivated ( void )
{
#ifdef FAX_AND_DATA

  SHORT cId = t30ShrdPrm.cId;  /* holds call identifier */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_T30_Deactivated()");

  switch( calltype )
  {
    case( FAX_CALL ):
      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT ):
        case( DS_ACT_REQ ):
        case( DS_DSC_REQ ):
        case( DS_MDF_REQ ):
        case( DS_STOP_REQ ):
        case( DS_TCH_MDF ):

          cmhRA_Deactivate ();
          break;
      }
      break;

    /* in case of a asynchronous data call */
    case( TRANS_CALL ):
    case( NON_TRANS_CALL ):

      TRACE_EVENT( "UNEXP BEARER SERV ASYNC" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhRA_Deactivate();
      break;
  }

#endif    /* of #ifdef FAX_AND_DATA */
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_T30_Failed             |
+-------------------------------------------------------------------+

  PURPOSE : T30 entity failure

*/

GLOBAL void cmhCC_T30_Failed ( void )
{
#if defined FAX_AND_DATA AND defined (DTI)

  SHORT cId = t30ShrdPrm.cId;  /* holds call identifier */
  T_CC_CALL_TYPE calltype = cmhCC_getcalltype(cId);

  TRACE_FUNCTION ("cmhCC_T30_Failed()");

  switch( calltype )
  {
    case( FAX_CALL ):

      switch( ccShrdPrm.datStat )
      {
        case( DS_ACT_REQ ):

          if( psaCC_ctb(cId)->calStat EQ CS_MDF_REQ )
          {
            ccShrdPrm.datStat = DS_ABO_REQ;
          }
          /*lint -fallthrough*/
        case( DS_ACT ):
        case( DS_REST_REQ ):
        case( DS_TCH_MDF ):

          cmhT30_Deactivate ();
          break;
      }
      break;

    /* in case of a asynchronous data call */
    case( TRANS_CALL ):
    case( NON_TRANS_CALL ):

      TRACE_EVENT( "UNEXP BEARER SERV ASYNC" );
      ccShrdPrm.datStat = DS_DSC_REQ;
      cmhT30_Deactivate();
      break;
    }

#endif    /* of #ifdef FAX_AND_DATA */
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_T30_RmtCaps            |
+-------------------------------------------------------------------+

  PURPOSE : T30 remote capability indication

*/

GLOBAL void cmhCC_T30_RmtCaps ( void )
{
#ifdef FAX_AND_DATA

  T_CC_CMD_PRM * pCCCmdPrm;    /* points to CC command parameters */
  UBYTE cmdBuf;                /* buffers current command */
  UBYTE srcBuf;                /* buffers current command source */
  SHORT cId = t30ShrdPrm.cId;  /* holds call identifier */

  TRACE_FUNCTION ("cmhCC_T30_RmtCaps()");

/*
 *-------------------------------------------------------------------
 * check if connect is expected
 *-------------------------------------------------------------------
 */
  pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    if( pCCCmdPrm -> mltyCncFlg EQ 0 )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }

#endif    /* of #ifdef FAX_AND_DATA */
}

#endif /* FF_FAX */
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_MPTYBuild              |
+-------------------------------------------------------------------+

  PURPOSE : Multiparty successful build.

*/

GLOBAL void cmhCC_MPTYBuild( SHORT cId,
                             T_BUILD_MPTY_RES *bldMPTY )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE ctbIdx;               /* holds call table index */
  UBYTE cmdBuf;               /* buffers command */
  UBYTE srcBuf;               /* buffers command source */

  TRACE_FUNCTION ("cmhCC_MPTYBuild()");

  TIMERSTOP( ACI_TMPTY );

  if( ctb->curCmd NEQ AT_CMD_CHLD )
    return;  /* wrong command context */

  /* set multiparty status for involved calls */
  for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
  {
    if (ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
        (psaCC_ctb(ctbIdx)->mptyStat  EQ CS_ACT_REQ OR
         psaCC_ctb(ctbIdx)->mptyStat  EQ CS_ACT ))
    {
      psaCC_ctb(ctbIdx)->mptyStat = CS_ACT;
      psaCC_ctb(ctbIdx)->calStat  = CS_ACT;
    }
  }

  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  psaCC_MPTY (cId, MPTY_BUILD_SUCCESS);

  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
        pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_MPTYSplit              |
+-------------------------------------------------------------------+

  PURPOSE : Multiparty successful split.

*/

GLOBAL void cmhCC_MPTYSplit( SHORT cId,
                             T_SPLIT_MPTY_RES *splMPTY )
{
  T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE ctbIdx;               /* holds call table index */
  UBYTE cmdBuf;               /* buffers command */
  UBYTE srcBuf;               /* buffers command source */
  UBYTE fndCId;               /* holds call id of found call */
  UBYTE fndCal;               /* holds number of found calls */

  TRACE_FUNCTION ("cmhCC_MPTYSplit()");

  TIMERSTOP( ACI_TMPTY );

  if( ctb->curCmd NEQ AT_CMD_CHLD )
    return;  /* wrong command context */

  /* set status for involved calls */
  for( fndCal = 0, ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
  {
    if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
        psaCC_ctb(ctbIdx)->mptyStat   EQ  CS_ACT AND
        ctbIdx                           NEQ cId )
    {
      psaCC_ctb(ctbIdx)->calStat  = CS_HLD;
      fndCal++;
      fndCId = ctbIdx;
    }
  }

  /* if only one other call is left, reset multiparty status */
  /* if only one other call is left, do not reset multiparty status - VO patch
  if( fndCal EQ 1 )
  {
    psaCC_ctb(fndCId)->mptyStat = CS_IDL;
  }
  */

  pCCCmdPrm = &cmhPrm[ctb->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);
  ctb->calStat  = CS_ACT;
  ctb->mptyStat = CS_IDL;

  psaCC_MPTY (cId, MPTY_SPLIT_SUCCESS);

  psaCC_setSpeechMode (); /* In case we split from a held mpty */

  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
        pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_MPTYHeld               |
+-------------------------------------------------------------------+

  PURPOSE : Multiparty successful held.

*/

GLOBAL void cmhCC_MPTYHeld( SHORT cId,
                            T_HOLD_MPTY_RES *hldMPTY )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE ctbIdx;               /* holds call table index */
  UBYTE cmdBuf;               /* buffers command */
  UBYTE srcBuf;               /* buffers command source */

  TRACE_FUNCTION ("cmhCC_MPTYHeld()");

  TIMERSTOP( ACI_TMPTY );

  /* check for command context */
  switch( psaCC_ctb(cId)->curCmd )
  {
    case( AT_CMD_CHLD ):
    case( AT_CMD_D ):
      break;

    default:
      return;  /* wrong command context */
  }

  /* set call status for multiparty call member */
  for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
  {
    if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
        psaCC_ctb(ctbIdx)->calStat    EQ CS_HLD_REQ AND
        psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT )
    {
      psaCC_ctb(ctbIdx)->calStat = CS_HLD;
    }
  }

  psaCC_MPTY (cId, MPTY_HOLD_SUCCESS);

  psaCC_setSpeechMode ();

  pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    if((pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActExc OR
        pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActAndAcpt OR
        pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActDial) AND
        pCCCmdPrm -> mltyCncFlg )
    {
      process_CHLDaddInfo( srcBuf, MTPTY_HELD );
    }

    if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
        pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_MPTYRetrieved          |
+-------------------------------------------------------------------+

  PURPOSE : Multiparty successful retrieved.

*/

GLOBAL void cmhCC_MPTYRetrieved( SHORT cId,
                                 T_RETRIEVE_MPTY_RES *rtvMPTY )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  UBYTE ctbIdx;               /* holds call table index */
  UBYTE cmdBuf;               /* buffers command */
  UBYTE srcBuf;               /* buffers command source */

  TRACE_FUNCTION ("cmhCC_MPTYRetrieved()");

  TIMERSTOP( ACI_TMPTY );

  if( psaCC_ctb(cId)->curCmd NEQ AT_CMD_CHLD )
    return;  /* wrong command context */

  /* set call status for multiparty call member */
  for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
  {
    if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
        psaCC_ctb(ctbIdx)->calStat    EQ CS_ACT_REQ AND
        psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT )
    {
      psaCC_ctb(ctbIdx)->calStat = CS_ACT;
    }
  }

  pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

  psaCC_MPTY (cId, MPTY_RETRIEVE_SUCCESS);

  psaCC_setSpeechMode ();

  if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
  {
    if( pCCCmdPrm -> mltyCncFlg EQ 0 AND
        pCCCmdPrm -> mltyDscFlg EQ 0     )  /* if last call */
    {
      R_AT( RAT_OK, srcBuf ) ( cmdBuf );

      /* log result */
      cmh_logRslt ( srcBuf, RAT_OK,
                    cmdBuf, (SHORT)(cId+1), -1, -1 );
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_NotifySS               |
+-------------------------------------------------------------------+

  PURPOSE : SS notification received: in preamble, some
  local functions, otherwise, the function would be huge...

*/


/*
+------------------------------------------------------------------------------
|   Function    :  cssx2I_Code_Convert
+------------------------------------------------------------------------------
|   Description :  This function converts CSSX codes to CSSI codes.
|
|   Parameters  :  cssx_code                 - CSS(X) code
|
|   Return      :  CSSI_CODE_ XXX            - exit sucessful with CSSI_CODE_
|                  CSSI_CODE_NotPresent      - exit not sueccessful
+------------------------------------------------------------------------------
*/

LOCAL T_ACI_CSSI_CODE cssx2I_Code_Convert(T_ACI_CSSX_CODE cssx_code)
{
  T_ACI_CSSI_CODE cssi_code;
  switch (cssx_code)
  {
    case( CSSX_CODE_ForwardedCall ):
      cssi_code = CSSI_CODE_ForwardedCall;
      break;
    case( CSSX_CODE_CFUActive ):
      cssi_code = CSSI_CODE_CFUActive;
      break;
    case( CSSX_CODE_SomeCCFActive ):
      cssi_code = CSSI_CODE_SomeCCFActive;
      break;
    case( CSSX_CODE_CallWaiting ):
      cssi_code = CSSI_CODE_CallWaiting;
      break;
    case( CSSX_CODE_OutCallsBarred ):
      cssi_code = CSSI_CODE_OutCallsBarred;
      break;
    case( CSSX_CODE_IncCallsBarred ):
      cssi_code = CSSI_CODE_IncCallsBarred;
      break;
    case( CSSX_CODE_CLIRSupRej ):
      cssi_code = CSSI_CODE_CLIRSupRej;
      break;
    case( CSSX_CODE_DeflectedCall ):
      cssi_code = CSSI_CODE_DeflectedCall;
      break;
  case( CSSX_CODE_CUGCall ):
      cssi_code = CSSI_CODE_CUGCall;
      break;

  default:
      cssi_code = CSSI_CODE_NotPresent;
      break;
    }
  return cssi_code;
}

/*
+------------------------------------------------------------------------------
|   Function    :  cssx2U_Code_Convert
+------------------------------------------------------------------------------
|   Description :  This function converts CSSX codes to CSSU codes.
|
|   Parameters  :  cssx_code                 - CSS(X) code
|
|   Return      :  CSSU_CODE_ XXX            - exit sucessful with CSSU_CODE_
|                  CSSU_CODE_NotPresent      - exit not sueccessful
+------------------------------------------------------------------------------
*/

LOCAL T_ACI_CSSU_CODE cssx2U_Code_Convert(T_ACI_CSSX_CODE cssx_code)
{
  T_ACI_CSSU_CODE cssu_code;
  switch (cssx_code)
  {
    case( CSSX_CODE_ForwardedCall ):
      cssu_code = CSSU_CODE_ForwardedCall;
      break;
    case(  CSSX_CODE_CUGCall ):
      cssu_code = CSSU_CODE_CUGCall ;
      break;
    case( CSSX_CODE_OnHold ):
      cssu_code = CSSU_CODE_OnHold;
      break;
    case( CSSX_CODE_Retrieved ):
      cssu_code = CSSU_CODE_Retrieved;
      break;
    case( CSSX_CODE_Multiparty ):
      cssu_code = CSSU_CODE_Multiparty;
      break;
    case( CSSX_CODE_HeldCallRel ):
      cssu_code = CSSU_CODE_HeldCallRel;
      break;
    case( CSSX_CODE_FwrdCheckSS ):
      cssu_code = CSSU_CODE_FwrdCheckSS;
      break;
    case( CSSX_CODE_ECTAlert ):
      cssu_code = CSSU_CODE_ECTAlert;
      break;
    case( CSSX_CODE_ECTConnect ):
      cssu_code = CSSU_CODE_ECTConnect;
      break;
    case( CSSX_CODE_DeflectedCall ):
      cssu_code = CSSU_CODE_DeflectedCall;
      break;

    default:
      cssu_code = CSSU_CODE_NotPresent;
      break;
  }
  return cssu_code;
}


/*
+------------------------------------------------------------------------------
|   Function    :  send_CSSX_notification
+------------------------------------------------------------------------------
|   Description :  This function sends CSSU and CSSI.
|
|   Parameters  :  ctbIdx                    - call table index
|                  cssx_code                 - CSS(X) code
|                  index                     - Index
|                  *number                   - buffer for number
|                  *toa                      - buffers type of address
|                  *subaddr                  - buffer for subaddress
|                  *tos                      - holds type of subaddress
|
|   Return      :
+------------------------------------------------------------------------------
*/

GLOBAL void send_CSSX_notification(SHORT ctbIdx,
                                   T_ACI_CSSX_CODE cssx_code,
                                   SHORT index,
                                   CHAR            *number,
                                   T_ACI_TOA       *toa,
                                   CHAR            *subaddr,
                                   T_ACI_TOS       *tos)

{
  UBYTE idx;     /* holds index counter */

  /*  Check if CC State is CS ACT REQ */
  if (ctbIdx > NO_ENTRY AND
      psaCC_ctb(ctbIdx)->calStat EQ CS_ACT_REQ AND 
      psaCC_ctb(ctbIdx)->calType EQ CT_MOC)
  {
    T_ACI_CSSI_CODE cssi_code;
    cssi_code = cssx2I_Code_Convert(cssx_code);
    if (cssi_code != CSSI_CODE_NotPresent )
    {
      S8 source = psaCC_ctb(ctbIdx)->curSrc;
      R_AT( RAT_CSSI, source)( cssi_code, index );
    }
  }
  else /* (calldirection EQ CT_MTC) */
  {
    /* Sent CSSU TO ALL */
    T_ACI_CSSU_CODE cssu_code;
    cssu_code = cssx2U_Code_Convert(cssx_code);
    if (cssu_code != CSSU_CODE_NotPresent )
    {
      for( idx = 0; idx < CMD_SRC_MAX; idx++ )
      {
        R_AT( RAT_CSSU, idx )(cssu_code, index, number, toa, subaddr, tos);
      }
    }
  }
}



LOCAL void cmhCC_NotifySS_v_ssCode( SHORT cId, T_NOTIFY_SS_INV *ntfySS )
{
  CHAR numBuf[MAX_B_SUBSCR_NUM_LEN];         /* buffer for number */
  T_ACI_TOA toa;                             /* holds type of address */
  CHAR subBuf[MAX_SUBADDR_LEN];              /* buffer for subaddress */
  T_ACI_TOS tos;                             /* holds type of subaddress */

  TRACE_FUNCTION ("cmhCC_NotifySS_v_ssCode()");

  switch( ntfySS -> notifySSArg.ssCode )
  {
     case( SS_CD_ALL_FWSS ):
     case( SS_CD_CFU ):
      if( ntfySS -> notifySSArg.v_ssStatus AND
          ntfySS -> notifySSArg.ssStatus & SSS_A )
      {
        send_CSSX_notification(cId,
                              CSSX_CODE_CFUActive,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);
      }
      break;

    case( SS_CD_CFB       ):
    case( SS_CD_CFNRY     ):
    case( SS_CD_CFNRC     ):
    case( SS_CD_ALL_CFWSS ):

      if( ntfySS -> notifySSArg.v_ssStatus AND
          ntfySS -> notifySSArg.ssStatus & SSS_A )
      {

         send_CSSX_notification(cId,
                              CSSX_CODE_SomeCCFActive,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);
      }
      break;

    case( SS_CD_ALL_CBSS ):

      if( ntfySS -> notifySSArg.v_ssStatus AND
          ntfySS -> notifySSArg.ssStatus & SSS_A )
      {
        /* RAT_CSSI ... outgoing calls are barred  */
        /* RAT_CSSI ... incoming calls are barred  */
        send_CSSX_notification(cId,
                              CSSX_CODE_OutCallsBarred,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

        send_CSSX_notification(cId,
                              CSSX_CODE_IncCallsBarred,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

      }
      break;

    case( SS_CD_BOC ):
    case( SS_CD_BAOC ):
    case( SS_CD_BOIC ):
    case( SS_CD_BOICXH ):

      if( ntfySS -> notifySSArg.v_ssStatus AND
          ntfySS -> notifySSArg.ssStatus & SSS_A )
      {
        /* RAT_CSSI ... outgoing calls are barred  */
        send_CSSX_notification(cId,
                              CSSX_CODE_OutCallsBarred,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

      }
      break;

    case( SS_CD_BIC ):
    case( SS_CD_BAIC ):
    case( SS_CD_BICRM ):

      if( ntfySS -> notifySSArg.v_ssStatus AND
          ntfySS -> notifySSArg.ssStatus & SSS_A )
      {
        /* RAT_CSSI ... incoming calls are barred  */
     send_CSSX_notification(cId,
                              CSSX_CODE_IncCallsBarred,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

}
      break;

    case( SS_CD_CD ):
      if (ntfySS->notifySSArg.v_ssNotification AND
          ntfySS->notifySSArg.ssNotification.fwdSubscriber EQ
            FWD_C_INC_CALL_FWD)
      {
        /*
         * If alerting is allowed now, send the CSSU indication.
         * Otherwise just remember that we got this notification.
         */
        if ((ccShrdPrm.TCHasg EQ TRUE) OR
            (psaCC_ctb(cId)->sigInf NEQ SIG_NOT_PRES))

        {
          /*
           * The conditions for user alerting are fulfilled.
           * Send the +CSSU: unsolicited result code now.
           */
          send_CSSX_notification(cId,
                              CSSX_CODE_DeflectedCall,
                              ACI_NumParmNotPresent,
                              psaCC_ctbRdrAdr2Num (cId, numBuf, sizeof (numBuf)),
                              cmhCC_ctbGetRdrNumTyp (cId, &toa),
                              psaCC_ctbRdrAdr2Sub (cId, subBuf),
                              cmhCC_ctbGetRdrSubTyp (cId, &tos));

          psaCC_FreeRdrPty (cId);
          psaCC_ctb(cId)->CDStat = NO_VLD_CD;
        }
        else
        {
          /*
           * Indication of the MT call towards the MMI is deferred until
           * the alerting conditions are fulfilled (TCH assignment).
           */
          psaCC_ctb(cId)->CDStat = CD_Notified;
        }
        return;
      }

      if (ntfySS->notifySSArg.v_ssNotification AND
          ntfySS->notifySSArg.ssNotification.clgSubscriber EQ
            CLG_A_OUTG_CALL_FWD_C)
      {
        /* RAT_CSSI ... outgoing call has been deflected */
        send_CSSX_notification(cId,
                              CSSX_CODE_DeflectedCall,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

      }
      break;

    default:
      TRACE_EVENT( "UNHANDLED SS-CODE IN NOTIFY" );
      break;
  }
}

LOCAL void cmhCC_NotifySS_v_ssNotification( SHORT cId, T_NOTIFY_SS_INV *ntfySS )
{

  TRACE_FUNCTION ("cmhCC_NotifySS_v_ssNotification()");

  if( ntfySS -> notifySSArg.ssNotification.clgSubscriber EQ
      CLG_A_OUTG_CALL_FWD_C )
  {
    /* RAT_CSSI ... outgoing call has been forwarded  */
    send_CSSX_notification(cId,
                              CSSX_CODE_ForwardedCall,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);
  }

  if( ntfySS -> notifySSArg.ssNotification.fwgSubscriber EQ
      FWG_B_INC_CALL_FWD_C )
  {
    /* RAT_CSSU ... this is a forwarded call  */
    send_CSSX_notification(cId,
                            CSSX_CODE_ForwardedCall,
                            ACI_NumParmNotPresent ,
                            NULL, NULL, NULL, NULL);

  }

  if( ntfySS -> notifySSArg.ssNotification.fwdSubscriber EQ
      FWD_C_INC_CALL_FWD )
  {
    /* RAT_CSSU ... this is a forwarded call  */
    send_CSSX_notification(cId,
                            CSSX_CODE_ForwardedCall,
                            ACI_NumParmNotPresent ,
                            NULL, NULL, NULL, NULL);

  }
}




LOCAL void cmhCC_NotifySS_v_ectIndicator( SHORT cId, T_NOTIFY_SS_INV *ntfySS )
{
  CHAR numBuf[MAX_B_SUBSCR_NUM_LEN];         /* buffer for number */
  T_ACI_TOA toa;                             /* holds type of address */
  CHAR subBuf[MAX_SUBADDR_LEN];              /* buffer for subaddress */
  T_ACI_TOS tos;                             /* holds type of subaddress */
  BOOL numFlg   = FALSE;                     /* flags a present number */
  BOOL subFlg   = FALSE;                     /* flags a present subaddress */

  TRACE_FUNCTION ("cmhCC_NotifySS_v_ectIndicator()");

  /* note that according to GSM 04.91, indications without RDN are
     possible but not without ectCallState */
  if( ntfySS -> notifySSArg.ectIndicator.v_ectCallState )
  {
    /* (G)ACI-FIX-1415 */
    if(ntfySS -> notifySSArg.ectIndicator.v_rdn )
    {
      if( ntfySS -> notifySSArg.ectIndicator.
        rdn.v_presentationAllowedAddress )
      {
        if( ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationAllowedAddress.v_partyNumber AND
          ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationAllowedAddress.partyNumber.c_bcdDigit )
        {
          utl_BCD2DialStr
            (ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partyNumber.bcdDigit,
            numBuf,
            ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partyNumber.c_bcdDigit);

          toa.npi = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partyNumber.npi;
          toa.ton = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partyNumber.noa;

          numFlg = TRUE;
        }

        if( ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationAllowedAddress.v_partySubaddress AND
          ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationAllowedAddress.partySubaddress.c_bcdDigit )
        {
          utl_BCD2DialStr
            (ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partySubaddress.bcdDigit,
            subBuf,
            ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partySubaddress.c_bcdDigit);

          tos.tos = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partySubaddress.tos;
          tos.oe  = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationAllowedAddress.partySubaddress.oei;

          subFlg = TRUE;
        }
      }
      /* check if the override case occured, do present RDN, (G)ACI-FIX-1434 */
      /* if presentationAllowedAddress is present then it is obsolete to look
         at presentationRestrictedAddress */
      else if( ntfySS -> notifySSArg.ectIndicator.
        rdn.v_presentationRestrictedAddress )
      {
        if( ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationRestrictedAddress.v_partyNumber AND
          ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationRestrictedAddress.partyNumber.c_bcdDigit )
        {
          utl_BCD2DialStr
            (ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partyNumber.bcdDigit,
            numBuf,
            ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partyNumber.c_bcdDigit);

          toa.npi = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partyNumber.npi;
          toa.ton = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partyNumber.noa;

          numFlg = TRUE;
        }

        if( ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationRestrictedAddress.v_partySubaddress AND
          ntfySS -> notifySSArg.ectIndicator.
          rdn.presentationRestrictedAddress.partySubaddress.c_bcdDigit )
        {
          utl_BCD2DialStr
            (ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partySubaddress.bcdDigit,
            subBuf,
            ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partySubaddress.c_bcdDigit);

          tos.tos = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partySubaddress.tos;
          tos.oe  = ntfySS -> notifySSArg.ectIndicator.
            rdn.presentationRestrictedAddress.partySubaddress.oei;

          subFlg = TRUE;
        }
      }
    }

    switch( ntfySS -> notifySSArg.ectIndicator.ectCallState )
    {
      case( ECT_CS_ALERTING ):
        /* RAT_CSSU ... ECT alerting */
        send_CSSX_notification(cId,
                                CSSX_CODE_ECTAlert,
                                ACI_NumParmNotPresent,
                                (numFlg)?numBuf:NULL,
                                (numFlg)?&toa:NULL,
                                (subFlg)?subBuf:NULL,
                                (subFlg)?&tos:NULL);
        break;

      case( ECT_CS_ACTIVE ):
        /* RAT_CSSU ... ECT active */
        send_CSSX_notification(cId,
                                CSSX_CODE_ECTConnect,
                                ACI_NumParmNotPresent,
                                (numFlg)?numBuf:NULL,
                                (numFlg)?&toa:NULL,
                                (subFlg)?subBuf:NULL,
                                (subFlg)?&tos:NULL);

        break;
    }
  }
}

LOCAL void cmhCC_NotifySS_v_ccbsf( T_NOTIFY_SS_INV *ntfySS )
{
  T_ACI_CCBS_SET ccbsSet;                    /* holds ccbs setting */

  TRACE_FUNCTION ("cmhCC_NotifySS_v_ccbsf()");

  if( ntfySS -> notifySSArg.ccbsf.v_ccbsIndex )
  {
    ccbsSet.idx = ntfySS -> notifySSArg.ccbsf.ccbsIndex;
  }
  else
    ccbsSet.idx = ACI_NumParmNotPresent;

  if( ntfySS -> notifySSArg.ccbsf.v_b_subscriberNumber AND
      ntfySS -> notifySSArg.ccbsf.b_subscriberNumber.c_bcdDigit)
  {
    utl_BCD2DialStr
      (ntfySS -> notifySSArg.ccbsf.b_subscriberNumber.bcdDigit,
       ccbsSet.number,
       ntfySS -> notifySSArg.ccbsf.b_subscriberNumber.c_bcdDigit);

    ccbsSet.type.npi = ntfySS -> notifySSArg.ccbsf.b_subscriberNumber.npi;
    ccbsSet.type.ton = ntfySS -> notifySSArg.ccbsf.b_subscriberNumber.noa;
  }
  else
  {
    ccbsSet.number[0] = 0x0;
    ccbsSet.type.npi = NPI_NotPresent;
    ccbsSet.type.ton = TON_NotPresent;
  }

  if( ntfySS -> notifySSArg.ccbsf.v_b_subscriberSubaddress AND
      ntfySS -> notifySSArg.ccbsf.b_subscriberSubaddress.c_bcdDigit)
  {
    utl_BCD2DialStr
      (ntfySS -> notifySSArg.ccbsf.b_subscriberSubaddress.bcdDigit,
       ccbsSet.subaddr,
       ntfySS -> notifySSArg.ccbsf.b_subscriberSubaddress.c_bcdDigit);

    ccbsSet.satype.tos = ntfySS -> notifySSArg.ccbsf.b_subscriberSubaddress.tos;
    ccbsSet.satype.oe  = ntfySS -> notifySSArg.ccbsf.b_subscriberSubaddress.oei;
  }
  else
  {
    ccbsSet.subaddr[0] = 0x0;
    ccbsSet.satype.tos = TOS_NotPresent;
    ccbsSet.satype.oe  = OE_NotPresent;
  }

  if( ntfySS -> notifySSArg.ccbsf.v_basicServiceGroup )
    ccbsSet.class_type = cmhSS_GetClass( (T_basicService*)&ntfySS -> notifySSArg.ccbsf.
                            basicServiceGroup );
  else
    ccbsSet.class_type = CLASS_NotPresent;

  if( ntfySS -> notifySSArg.v_alertingPattern )
  {
    ccbsSet.alrtPtn = ntfySS -> notifySSArg.alertingPattern;
  }
  else
  {
    ccbsSet.alrtPtn = ALPT_NotPresent;
  }

  cmhrat_ccbs( CMD_SRC_MAX, CCBS_IND_Recall,
               CCBS_STAT_NotPresent, &ccbsSet );
}


GLOBAL void cmhCC_NotifySS( SHORT cId, T_NOTIFY_SS_INV *ntfySS )
{
  UBYTE         idx;        /* holds index counter */
  T_callingName *NameId;    /* holds Name Identifier for CNAP */

  TRACE_FUNCTION ("cmhCC_NotifySS()");

  /* check SS code */
  if( ntfySS -> notifySSArg.v_ssCode )
  {
    cmhCC_NotifySS_v_ssCode( cId, ntfySS );
  }

  /* check SS notification */
  if( ntfySS -> notifySSArg.v_ssNotification )
  {
    cmhCC_NotifySS_v_ssNotification( cId, ntfySS );
  }

  /* check call is waiting indicator */
  if( ntfySS -> notifySSArg.v_callIsWaitingIndicator )
  {
    /* RAT_CSSI ... call is waiting */
    send_CSSX_notification(cId,
                              CSSX_CODE_CallWaiting,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

  }

  /* check call on hold indicator */
  if( ntfySS -> notifySSArg.v_callOnHoldIndicator )
  {
    switch( ntfySS -> notifySSArg.callOnHoldIndicator )
    {
    case( CHLD_CALL_RETRIEVED ):
      send_CSSX_notification(cId,
                              CSSX_CODE_Retrieved,
                              ACI_NumParmNotPresent ,
                              NULL, NULL, NULL, NULL);

      break;

    case( CHLD_CALL_ON_HOLD ):
      /* RAT_CSSU ... call has been put on hold */
      send_CSSX_notification(cId,
                              CSSX_CODE_OnHold,
                              ACI_NumParmNotPresent ,
                              NULL, NULL, NULL, NULL);

      break;
    }
  }

  /* check multparty indicator */
  if( ntfySS -> notifySSArg.v_mptyIndicator )
  {
    /* If the Call is on hold and a SS_Notify with a MPTY
       the state shall change from CS_HOLD to CS_ACT */
      psaCC_ctb(cId)->calStat  = CS_ACT;
      /* mptyStat equal to CS_ACT_REQ set it to CS_ACT
         required to place multiparty call on hold */
      if(psaCC_ctb(cId)->mptyStat EQ CS_ACT_REQ)
      {
        psaCC_ctb(cId)->mptyStat = CS_ACT;
      }

    /* RAT_CSSU ... multiparty call entered */
    send_CSSX_notification(cId,
                              CSSX_CODE_Multiparty,
                              ACI_NumParmNotPresent ,
                              NULL, NULL, NULL, NULL);

}

  /* check CUG index */
  if( ntfySS -> notifySSArg.v_cugIndex )
  {
      send_CSSX_notification(cId,
                              CSSX_CODE_CUGCall,
                              ntfySS -> notifySSArg.cugIndex,
                              NULL, NULL, NULL, NULL);
  }

  /* check CLIR suppression */
  if( ntfySS -> notifySSArg.v_clirSuppressionRejected )
  {
    /* RAT_CSSI ... CLIR  suppression rejected */
    send_CSSX_notification(cId,
                              CSSX_CODE_CLIRSupRej,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

  }

  /* check ECT indicator */
  if( ntfySS -> notifySSArg.v_ectIndicator )
  {
    cmhCC_NotifySS_v_ectIndicator( cId, ntfySS );
  }

  /* check CNAP indicator */
  if( ntfySS -> notifySSArg.v_nameIndicator )
  {
    if ( ntfySS -> notifySSArg.nameIndicator.v_callingName )
    {
      NameId = &(ntfySS -> notifySSArg.nameIndicator.callingName);
      for( idx = 0; idx < CMD_SRC_MAX; idx++ )
      {
        R_AT( RAT_CNAP, idx )
          ( NameId, CNAP_SERVICE_STATUS_NOT_PRESENT);
      }
    }
  }

  /* check CCBS feature */
  if( ntfySS -> notifySSArg.v_ccbsf )
  {
    cmhCC_NotifySS_v_ccbsf( ntfySS );
  }
}



/*
+------------------------------------------------------------------------------
|   Function    :  cmhCC_CheckSS
+------------------------------------------------------------------------------
|   Description :  check SS indication received.
|
|   Parameters  :  cId -
|
|   Return      :
+------------------------------------------------------------------------------
*/
GLOBAL void cmhCC_CheckSS( SHORT cId )
{
  UBYTE idx;                      /* holds index counter */

  TRACE_FUNCTION ("cmhCC_CheckSS()");

/*
 *-------------------------------------------------------------------
 * indicate check SS
 *-------------------------------------------------------------------
 */
  /* RAT_CSSU ... forward check SS indication */
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    send_CSSX_notification( cId,
                              CSSX_CODE_FwrdCheckSS,
                              ACI_NumParmNotPresent,
                              NULL, NULL, NULL, NULL);

  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CCBSRegistered         |
+-------------------------------------------------------------------+

  PURPOSE :  call completion to busy subscriber successfully registered.

*/

GLOBAL void cmhCC_CCBSRegistered( SHORT cId,
                                  T_ACC_REGISTER_CC_ENTRY_RES *CCBSreg )
{
  UBYTE          cmdBuf;                    /* buffers command */
  UBYTE          srcBuf;                    /* buffers command source */
  T_ACI_CCBS_SET ccbsSet;                   /* holds ccbs setting */

  TRACE_FUNCTION ("cmhCC_CCBSRegistered()");

  /* check for command context */
  if( psaCC_ctb(cId)->curCmd NEQ AT_CMD_CHLD )
  {
    TRACE_EVENT("cmhCC_CCBSRegistered: wrong command context !");
    return;
  }

  if( CCBSreg->accRegisterCCEntryRes.v_ccbsf )
  {
    if( CCBSreg->accRegisterCCEntryRes.ccbsf.v_ccbsIndex )

      ccbsSet.idx = CCBSreg->accRegisterCCEntryRes.ccbsf.ccbsIndex;
    else
      ccbsSet.idx = ACI_NumParmNotPresent;


    if( CCBSreg->accRegisterCCEntryRes.ccbsf.
        v_b_subscriberNumber                  AND
        CCBSreg->accRegisterCCEntryRes.ccbsf.
        b_subscriberNumber.c_bcdDigit)
    {
      utl_BCD2DialStr
        (CCBSreg->accRegisterCCEntryRes.ccbsf.b_subscriberNumber.
         bcdDigit,
         ccbsSet.number,
         CCBSreg->accRegisterCCEntryRes.ccbsf.b_subscriberNumber.
         c_bcdDigit);

      ccbsSet.type.npi = CCBSreg->accRegisterCCEntryRes.ccbsf.
                         b_subscriberNumber.npi;
      ccbsSet.type.ton = CCBSreg->accRegisterCCEntryRes.ccbsf.
                         b_subscriberNumber.noa;
    }
    else
    {
      ccbsSet.number[0] = 0x0;
      ccbsSet.type.npi = NPI_NotPresent;
      ccbsSet.type.ton = TON_NotPresent;
    }

    if( CCBSreg->accRegisterCCEntryRes.ccbsf.
        v_b_subscriberSubaddress              AND
        CCBSreg->accRegisterCCEntryRes.ccbsf.
        b_subscriberSubaddress.c_bcdDigit)
    {
      utl_BCD2DialStr
        (CCBSreg->accRegisterCCEntryRes.ccbsf.b_subscriberSubaddress.
         bcdDigit,
         ccbsSet.subaddr,
         CCBSreg->accRegisterCCEntryRes.ccbsf.b_subscriberSubaddress.
         c_bcdDigit);

      ccbsSet.satype.tos = CCBSreg->accRegisterCCEntryRes.ccbsf.
                   b_subscriberSubaddress.tos;
      ccbsSet.satype.oe  = CCBSreg->accRegisterCCEntryRes.ccbsf.
                   b_subscriberSubaddress.oei;
    }
    else
    {
      ccbsSet.subaddr[0] = 0x0;
      ccbsSet.satype.tos = TOS_NotPresent;
      ccbsSet.satype.oe  = OE_NotPresent;
    }

    if( CCBSreg->accRegisterCCEntryRes.ccbsf.v_basicServiceGroup )
      ccbsSet.class_type = cmhSS_GetClass( (T_basicService*)&CCBSreg->accRegisterCCEntryRes.
                                       ccbsf.basicServiceGroup );
    else
      ccbsSet.class_type = CLASS_NotPresent;

    ccbsSet.alrtPtn = ALPT_NotPresent;
  }

  cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);
  cmhCC_tstAndUnflagCall( cId, &(cmhPrm[srcBuf].ccCmdPrm.mltyDscFlg));
  psaCC_FreeCtbNtry (cId);

  cmhrat_ccbs( srcBuf, CCBS_IND_Registered,
               CCBS_STAT_NotPresent, &ccbsSet );

  R_AT( RAT_OK, srcBuf ) ( cmdBuf );

  /* log result */
  cmh_logRslt ( srcBuf, RAT_OK,
                cmdBuf, (SHORT)(cId+1), -1, -1 );
}

/* sends RAT_CCBS: sometimes it is an intermediate result, and sometimes it is an
indication.
When srcId = CMD_SRC_MAX, it is an indication and shall go to all sources...
Otherwise, only to the source specified... */
GLOBAL void cmhrat_ccbs( UBYTE           srcId,
                         T_ACI_CCBS_IND  ccbs_ind,
                         T_ACI_CCBS_STAT status,
                         T_ACI_CCBS_SET  *setting )
{
  UBYTE idx;

  if( srcId EQ CMD_SRC_MAX )
  {
#if defined MFW || defined SMI OR defined FF_MMI_RIV
    rAT_PercentCCBS(ccbs_ind, status, setting);
#endif

#ifdef FF_ATI
    for( idx = CMD_SRC_ATI_1; idx < CMD_SRC_MAX; idx++ )
    {
      srcId_cb = idx;
      rCI_PercentCCBS(ccbs_ind, status, setting, FALSE);      
    }
#endif /* FF_ATI */

    return;
  }
#if defined MFW || defined SMI OR defined FF_MMI_RIV
  if( srcId EQ CMD_SRC_LCL )
  {
    rAT_PercentCCBS( ccbs_ind, status, setting );
    return;
  }
#endif

  /* else it is an ATI source */
  srcId_cb = srcId;

#ifdef FF_ATI
  rCI_PercentCCBS(ccbs_ind, status, setting, TRUE);
#endif /* FF_ATI */
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_CDRegistered           |
+-------------------------------------------------------------------+

  PURPOSE :  Call Deflection (CD) successfully registered.

*/

GLOBAL void cmhCC_CDRegistered( SHORT cId )
{
  TRACE_FUNCTION ("cmhCC_CDRegistered()");

  switch( psaCC_ctb(cId)->curCmd )
  {
    case AT_CMD_CTFR:
      psaCC_ctb(cId)->CDStat = CD_Succeeded;
      break;

    default: /* This is unexpected or network failure, ignore the event */
      break;
  }
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_SSTransFail            |
+-------------------------------------------------------------------+

  PURPOSE : SS transaction failed.

*/

GLOBAL void cmhCC_SSTransFail   ( SHORT cId )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  SHORT ctbIdx;               /* holds call table index */
  SHORT addId;                /* holds additional call id */
  UBYTE cmdBuf;               /* buffers command */
  UBYTE srcBuf;               /* buffers command source */

  TRACE_FUNCTION ("cmhCC_SSTransFail()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( psaCC_ctb(cId)->curCmd )
  {
   /*
    *----------------------------------------------------------------
    * process result for D and A command
    *----------------------------------------------------------------
    */
    case( AT_CMD_D ):
    case( AT_CMD_A ):

      /* restore call status for hold request*/
      if( psaCC_ctb(cId)->calStat EQ CS_HLD_REQ )
        for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
        {
          if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
              psaCC_ctb(ctbIdx)->calStat    EQ CS_HLD_REQ AND
              psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT )
          {
            psaCC_ctb(ctbIdx)->calStat = CS_ACT;
          }
        }

      pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;

      cmhCC_PrepareCmdEnd (cId, &cmdBuf, &srcBuf);

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {
        if( pCCCmdPrm -> CHLDmode EQ CHLD_MOD_HldActDial AND
            pCCCmdPrm -> mltyCncFlg )
        {
          for( addId = 0; !((pCCCmdPrm -> mltyCncFlg >> addId) & 0x01); addId++ )
            ;

          if( CHLDaddInfo EQ CHLD_ADD_INFO_DIAL_CAL )
          {
              CHLDaddInfo = NO_CHLD_ADD_INFO;
              psaCC_FreeCtbNtry (addId);  /* remove pending call */
          }
        }

        pCCCmdPrm -> mltyCncFlg = 0;        /* unflag calls */

        R_AT( RAT_CME, srcBuf ) ( cmdBuf, CME_ERR_NotPresent );

        cmh_logRslt ( srcBuf, RAT_CME,
                        cmdBuf, -1, -1, CME_ERR_NotPresent );
      }
      break;

   /*
    *----------------------------------------------------------------
    * process result for +CTFR command
    *----------------------------------------------------------------
    */
    case( AT_CMD_CTFR ):
      psaCC_ctb(cId)->CDStat = CD_Failed;
      break;

   /*
    *----------------------------------------------------------------
    * process result for +CHLD command
    *----------------------------------------------------------------
    */
    case( AT_CMD_CHLD ):

      /* determine CHLD mode */
      switch( cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm.CHLDmode )
      {
       /*
        *------------------------------------------------------------
        * no multiparty relation
        *------------------------------------------------------------
        */
        case( CHLD_MOD_NotPresent ):
        case( CHLD_MOD_RelHldOrUdub ):
        case( CHLD_MOD_RelActSpec ):

          TRACE_EVENT( "UNEXP CHLD MODE FOR SS ERROR COMP" );
          return;

       /*
        *------------------------------------------------------------
        * multiparty hold or retrieve
        *------------------------------------------------------------
        */
        case( CHLD_MOD_RelActAndAcpt ):
        case( CHLD_MOD_HldActAndAcpt ):

          /* restore call status for retrieve request */
          if( psaCC_ctb(cId)->calStat EQ CS_ACT_REQ )
          {
            for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
            {
              if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
                  psaCC_ctb(ctbIdx)->calStat    EQ CS_ACT_REQ AND
                  psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT )
              {
                psaCC_ctb(ctbIdx)->calStat = CS_HLD;
              }
            }
            psaCC_MPTY (cId, MPTY_RETRIEVE_FAIL);
          }

          /* restore call status for hold request*/
          if( psaCC_ctb(cId)->calStat EQ CS_HLD_REQ )
          {
            for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
            {
              if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
                  psaCC_ctb(ctbIdx)->calStat    EQ CS_HLD_REQ AND
                  psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT )
              {
                psaCC_ctb(ctbIdx)->calStat = CS_ACT;
              }
            }
            psaCC_MPTY (cId, MPTY_HOLD_FAIL);
          }

          break;

       /*
        *------------------------------------------------------------
        * multiparty split
        *------------------------------------------------------------
        */
        case( CHLD_MOD_HldActExc ):

          psaCC_ctb(cId)->mptyStat = CS_ACT;
          psaCC_MPTY (cId, MPTY_SPLIT_FAIL);
          break;

       /*
        *------------------------------------------------------------
        * multiparty build
        *------------------------------------------------------------
        */
        case( CHLD_MOD_AddHld ):

          /* restore call status for build request */
          for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
          {
            if( ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
                psaCC_ctb(ctbIdx)->mptyStat   EQ CS_ACT_REQ AND
                psaCC_ctb(ctbIdx)->calStat    EQ CS_HLD )
            {
              psaCC_ctb(ctbIdx)->mptyStat = CS_IDL;
            }
          }

          if( psaCC_ctb(cId)->mptyStat EQ CS_ACT_REQ )
            psaCC_ctb(cId)->mptyStat = CS_IDL;
          psaCC_MPTY (cId, MPTY_BUILD_FAIL);
          break;

       /*
        *------------------------------------------------------------
        * explicit call transfer
        *------------------------------------------------------------
        */
        case( CHLD_MOD_Ect ):
          pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
          TRACE_EVENT("ECT failed...");

          TIMERSTOP( ACI_TECT );

          /* restore call status for other call that was to be transfered */
          for( ctbIdx = 0; ctbIdx < MAX_CALL_NR; ctbIdx++ )
          {
            if( ctbIdx EQ cId )
            {
              continue;
            }
            else if (ccShrdPrm.ctb[ctbIdx] NEQ NULL AND
                     cmhCC_tstAndUnflagCall( ctbIdx, &(pCCCmdPrm -> mltyDscFlg)) AND
                     psaCC_ctb(ctbIdx)->curCmd EQ AT_CMD_CHLD )
            {
              /* then it is the second call id */
              cmhCC_PrepareCmdEnd (ctbIdx, NULL, NULL);
            }
          }

          /* restore first call id parameters */
          cmhCC_PrepareCmdEnd (cId, NULL, &srcBuf);

          if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyDscFlg)) )
          {
            R_AT( RAT_CME, srcBuf )
                        ( AT_CMD_CHLD, CME_ERR_Unknown );

            cmh_logRslt ( srcBuf, RAT_CME,
                          AT_CMD_CHLD, -1, -1, CME_ERR_Unknown );
          }
          return;

       /*
        *------------------------------------------------------------
        * call completion to busy subscriber
        *------------------------------------------------------------
        */
        case( CHLD_MOD_Ccbs ):
          pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
          TRACE_EVENT("CCBS failed...");

          /* restore first call id parameters */
          cmhCC_PrepareCmdEnd (cId, NULL, &srcBuf);

          if( psaCC_ctb(cId)->opCode EQ OPC_ACC_REGISTER_CC_ENTRY )
            psaCC_FreeCtbNtry (cId);  /* remove call table entry */

          if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyDscFlg)) )
          {
            pCCCmdPrm -> mltyDscFlg = 0;        /* unflag calls */

            R_AT( RAT_CME, srcBuf )
                        ( AT_CMD_CHLD, CME_ERR_Unknown );

            cmh_logRslt ( srcBuf, RAT_CME,
                          AT_CMD_CHLD, -1, -1, CME_ERR_Unknown );
          }
          return;
      }

      pCCCmdPrm = &cmhPrm[psaCC_ctb(cId)->curSrc].ccCmdPrm;
      cmhCC_PrepareCmdEnd (cId, NULL, &srcBuf);

      if( cmhCC_tstAndUnflagCall( cId, &(pCCCmdPrm -> mltyCncFlg)))
      {
        pCCCmdPrm -> mltyCncFlg = 0;        /* unflag calls */

        R_AT( RAT_CME, srcBuf ) ( AT_CMD_CHLD, CME_ERR_Unknown );

        cmh_logRslt ( srcBuf, RAT_CME,
                      AT_CMD_CHLD, -1, -1, CME_ERR_Unknown );
      }

      break;
  }

  return;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCR                 |
|                                 ROUTINE : cmhCC_MPTYTimeout       |
+-------------------------------------------------------------------+

  PURPOSE : handle multiparty timeout

*/

GLOBAL void cmhCC_MPTYTimeout ( void )
{
  TRACE_FUNCTION( "cmhCC_MPTYTimeout()" );

  if (!psaCC_ctbIsValid (ccShrdPrm.cIdMPTY))
  {
    TRACE_ERROR ("ccShrdPrm.cIdMPTY invalid");
    return;
  }

/*
 *-------------------------------------------------------------------
 * SS failure
 *-------------------------------------------------------------------
 */
#ifdef SIM_TOOLKIT
  if (psaCC_ctb(ccShrdPrm.cIdMPTY)->SATinv )
  {
    psaCC_ctb(ccShrdPrm.cIdMPTY)->SATinv = FALSE;
    /* return network error cause GSM 11.14 / 12.12.3 */
    cmhSAT_NtwErr( ADD_NO_CAUSE );
  }
#endif
  cmhCC_SSTransFail(ccShrdPrm.cIdMPTY);

}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCR                 |
|                                 ROUTINE : cmhCC_ECTTimeout        |
+-------------------------------------------------------------------+

  PURPOSE : handle explicit call transfer timeout

*/

LOCAL SHORT search_ect_call(void)
{
  SHORT idx;
  UBYTE chld_src;

  for(idx = 0; idx < MAX_CALL_NR; idx++)
  {
    if (ccShrdPrm.ctb[idx] NEQ NULL AND
        psaCC_ctb(idx)->curCmd EQ AT_CMD_CHLD)
    {
      chld_src = psaCC_ctb(idx)->curSrc;

      if( cmhPrm[chld_src].ccCmdPrm.CHLDmode EQ CHLD_MOD_Ect )
      {
        return(idx);
      }
    }
  }
  return(NO_ENTRY);
}

GLOBAL void cmhCC_ECTTimeout ( void )
{
  SHORT ectId;

  TRACE_FUNCTION( "cmhCC_ECTTimeout()" );

  ectId = search_ect_call( );

  if (ectId NEQ NO_ENTRY)
  cmhCC_SSTransFail(ectId);
}

#ifdef FF_TTY
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_TTY_Control            |
+-------------------------------------------------------------------+

  PURPOSE : Enabling/disabling TTY for the active call

*/

LOCAL BOOL cmhCC_TTY_Proceed (SHORT cId)
{
  T_TTY_CMD ttyAction = TTY_OFF;
  T_bcpara *bc;

  if (ccShrdPrm.ctb[cId] NEQ NULL)
  {
    /* Call table entry exists */
    bc = &psaCC_ctb(cId)->BC[psaCC_ctb(cId)->curBC];
  
    if ((bc->bearer_serv EQ BEARER_SERV_SPEECH_CTM OR
       bc->bearer_serv EQ BEARER_SERV_AUX_SPEECH_CTM) AND
        psaCC_ctb(cId)->calStat NEQ CS_DSC_REQ)
  {
    if ((ccShrdPrm.chMod EQ CHM_SPEECH) OR
        (ccShrdPrm.chMod EQ CHM_SPEECH_V2) OR
        (ccShrdPrm.chMod EQ CHM_SPEECH_V3))
    {
      audio_set_tty (ttyAction = (T_TTY_CMD)ccShrdPrm.ttyCmd);
    }
    else
    {
      TRACE_EVENT_P1 ("TTY no speech mode: %d", (int)ccShrdPrm.chMod);
    }
  }
  else
  {
    TRACE_EVENT_P1 ("TTY wrong BCAP: %d", (int)bc->bearer_serv);
  }

  if (ttyAction NEQ (UBYTE)TTY_OFF)
  {
    cmhCC_notifyTTY (CTTY_NEG_Grant, cmhCC_getTTYtrx_state (ttyAction));
    return TRUE;
  }
  else
  {
    cmhCC_notifyTTY (((ccShrdPrm.ctmReq EQ CTM_ENABLED)?
                      CTTY_NEG_Reject: CTTY_NEG_None),
                     CTTY_TRX_Unknown);
  }
  }
  else
  {
    TRACE_EVENT ("TTY no call table entry");
  }

  return FALSE;
}

GLOBAL void cmhCC_TTY_Control (SHORT cId, UBYTE action)
{
  TRACE_EVENT_P3 ("TTY event %d, old state %d, callId %d",
                  action, ccShrdPrm.ctmState, cId);

  if (!ccShrdPrm.TCHasg)
  {
    TRACE_EVENT ("TTY: no TCH");
  }
  switch (action)
  {
  case TTY_TCH:
    if (ccShrdPrm.ctmState EQ TTY_STATE_IDLE)
    {
      ccShrdPrm.ctmState = TTY_STATE_SYNC;
    }
    else if (ccShrdPrm.ctmState EQ TTY_STATE_BCAP)
    {
      if (cmhCC_TTY_Proceed (cId))
        ccShrdPrm.ctmState = TTY_STATE_ACTIVE;
      else
        ccShrdPrm.ctmState = TTY_STATE_WAIT;
    }
    break;

  case TTY_START:
    if (ccShrdPrm.ctmState EQ TTY_STATE_IDLE)
    {
      ccShrdPrm.ctmState = TTY_STATE_BCAP;
    }
    else if (ccShrdPrm.ctmState EQ TTY_STATE_SYNC)
    {
      if (cmhCC_TTY_Proceed (cId))
        ccShrdPrm.ctmState = TTY_STATE_ACTIVE;
      else
        ccShrdPrm.ctmState = TTY_STATE_WAIT;
    }
    break;

  case TTY_PAUSE:
    if (ccShrdPrm.ctmState EQ TTY_STATE_WAIT)
    {
      ccShrdPrm.ctmState = TTY_STATE_SYNC;
    }
    else if (ccShrdPrm.ctmState EQ TTY_STATE_ACTIVE)
    {
      audio_set_tty (TTY_OFF);
      ccShrdPrm.ctmState = TTY_STATE_SYNC;
    }
    break;

  case TTY_STOP:
    if (ccShrdPrm.ctmState EQ TTY_STATE_ACTIVE)
    {
      audio_set_tty (TTY_OFF);
      cmhCC_notifyTTY (CTTY_NEG_None, CTTY_TRX_Off);
    }
    ccShrdPrm.ctmState = (ccShrdPrm.ctmReq EQ CTM_ENABLED)?
                         TTY_STATE_IDLE: TTY_STATE_NONE;
    break;

  default:
    break;
  }
  TRACE_EVENT_P1 ("TTY new state %d", ccShrdPrm.ctmState);
}
#endif /* FF_TTY */

#if defined (FF_WAP) || defined (FF_TCP_IP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E) 
/* Only for WAP or RNET */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_PPP_Established        |
+-------------------------------------------------------------------+

  PURPOSE : PPP entity activated, data path established

*/

GLOBAL SHORT cmhCC_PPP_Established (ULONG ip_address, USHORT max_receive_unit,
                                    ULONG dns1, ULONG dns2)
{

  char c_ip_address[16],c_dns1[16],c_dns2[16];
  SHORT cId = raShrdPrm.cId;
  TRACE_FUNCTION ("cmhCC_PPP_Established()");

  ipAddress = ip_address;
  sprintf (c_ip_address, "%03u.%03u.%03u.%03u", (ip_address & 0xff000000) >> 24,
                                                (ip_address & 0x00ff0000) >> 16,
                                                (ip_address & 0x0000ff00) >> 8 ,
                                                (ip_address & 0x000000ff)        );

  sprintf(c_dns1, "%03u.%03u.%03u.%03u",       (dns1 & 0xff000000) >> 24,
                                               (dns1 & 0x00ff0000) >> 16,
                                               (dns1 & 0x0000ff00) >> 8 ,
                                               (dns1 & 0x000000ff)        );
  
  sprintf(c_dns2, "%03u.%03u.%03u.%03u",       (dns2 & 0xff000000) >> 24,
                                               (dns2 & 0x00ff0000) >> 16,
                                               (dns2 & 0x0000ff00) >> 8 ,
                                               (dns2 & 0x000000ff)        );

  TRACE_EVENT_P3("addr : %s ,dns1 : %s ,dns2: %s",c_ip_address,c_dns1,c_dns2);

  if(is_gpf_tcpip_call()) {
    pppShrdPrm.ipaddr = ip_address ;
    pppShrdPrm.dns1   = dns1 ;
    pppShrdPrm.dns2   = dns2 ;
  }
#ifdef FF_TCP_IP
  if (psaCC_ctbIsValid (cId) AND /* Ensure not to dereferentiate NULL */
      pppShrdPrm.is_PPP_CALL EQ TRUE)
  {
    pppShrdPrm.ipaddr = ip_address ;
    pppShrdPrm.dns1   = dns1 ;
    pppShrdPrm.dns2   = dns2 ;
    R_AT( RAT_CONNECT, raShrdPrm.owner )
      (psaCC_ctb(cId)->curCmd, 
       cmhCC_GetDataRate(&psaCC_ctb(cId)->BC[psaCC_ctb(cId)->curBC]),
       cId+1, 
       FALSE);
    return 0;
  }
#endif /*FF_TCP_IP*/

#if defined (FF_SAT_E)
  if(cmhSAT_OpChnChckCSD(UDP))
  {
    psaTCPIP_Configure((UBYTE*)c_ip_address, NULL, NULL, 
                       (UBYTE*)c_dns1, (UBYTE*)c_dns2,max_receive_unit,
                       cmhSAT_OpChnUDPConfCsd) ;
  }
  else
#endif /* FF_SAT_E */
#if defined (FF_WAP) || defined (FF_GPF_TCPIP)
  {
    psaTCPIP_Configure((UBYTE*)c_ip_address, NULL, NULL, 
                       (UBYTE*)c_dns1, (UBYTE*)c_dns1,max_receive_unit,
                       psaTCPIP_conf_csd_callback) ;
  }
#endif /* FF_WAP OR FF_GPF_TCPIP */
  return 0;
}

#ifdef CO_UDP_IP
/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_IPA_Configurated       |
+-------------------------------------------------------------------+

  PURPOSE : IPA entity activated, data path established
*/

GLOBAL SHORT cmhCC_IPA_Configurated (void)
{
  TRACE_FUNCTION ("cmhCC_IPA_Configurated()");

  psaUDPA_Config(UDPA_CONFIG_UP);

  return 0;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_UDPA_Configurated      |
+-------------------------------------------------------------------+

  PURPOSE : IPA entity activated, data path established

*/

GLOBAL SHORT cmhCC_UDPA_Configurated (void)
{
  TRACE_FUNCTION ("cmhCC_UDPA_Configurated()");
#ifdef FF_WAP
  if (Wap_Call)
  {
    if ( tcpipShrdPrm.connection_type EQ TCPIP_CONNECTION_TYPE_CSD_WAP )
    {
      rAT_WAP_PPP_connected(wapId,ipAddress);
    }
    else
    {
      TRACE_EVENT_P1 ("IP: %s", tcpipShrdPrm.ipaddr);
      rAT_WAP_PPP_connected(wapId, psaTCPIP_bytes2ipv4addr(tcpipShrdPrm.ipaddr));
    }
  }
#endif      
  psaUDPIP_config_dispatch() ;
  return 0;
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_UDPA_Deconfigurated    |
+-------------------------------------------------------------------+

  PURPOSE :

*/

GLOBAL SHORT cmhCC_UDPA_Deconfigurated (void)
{
  TRACE_FUNCTION ("cmhCC_UDPA_Deconfigurated ()");

  cmhUDPA_Deactivate(tcpipShrdPrm.src_id);

  return 0;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_IPA_Deconfigurated     |
+-------------------------------------------------------------------+

  PURPOSE :

*/

GLOBAL SHORT cmhCC_IPA_Deconfigurated (void)
{
  TRACE_FUNCTION ("cmhCC_IPA_Deconfigurated()");

  psaUDPA_Config(UDPA_CONFIG_DOWN);

  return 0;
}

#endif /* of WAP || SAT E */

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_PPP_Terminated         |
+-------------------------------------------------------------------+

  PURPOSE : PPP entity terminated, close connection / update CC parameters

*/

GLOBAL SHORT cmhCC_PPP_Terminated ( void )
{
  TRACE_FUNCTION ("cmhCC_PPP_Terminated()");

#ifdef DTI
#if defined (FF_WAP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E) 
  if (Wap_Call EQ TRUE)
  {
    if(is_gpf_tcpip_call()) {
      GPF_TCPIP_STATEMENT(dti_cntrl_entity_disconnected(peer_link_id, 
                                                        DTI_ENTITY_TCPIP ));
    }
    else {
    dti_cntrl_entity_disconnected( peer_link_id, DTI_ENTITY_IP );
    }
    dti_cntrl_entity_disconnected( prot_link_id, DTI_ENTITY_L2R );
  }
#endif /* WAP || defined (FF_GPF_TCPIP) || SAT E */

  dti_cntrl_entity_disconnected( peer_link_id, DTI_ENTITY_PPPC );
  dti_cntrl_entity_disconnected( prot_link_id, DTI_ENTITY_PPPC );


#if defined (FF_SAT_E)
  if( cmhSAT_OpChnChckCSD(UDP))
  {
    psaTCPIP_Deactivate(cmhSAT_OpChnUDPDeactCsd) ;
  }
  else
#endif /* FF_SAT_E */
#if defined (FF_WAP) OR defined (FF_GPF_TCPIP)
  {
    psaTCPIP_Deactivate(psaTCPIP_deact_csd_callback) ;
  }
#endif /* defined (WAP) OR defined (FF_GPF_TCPIP) */
#endif /* DTI */
  return 0;
}


#endif /* of WAP or FF_TCP_IP || defined (FF_GPF_TCPIP) or SAT E */

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

  PURPOSE : Call-backs for ALS support check.
*/

GLOBAL void cmhCC_checkALS_Support_cb ( SHORT aId )
{
  TRACE_FUNCTION ("cmhCC_checkALS_Support_cb()");

  simShrdPrm.atb[aId].ntryUsdFlg = FALSE;

  /* Step #1: Reading of CPHS Info */
  if (simShrdPrm.atb[aId].errCode NEQ SIM_NO_ERROR OR
      simShrdPrm.atb[aId].exchData EQ NULL OR
      simShrdPrm.atb[aId].dataLen < 2)
  {
    ;  /* CPHS info not supported or invalid */
  }
  else if ((simShrdPrm.atb[aId].exchData[1] & 0x03) EQ ALLOCATED_AND_ACTIVATED)
  {
    /* continue with step 2 */
    cmhCC_checkALS_Support_2();
    return;
  }

  cmhCC_checkALS_Support_exec( 0 );
}

GLOBAL void cmhCC_checkALS_Support_cb_2 ( SHORT aId )
{
  int i;

  TRACE_FUNCTION ("cmhCC_checkALS_Support_cb_2()");

  simShrdPrm.atb[aId].ntryUsdFlg = FALSE;

  if (simShrdPrm.atb[aId].errCode NEQ SIM_NO_ERROR OR
      simShrdPrm.atb[aId].exchData EQ NULL         OR
      simShrdPrm.atb[aId].dataLen < ACI_CPHS_CSP_SIZE )
  {
    ;  /* CSP not supported or invalid */
  }
  else
  {
    for (i = 0; i < simShrdPrm.atb[aId].dataLen; i += 2)
    {
      if (simShrdPrm.atb[aId].exchData[i] EQ ALS_SERVICE_GROUP_CODE)
      {
        if (BITFIELD_CHECK(simShrdPrm.atb[aId].exchData[i+1],ALS_BIT_ON))
        {
          cmhCC_checkALS_Support_exec( 1 );
          return;
        }
        break;
      }
    }
  }

  cmhCC_checkALS_Support_exec( 0 );
}


GLOBAL void cmhCC_checkALS_Support_exec ( UBYTE flag )
{
  T_ACI_CMD_SRC ownBuf;       /* buffers current owner */
  T_ACI_ALS_MOD ALSmode;

  TRACE_FUNCTION ("cmhCC_checkALS_Support_exec()");

  ownBuf = simEntStat.entOwn;

  simEntStat.curCmd = AT_CMD_NONE;
  simEntStat.entOwn = simShrdPrm.owner = OWN_NONE;

  switch (ccShrdPrm.als_cmd)
  {
    case ALS_CMD_SET:
      if (flag)
      {
        cmhPrm[ownBuf].ccCmdPrm.ALSmode = ALS_MOD_AUX_SPEECH;
        R_AT( RAT_OK, ownBuf ) ( AT_CMD_ALS );
      }
      else
      {
        R_AT( RAT_CME, ownBuf ) ( AT_CMD_ALS, CME_ERR_OpNotSupp );
      }      
      break;
    case ALS_CMD_TEST:
      if (flag)
      {
        ALSmode = ALS_MOD_SPEECH | ALS_MOD_AUX_SPEECH;
      }
      else 
      {
        ALSmode = ALS_MOD_SPEECH;
      }
      R_AT( RAT_ALS, ownBuf ) ( ALSmode );
      R_AT( RAT_OK, ownBuf ) ( AT_CMD_ALS );
      break;
    default:
      TRACE_EVENT("wrong value in als_cmd");
      R_AT( RAT_CME, ownBuf ) ( AT_CMD_ALS, CME_ERR_OpNotSupp );
  }
  ccShrdPrm.als_cmd = ALS_CMD_NONE;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCR                 |
|                                 ROUTINE : cmhCC_redialTimeout     |
+-------------------------------------------------------------------+

  PURPOSE : handle redial timeout

*/

GLOBAL void cmhCC_redialTimeout ( void )
{
  int i;
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */

  TRACE_FUNCTION( "cmhCC_redialTimeout()" );

  if (psaCC_ctbIsValid (rdlPrm.rdlcId))
  {
    pCCCmdPrm = &cmhPrm[psaCC_ctb(rdlPrm.rdlcId)->curSrc].ccCmdPrm;

    if (rdlPrm.rdlMod EQ AUTOM_REPEAT_ON)
    {
      if((psaCC_ctb(rdlPrm.rdlcId)->rdlTimIndex >= 1) AND 
         (psaCC_ctb(rdlPrm.rdlcId)->rdlTimIndex < 3))
      {
#ifdef _SIMULATION_
          TIMERSTART(ACI_REPEAT_1,ACI_REPEAT_HND);
#else
          psaCC_ctb(rdlPrm.rdlcId)->rdlTimIndex++;
          TIMERSTART(ACI_REPEAT_2_4,ACI_REPEAT_HND);
#endif
      }
      else
      {
        psaCC_ctb(rdlPrm.rdlcId)->rdlTimIndex = RDL_TIM_INDEX_NOT_PRESENT;
        psaCC_ctb(rdlPrm.rdlcId)->rdlCnt++;
        for(i = 0; i < CMD_SRC_MAX; i++)
        {
          R_AT(RAT_RDL, i)(REDIAL_ATT_START);
        }
        psaCC_ctb(rdlPrm.rdlcId)->calType = CT_MOC_RDL;
        cmhCC_flagCall( rdlPrm.rdlcId, &(pCCCmdPrm->mltyCncFlg));
        /* start a new call */
        psaCC_NewCall(rdlPrm.rdlcId);
        rdlPrm.rdlcId = NO_ENTRY;
      }
    }
    else
    {
        TRACE_EVENT("cmhCC_redialTimeout: wrong cId");
    }
  }
}


/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)    MODULE  : CMH_CCR                      |
|                            ROUTINE : cmhCC_sendFie                |
+-------------------------------------------------------------------+

  PURPOSE : forward unsolicited facility responses from CC to terminal

*/
GLOBAL T_ACI_RETURN cmhCC_sendFie( T_ACI_FAC_DIR tDirection,
                                         SHORT         cId,
                                         T_fac_inf    *fie )
{
  T_ACI_CMD_SRC tSrc;

  TRACE_EVENT( "cmhCC_sendFie()" );

  for( tSrc=CMD_SRC_LCL; tSrc<CMD_SRC_MAX; tSrc++ )  /* try over all sources */
  {
    if( cmhPrm[tSrc].ccCmdPrm.CSCNcc_mode.CcCSCNModeState EQ CC_CSCN_MOD_STATE_ON )
    {
      switch (cmhPrm[tSrc].ccCmdPrm.CSCNcc_mode.CcCSCNModeDirection)
      {
        case CC_CSCN_MOD_DIR_BOTH:
          break; /* printout regardless of direction */

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

        case CC_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_CCCN, tSrc )( tDirection, cId, fie );
    }
  }
  return( AT_CMPL );
}

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