view src/g23m-aci/aci/cmh_ccs.c @ 149:163b839c55de

rm mmiGame.[ch]
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 16 Nov 2020 06:03:26 +0000
parents fa8dc04885d8
children
line wrap: on
line source

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

#ifndef CMH_CCS_C
#define CMH_CCS_C
#endif

#include "aci_all.h"

#include "aci_cmh.h"
#include "ksd.h"

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

/* for CCD */
#include "ccdapi.h"
#include "aci.h" /*  for CCD_END... */

/***********/

#include "ati_cmd.h"
#include "aci_cmd.h"

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

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

#ifdef FF_TTY
#include "audio.h"
#endif

#include "aci_mem.h"
#include "l4_tim.h"

#include "phb.h"
#include "psa.h"
#include "psa_cc.h"
#include "psa_sim.h"
#include "psa_mm.h"
#include "psa_ss.h"
#include "psa_util.h"
#include "cmh.h"
#include "cmh_cc.h"
#include "cmh_mm.h"
#include "cmh_sim.h"
#include "cmh_phb.h"

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

#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"
#endif

#ifdef DTI
#if defined (FF_WAP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E) 
#include "wap_aci.h"
#include "psa_ppp_w.h"
#include "cmh_ppp.h"
#endif  /* FF_WAP || FF_GPF_TCPIP || FF_SAT_E */
#endif /* DTI */

#ifdef GPRS
#include "gaci.h"
#include "gaci_cmh.h"
#include "psa_sm.h"
#include "cmh_sm.h"
#endif  /* GPRS */

#include "aoc.h"
#include "ksd.h"

#ifdef ACI
#include "cmh_mmi.h"
#endif

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

/*==== CONSTANTS ==================================================*/
#ifdef TI_PS_FF_AT_CMD_P_ECC
//LOCAL char additional_ecc_numbers[ADDITIONAL_ECC_NUMBER_MAX][ADDITIONAL_ECC_NUMBER_LENGTH];
LOCAL char additional_ecc_numbers[ADDITIONAL_ECC_NUMBER_MAX][ADDITIONAL_ECC_NUMBER_LENGTH+1]; //OMAPS00117704/OMAPS00117705
#endif /* TI_PS_FF_AT_CMD_P_ECC */
#ifdef TI_PS_FF_AT_P_CMD_RDLB
GLOBAL T_ACI_CC_REDIAL_BLACKL * cc_blacklist_ptr = NULL;
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
/*==== EXPORT =====================================================*/


#if defined (GPRS) AND defined (DTI)
EXTERN T_ATI_RSLT atGD (char *cl, UBYTE srcId, BOOL *gprs_command);
#endif  /* GPRS */

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

/* Implements Measure#32: Row 89, 90, 116, 117, 1241 & 1242 */
const char * const ksd_supp_clir_str = "*31#";
const char * const ksd_inv_clir_str = "#31#";

EXTERN T_PCEER causeMod;
EXTERN SHORT causeCeer;
/* parameter block for delayed cmhCC_Dial call */
LOCAL struct cmhCC_Dial_buffer { 
  T_ACI_CMD_SRC srcId;
} cmhCC_Dial_buffer;

#ifdef TI_PS_FF_AT_P_CMD_CUSCFG
EXTERN T_ACI_CUSCFG_PARAMS cuscfgParams;
#endif /* TI_PS_FF_AT_P_CMD_CUSCFG */
/*==== PROTOTYPES =================================================*/

LOCAL UCHAR cmhCC_Dial_delayed (void *arg);
LOCAL T_ACI_RETURN chld_RelHldOrUdub(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_RelActAndAcpt(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_RelActSpec(T_ACI_CMD_SRC srcId, CHAR *call);
LOCAL T_ACI_RETURN chld_HldActAndAcpt(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_HldActExc(T_ACI_CMD_SRC srcId, CHAR *call);
LOCAL T_ACI_RETURN chld_AddHld(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_Ect(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_Ccbs(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_OnlyHold(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_RelDialCall(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_RetrieveHoldCall(T_ACI_CMD_SRC srcId);
LOCAL T_ACI_RETURN chld_RetrieveHoldCallSpec(T_ACI_CMD_SRC srcId, CHAR *call);
LOCAL T_ACI_RETURN chld_RelAnySpec(T_ACI_CMD_SRC srcId, CHAR *call);
LOCAL BOOL cmhCC_check_RedialCall         ( T_ACI_AT_CMD at_cmd_id );
LOCAL BOOL cmhCC_check_pending_satCall();
LOCAL BOOL chld_HoldActiveCalls           ( T_ACI_CMD_SRC srcId,
                                            BOOL *mptyHldFlg,
                                            BOOL *hldCalFlg, 
                                            SHORT *cId );
LOCAL T_ACI_RETURN chld_Rel_MultipartySpec( T_ACI_CMD_SRC srcId,
                                            SHORT *spcId,
                                            T_ACI_CHLD_MOD chld_mode,
                                            CHAR *call );
LOCAL void cmhCC_disconnect_waiting_call  ( T_ACI_CMD_SRC srcId,
                                            SHORT waitId,
                                            T_ACI_AT_CMD at_cmd_id,
                                            USHORT *mltyDscFlg );

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

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

  PURPOSE : This is the functional counterpart to the D> AT command
            which is responsible to originate a call using the phone-
            book. The searched number can be declared either by the
            name or by giving the index of a specified phonebook. If
            an entry could be found, the ordinary AT D command is
            called.

            <str>     : name string to search.
            <mem>     : type of phonebook.
            <index>   : phonebook index.
            <clirOvrd>: CLIR override
            <cugCtrl> : CUG control
            <callType>: call type
*/

#define RETURN(x) { retVal = x; goto cleanup_exit; }
/*lint -e{801} Use of goto*/
#ifdef NO_ASCIIZ
GLOBAL T_ACI_RETURN sAT_Dm        ( T_ACI_CMD_SRC     srcId,
                                    T_ACI_PB_TEXT     *str,
                                    T_ACI_PB_STOR     mem,
                                    SHORT             index,
                                    T_ACI_D_CLIR_OVRD clirOvrd,
                                    T_ACI_D_CUG_CTRL  cugCtrl,
                                    T_ACI_D_TOC       callType )
#else  /* ifdef NO_ASCIIZ */
GLOBAL T_ACI_RETURN sAT_Dm        ( T_ACI_CMD_SRC     srcId,
                                    CHAR              *str,
                                    T_ACI_PB_STOR     mem,
                                    SHORT             index,
                                    T_ACI_D_CLIR_OVRD clirOvrd,
                                    T_ACI_D_CUG_CTRL  cugCtrl,
                                    T_ACI_D_TOC       callType )
#endif /* ifdef NO_ASCIIZ */
{
  T_CLPTY_PRM *cldPty;        /* holds calling party parameter */
  T_ACI_RETURN retVal;        /* holds function return value */
  T_PHB_RECORD phbNtry;       /* holds phonebook entry */
  T_PHB_TYPE slctPHB;         /* holds selected phonebook */
  T_ACI_PB_TEXT *dial_name;
#ifndef NO_ASCIIZ
  T_ACI_PB_TEXT dialname;
#endif /* #ifndef NO_ASCIIZ */

  ACI_MALLOC (cldPty, sizeof (T_CLPTY_PRM));

  TRACE_FUNCTION ("sAT_Dm()");
/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    RETURN( AT_FAIL )
  }

  /* init cldPty */
  cmhCC_init_cldPty( cldPty );

#ifdef NO_ASCIIZ
  dial_name = str;
#else  /* #ifdef NO_ASCIIZ */
  dial_name = &dialname;

  if ( str NEQ NULL )
  {
    USHORT len = (USHORT)strlen( str );

    cmh_cvtToDefGsm ( str, (CHAR*)dial_name->data, &len );
    dial_name->cs = CS_Sim;
    dial_name->len = (UBYTE)len;
  }
  else
  {
    dial_name->cs = CS_NotPresent;
    dial_name->len = 0;
  }
#endif /* #ifdef NO_ASCIIZ */

/*
 *-------------------------------------------------------------------
 * check for name search
 *-------------------------------------------------------------------
 */
  if( dial_name->len NEQ 0 )
  {
    if( psaCC_phbSrchName( srcId, dial_name, cldPty ) )
      RETURN( cmhCC_Dial( srcId, cldPty, clirOvrd, cugCtrl, callType ))

    else
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_NotFound );
      RETURN( AT_FAIL )
    }
  }

/*
 *-------------------------------------------------------------------
 * check for index read
 *-------------------------------------------------------------------
 */
#ifdef NO_ASCIIZ
  if( ( !str OR !str->len ) AND index NEQ ACI_NumParmNotPresent )
#else  /* #ifdef NO_ASCIIZ */
  if( !str AND index NEQ ACI_NumParmNotPresent )
#endif /* #ifdef NO_ASCIIZ */
  {
    if( !cmhPHB_cvtPhbType ((( mem EQ PB_STOR_NotPresent )?
            cmhPrm[srcId].phbCmdPrm.cmhStor : mem), &slctPHB ))
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      RETURN( AT_FAIL )
    }

#ifdef TI_PS_FFS_PHB
    if (pb_read_record (slctPHB, index, &phbNtry) EQ PHB_OK)
#else
    if( pb_read_phys_record( slctPHB, index, &phbNtry ) EQ PHB_OK )
#endif
    {
      cmhPHB_getAdrStr( cldPty->num, sizeof (cldPty->num) - 1,
                        phbNtry.number, phbNtry.len );

      cmh_demergeTOA ( phbNtry.ton_npi, &cldPty->ton, &cldPty->npi );
      RETURN( cmhCC_Dial( srcId, cldPty, clirOvrd, cugCtrl, callType ))
    }
    else
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_InvIdx );
      RETURN( AT_FAIL )
    }
  }
  RETURN( AT_FAIL )

  /* The one and only exit out of this function to avoid memory leaks */
cleanup_exit:
  ACI_MFREE (cldPty);
  return retVal;
}

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

  PURPOSE : This is the functional counterpart to the D AT command
            which is responsible to originate a call to a given phone
            number. The D command starts to establish a new call if no
            call is currently active. Otherwise if a call is in active
            state the D command starts to modify the active call. If the
            call mode set by the +CMOD command indicates a single call
            no modification takes place and the D command returns with
            a fail.

            <number>  : phone number.
            <clirOvrd>: CLIR override
            <cugCtrl> : CUG control
            <callType>: call type
*/

GLOBAL T_ACI_RETURN sAT_Dn       ( T_ACI_CMD_SRC srcId,
                                   CHAR * number,
                                   T_ACI_D_CLIR_OVRD clirOvrd,
                                   T_ACI_D_CUG_CTRL  cugCtrl,
                                   T_ACI_D_TOC       callType )
{
/* Implements Measure#32: Row 88  */
  CHAR trace_number_buffer[59];
  T_CLPTY_PRM *cldPty = NULL; /* holds calling party parameter */
  T_ACI_RETURN retVal;        /* holds function return value */
#if defined (GPRS) AND defined (DTI)
  BOOL              gprs_command;
  T_ATI_RSLT        r_value;
#endif  /* GPRS */

  TRACE_FUNCTION ("sAT_Dn()");
  if (number NEQ NULL)
  {
    /* char trcBuf[80]; */
/* Implements Measure#32: Row 88  */
    strncpy (&trace_number_buffer[0], number, 58);
    trace_number_buffer[58] = '\0';

    if (trace_number_buffer[55])
    {
      trace_number_buffer[55] = trace_number_buffer[56] = trace_number_buffer[57] = '.';  /* add trailing "..." if string is >=76 */
    }
    TRACE_EVENT_P1 ("sAT_Dn(): dialled nb=%s",trace_number_buffer);
  }
/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

#if defined (GPRS) AND defined (DTI)
  r_value = atGD( number, (UBYTE) srcId, &gprs_command );
  if ( gprs_command EQ TRUE)
  {
    /* SPR#1983 - SH */
    switch (r_value)
    {
      case ATI_CMPL:
        return AT_CMPL;

      case ATI_EXCT:
        return AT_EXCT;

      default:
        return AT_FAIL;
    }
    /* end SPR#1983 */
  }
#endif  /* GPRS */

  ACI_MALLOC (cldPty, sizeof (T_CLPTY_PRM));

  /* initialize called party parameter */
  if(number NEQ NULL)
  {
    cmhCC_init_cldPty( cldPty );

    cmh_bldCalPrms ( number, cldPty );
  }

/*
 *-------------------------------------------------------------------
 * start dialling
 *-------------------------------------------------------------------
 */
  retVal = cmhCC_Dial( srcId,
                      (number NEQ NULL) ? cldPty : NULL,
                      clirOvrd,
                      cugCtrl,
                      callType );
  ACI_MFREE (cldPty);
  return retVal;
}


/* initialize cldPty structure */
GLOBAL void cmhCC_init_cldPty( /*lint -e(578) */T_CLPTY_PRM *cldPty )
{
  cldPty->num[0] = 0;
  cldPty->ton = MNCC_TON_NOT_PRES;
  cldPty->npi = MNCC_NPI_NOT_PRES;
  cldPty->sub[0] = 0;
  cldPty->tos = MNCC_TOS_NOT_PRES;
  cldPty->oe  = MNCC_OE_EVEN;
}


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

  PURPOSE : This is the functional counterpart to the %CHLD AT command
            which is responsible to handle the supplementary services
            witin a call. This function is resonsible for the +CHLD
            and %CHLD command both.
*/
LOCAL T_ACI_RETURN cmhCC_CHLD_Serv(T_ACI_CMD_SRC    srcId,
                                    T_ACI_CHLD_MOD   mode,
                                    CHAR            *call)
{
  /* check command source */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    return( AT_FAIL );
  }

  switch( mode )
  {
    /* release all held calls, or UDUB for CWA */
    case( CHLD_MOD_RelHldOrUdub ):
      return(chld_RelHldOrUdub(srcId));

    /* release all active calls, and accept held or waiting call */
    case( CHLD_MOD_RelActAndAcpt ):
      return(chld_RelActAndAcpt(srcId));

    /* release a specific active call */
    case( CHLD_MOD_RelActSpec ):
      return(chld_RelActSpec(srcId, call));

    /* place all active calls on hold, and accept held or waiting call */
    case( CHLD_MOD_HldActAndAcpt ):
      return(chld_HldActAndAcpt(srcId));

    /* place all active calls on hold except the specified call */
    case( CHLD_MOD_HldActExc ):
      return(chld_HldActExc(srcId, call));

    /* add a held call to the conversation */
    case( CHLD_MOD_AddHld ):
      return(chld_AddHld(srcId));

    /* explicit call transfer */
    case( CHLD_MOD_Ect ):
      return(chld_Ect(srcId));

    /* activate call completion to busy subscriber */
    case( CHLD_MOD_Ccbs ):
      return(chld_Ccbs(srcId));

    /* place a call on hold */
    case(CHLD_MOD_OnlyHold):
      return(chld_OnlyHold(srcId));

    /* release currently dialling call only */
    case(CHLD_MOD_RelDialCall):
      return(chld_RelDialCall(srcId));

    /* retrive first held call on the list */
    case(CHLD_MOD_RetrieveHoldCall):
      return(chld_RetrieveHoldCall(srcId));

    /* retrieve specific held call */
    case(CHLD_MOD_RetrieveHoldCallSpec):
      return(chld_RetrieveHoldCallSpec(srcId, call));

    /* releases specific call */
    case(CHLD_MOD_RelAnySpec):
      return(chld_RelAnySpec(srcId, call));

    }
  /* for unexpected conditions */
  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
  return( AT_FAIL );
}

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

  PURPOSE : Start dialling.

*/

/* helper function for delivering delayed rAT_PlusCPMS callback */
LOCAL UCHAR cmhCC_Dial_delayed (void* arg)
{
  struct cmhCC_Dial_buffer* p = (struct cmhCC_Dial_buffer*) arg;
  TRACE_EVENT("delayed delivery of RAT_NO_CARRIER after cmhCC_Dial");
  R_AT( RAT_NO_CARRIER, p->srcId ) ( AT_CMD_D, 0 );
  return FALSE; /* single-shot */
}

GLOBAL T_ACI_RETURN cmhCC_Dial   ( T_ACI_CMD_SRC     srcId,
                 /*lint -e(578) */ T_CLPTY_PRM      *cldPty,
                                   T_ACI_D_CLIR_OVRD clirOvrd,
                                   T_ACI_D_CUG_CTRL  cugCtrl,
                                   T_ACI_D_TOC       callType )
{
  SHORT cId, newId;           /* holds call id */
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
  T_ACI_RETURN   retVal;      /* holds return value */
  UBYTE          prio;        /* holds priority of the call */
  USHORT         dummy=0;
  UBYTE idx;

#if defined SMI OR defined MFW  OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif

  TRACE_FUNCTION ("cmhCC_Dial()");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  causeMod  = P_CEER_mod;      /* Clear module which was set for ceer */
  causeCeer = CEER_NotPresent; /* Clear proprietary cause when at point of dialling. */
/*
 *-------------------------------------------------------------------
 * check for an active call
 *-------------------------------------------------------------------
 */

  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT );

#ifdef FAX_AND_DATA

  if( cId NEQ NO_ENTRY )
  {

  /*
   *-----------------------------------------------------------------
   * check call mode to modify the call
   *-----------------------------------------------------------------
   */
    if( cmhCC_ChckInCallMdfy( cId, AT_CMD_D ) )
    {
      cmhCC_flagCall( cId, &(pCCCmdPrm->mltyCncFlg));
      psaCC_ctb(cId)->curCmd = AT_CMD_D;
      psaCC_ctb(cId)->curSrc = srcId;
      psaCC_ModifyCall(cId);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
      /* log command */
      cmdLog.atCmd                = AT_CMD_D;
      cmdLog.cmdType              = CLOG_TYPE_Set;
      cmdLog.retCode              = AT_EXCT;
      cmdLog.cId                  = cId+1;
      cmdLog.sId                  = ACI_NumParmNotPresent;
      cmdLog.cmdPrm.sD.srcId      = srcId;
      cmdLog.cmdPrm.sD.number     = NULL;
      cmdLog.cmdPrm.sD.clirOvrd   = clirOvrd;
      cmdLog.cmdPrm.sD.cugCtrl    = cugCtrl;
      cmdLog.cmdPrm.sD.callType   = callType;
#ifdef SIM_TOOLKIT
      cmdLog.cmdPrm.sD.simCallCtrl= D_SIMCC_NOT_ACTIVE;
#endif /* SIM_TOOLKIT */

      rAT_PercentCLOG( &cmdLog );
#endif

      return( AT_EXCT );
    }
  }

#endif  /* of #ifdef FAX AND_DATA */

  if( cldPty EQ NULL )
  {
    TRACE_EVENT("ERROR: cldPty is NULL");

    if (callType EQ D_TOC_Voice)
      return(AT_CMPL);
    else
    {
      if (!cmh_set_delayed_call (cmhCC_Dial_delayed, &cmhCC_Dial_buffer))
        return AT_BUSY;

      cmhCC_Dial_buffer.srcId = srcId;

      TRACE_EVENT("delayed return requested: 100 ms");
        cmh_start_delayed_call (100);

      return(AT_EXCT);
    }
  }

/*
 *-------------------------------------------------------------------
 * determine call priority
 *-------------------------------------------------------------------
 */
  if (cmhMM_ChkIgnoreECC(cldPty->num))
  {
    prio = MNCC_PRIO_NORM_CALL;
    TRACE_EVENT("cmhCC_Dial(): ECC check is ignored");
  }
  else
  {
    TRACE_EVENT("cmhCC_Dial(): ECC check is coninued");
    prio = psaCC_phbSrchECC ( cldPty->num, TRUE );
  }

/*
 *-------------------------------------------------------------------
 * check fixed dialing phonebook if enabled
 *-------------------------------------------------------------------
 */
  if( prio EQ MNCC_PRIO_NORM_CALL  AND
      (simShrdPrm.crdFun EQ SIM_FDN_ENABLED OR
       simShrdPrm.crdFun EQ SIM_FDN_BDN_ENABLED) )
  {
    if( ksd_isFDNCheckSeq ( cldPty->num ) )
    {
      if(!psaCC_phbNtryFnd( FDN, cldPty ))
      {
        TRACE_EVENT ( "FDN check failed" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_FdnCheck );
        return( AT_FAIL );
      }
    }
  }

/*
 *-------------------------------------------------------------------
 * Add Number or Sequence to LDN phonebook
 * This has to be done prior keystrokes to allow adding some special
 * sequences for dialing purpose with prepaid SIMs when roaming (USSD callback)
 *-------------------------------------------------------------------
 */
  if (prio NEQ MNCC_PRIO_EMERG_CALL) /* only normal calls are added to the LDN PB */
  {
    if(ksd_isLDNWriteCheckSeq(cldPty->num)) /* check whether the string needs to be written to LDN?*/
    {
      /* A call table entry does not exist here yet */
      psaCC_phbAddNtry( LDN, NO_ENTRY, CT_MOC, cldPty );  /* add call to LDN PB */
    }
  }

/*
 *-------------------------------------------------------------------
 * check for a keystroke sequence
 *-------------------------------------------------------------------
 */

  if(prio NEQ MNCC_PRIO_EMERG_CALL)
  {
    retVal = cmhCC_chkKeySeq ( srcId,
                               cldPty,
                               &callType,
                               &clirOvrd,
                               CC_SIM_YES );

    if( retVal NEQ AT_CONT )
      return( retVal );
  }
  else if (strlen(cldPty->num) > 4)
  {
    /* decode clirOvrd in case of ECC
       since cmhCC_chkKeySeq is not aware of ECC */

/* Implements Measure#32: Row 89 & 90 */
    if ( !strncmp(cldPty->num,(char*)ksd_supp_clir_str,4) OR /* KSD_SUPPRESS_CLIR */
         !strncmp(cldPty->num,(char*)ksd_inv_clir_str,4) )   /* KSD_INVOKE_CLIR */
    {
      CHAR *p1, *p2;

      if (*cldPty->num EQ '*')
        clirOvrd = D_CLIR_OVRD_Supp;
      else
        clirOvrd = D_CLIR_OVRD_Invoc;
      /* and remove clirOvrd from dial num */
      for (p1=cldPty->num, p2=cldPty->num+4; /*lint -e720 */ *p1++ = *p2++; )
        ;
    }
  }


/*
 *-------------------------------------------------------------------
 * check for a short string sequence: should also be USSD (see 02.30 chptr 4.5.3.2)
 *-------------------------------------------------------------------
 */
  if( ( prio EQ MNCC_PRIO_NORM_CALL ) AND ( !ksd_isBCDForUSBand(cldPty->num) ) )
 {
   retVal = cmhCC_chkShortString (srcId, cId, cldPty);
   if (retVal NEQ AT_EXCT)
   {
     return (retVal);
   }
 }

/*
 *-------------------------------------------------------------------
 * check redialing
 *-------------------------------------------------------------------
 */
  /* Implements Measure 64 */
  cmhCC_CheckRedialTimer( FALSE );
/*
 *-------------------------------------------------------------------
 * continue dialing
 *-------------------------------------------------------------------
 */
  newId = psaCC_ctbNewEntry();

  if( newId EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTabFull );
    return( AT_FAIL );        /* call table full */
  }

  if( cId NEQ NO_ENTRY )
  {

  /*
   *-----------------------------------------------------------------
   * check if there is already a call on hold
   *-----------------------------------------------------------------
   */
    if( psaCC_ctbFindCall( OWN_SRC_INV, CS_HLD, NO_VLD_CT ) NEQ NO_ENTRY )
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_OneCallOnHold );
      psaCC_FreeCtbNtry (newId);
      return( AT_FAIL );
    }

  /*
   *-----------------------------------------------------------------
   * check to put active call on hold, if it is no data call and not
   * an emergency call
   *-----------------------------------------------------------------
   */
    if( psaCC_ctb(cId)->prio EQ MNCC_PRIO_NORM_CALL AND
        cmhCC_getcalltype(cId)  EQ VOICE_CALL )
    {
      if( pCCCmdPrm->mltyCncFlg NEQ 0 )
      {
        psaCC_FreeCtbNtry (newId);
        return( AT_BUSY );
      }
    }
    else
    {
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
      psaCC_FreeCtbNtry (newId);
      return( AT_FAIL );
    }
  }

/*
 *-------------------------------------------------------------------
 * setup call parameters
 *-------------------------------------------------------------------
 */
  cmhCC_chkDTMFDig ( cldPty->num, newId, dummy, TRUE );
  

  retVal = cmhCC_fillSetupPrm ( newId, srcId, cldPty, NULL, prio,
                                clirOvrd, cugCtrl, callType );
  if( retVal NEQ AT_CMPL  )
  {
    psaCC_FreeCtbNtry (newId);
    return( retVal );
  }

#ifdef TI_PS_FF_AT_P_CMD_RDLB
/*
 *-------------------------------------------------------------------
 * check number against black list entries
 *-------------------------------------------------------------------
 */
  if(rdlPrm.rdlMod EQ AUTOM_REPEAT_ON)
  {
    if(cmhCC_redialChkBlackl(newId) NEQ AT_CMPL)
    {
      psaCC_FreeCtbNtry (newId);
      return( AT_FAIL);
    }
  }
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
/*
 *-----------------------------------------------------------------
 * declare call table entry as used and the owner of the call
 *-----------------------------------------------------------------
 */
  psaCC_ctb(newId)->calType    = CT_MOC;
  psaCC_ctb(newId)->calOwn     = (T_OWN)srcId;
  psaCC_ctb(newId)->curCmd     = AT_CMD_D;
  psaCC_ctb(newId)->curSrc     = srcId;

/*
 *-------------------------------------------------------------------
 * check for call control by SIM toolkit
 *-------------------------------------------------------------------
 */
#ifdef SIM_TOOLKIT

  if ( prio NEQ MNCC_PRIO_EMERG_CALL ) /* don't send emergency calls to */
  {                               /* SIM toolkit                   */
    if ( !ksd_isFDNCheckSeq ( cldPty-> num ) )
      ;    /* bypass *#06# from CntrlBySIM */
    else
    {
      if( psaSIM_ChkSIMSrvSup( SRV_CalCntrl ) AND satShrdPrm.SIMCCParm.busy NEQ TRUE )
      {
        /*  get bearer capability parameter */ 
        ccShrdPrm.BC0_send_flag =  ccShrdPrm.ctb[newId]->BC[0].bearer_serv NEQ MNCC_BEARER_SERV_NOT_PRES   AND
                         ccShrdPrm.ctb[newId]->BC[0].bearer_serv NEQ MNCC_BEARER_SERV_SPEECH      AND
                         ccShrdPrm.ctb[newId]->BC[0].bearer_serv NEQ MNCC_BEARER_SERV_AUX_SPEECH;
        
        ccShrdPrm.BC1_send_flag =  ccShrdPrm.ctb[newId]->BC[1].bearer_serv NEQ MNCC_BEARER_SERV_NOT_PRES   AND
                         ccShrdPrm.ctb[newId]->BC[1].bearer_serv NEQ MNCC_BEARER_SERV_SPEECH      AND
                         ccShrdPrm.ctb[newId]->BC[1].bearer_serv NEQ MNCC_BEARER_SERV_AUX_SPEECH;
        if ( (callType EQ D_TOC_Data) AND ( ccShrdPrm.BC0_send_flag OR ccShrdPrm.BC1_send_flag) )
        {
          satShrdPrm.capParm.cId = newId;
          psaCC_BCapCode( BCRI_SAT, newId );
          return (AT_EXCT);
        }
        else
        {
          retVal = cmhSAT_CalCntrlBySIM( newId );
        }

        if( retVal NEQ AT_CMPL )
        {
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
          cmdLog.atCmd                = AT_CMD_D;
          cmdLog.cmdType              = CLOG_TYPE_Set;
          cmdLog.retCode              = AT_EXCT;
          cmdLog.cId                  = newId+1;
          cmdLog.sId                  = ACI_NumParmNotPresent;
          cmdLog.cmdPrm.sD.srcId      = srcId;
          cmdLog.cmdPrm.sD.number     = cldPty->num;
          cmdLog.cmdPrm.sD.clirOvrd   = clirOvrd;
          cmdLog.cmdPrm.sD.cugCtrl    = cugCtrl;
          cmdLog.cmdPrm.sD.callType   = callType;
          cmdLog.cmdPrm.sD.simCallCtrl= D_SIMCC_ACTIVE_CHECK;

          rAT_PercentCLOG( &cmdLog );
#endif
          return( retVal );
        }
      }
    }
  }

#endif


  if( cId NEQ NO_ENTRY )
  {
    /* put an active call on hold prior to set up the new call */
    CHLDaddInfo = CHLD_ADD_INFO_DIAL_CAL;
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActDial;

    cmhCC_HoldCall(cId, srcId, AT_CMD_D);

    /* flag newId to start the call once active call has been held */
    cmhCC_flagCall( newId, &(pCCCmdPrm->mltyCncFlg));
  }
  else
  {
    /* start a new call */
    cmhCC_flagCall( newId, &(pCCCmdPrm->mltyCncFlg));

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

/* log command */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_D;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.cId                  = newId+1;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sD.srcId      = srcId;
  cmdLog.cmdPrm.sD.number     = cldPty->num;
  cmdLog.cmdPrm.sD.clirOvrd   = clirOvrd;
  cmdLog.cmdPrm.sD.cugCtrl    = cugCtrl;
  cmdLog.cmdPrm.sD.callType   = callType;
#ifdef SIM_TOOLKIT
  cmdLog.cmdPrm.sD.simCallCtrl= D_SIMCC_NOT_ACTIVE;
#endif /* SIM_TOOLKIT */

  rAT_PercentCLOG( &cmdLog );

#endif

  return( AT_EXCT );
}

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

  PURPOSE : This is the functional counterpart to the H AT command
            which is responsible to terminate or modify a call.

            1. The function searches for an active call. If this
            call is modifiable, it will be modified and the function
            returns.
            2. Then the function searches for a call that is in the
            disconnect request state and indicates CCBS possibility,
            this call will be finally released.
            3. If enabled the next search looks for a pending SAT call.
            If such a call is found the call is rejected and the SIM card
            will be informed.
            4. The next step is to clear all calls of the call table
            exept a waiting call. The function returns if at least one
            call could be found.
            5. If no call was found, the function searches for a waiting
            call. If a waiting call was found, the call will be
            terminated declaring the user as busy.
            6. If none of the above situations match, the function
            returns with a fail.

*/

GLOBAL T_ACI_RETURN sAT_H ( T_ACI_CMD_SRC srcId )
{
  SHORT cId;                  /* holds call id */
  SHORT waitId = NO_ENTRY;    /* holds call waiting id */
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */
#if defined (GPRS) AND defined (DTI)
  T_ACI_RETURN  ret_value;
#endif  /* GPRS */

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif

  TRACE_FUNCTION ("sAT_H()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;


#if defined (GPRS) AND defined (DTI)
  /*  handle command for GPRS */
  if ( TRUE EQ cmhSM_sAT_H( srcId, &ret_value ) )
    return ret_value;
#endif  /* GPRS */

/*  prepare log command */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_H;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sH.srcId      = srcId;
#endif

#ifdef ACI /* for ATI only version */
  cmhMMI_handleAudioTone ( AT_CMD_H, RAT_OK, CPI_MSG_NotPresent );
#endif

/*
 *-------------------------------------------------------------------
 * find an active call and check call mode in case of
 * in-call modification
 *-------------------------------------------------------------------
 */
#if defined (FAX_AND_DATA) AND defined (DTI)
  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT );

  if( cId NEQ NO_ENTRY AND
      cmhCC_ChckInCallMdfy( cId, AT_CMD_H ) )
  {
    switch( cmhCC_getcalltype(cId) )
    {
      case( TRANS_CALL ):
        ccShrdPrm.datStat = DS_MDF_REQ;
        cmhTRA_Deactivate();

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
        cmdLog.cId = cId+1;
        rAT_PercentCLOG( &cmdLog );
#endif
        return( AT_EXCT );

      case( NON_TRANS_CALL ):
        ccShrdPrm.datStat = DS_MDF_REQ;
        cmhL2R_Deactivate();

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
        cmdLog.cId = cId+1;
        rAT_PercentCLOG( &cmdLog );
#endif
        return( AT_EXCT );

#ifdef FF_FAX
      case( FAX_CALL ):
        ccShrdPrm.datStat = DS_MDF_REQ;
        cmhT30_Deactivate ();

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
        cmdLog.cId = cId+1;
        rAT_PercentCLOG( &cmdLog );
#endif
        return( AT_EXCT );
#endif /* FF_FAX */
    }
  }
#endif /* FAX_AND_DATA */

  /* 
   * 3GPP standard 27007 
   * (+CVHU)
   *
   * FreeCalypso note: +CVHU support was not present in the TCS211 version
   * of ACI, but it appears in the version we got from the LoCosto source.
   * The following stanza is a new addition with this LoCosto version,
   * and it was broken for our sans-PSI configuration: the reference to
   * to psiShrdPrm only works when PSI is there, and it is a compilation
   * failure otherwise.  The conditional on FF_PSI and the #else version
   * have been added by Space Falcon; the correctness of the latter is
   * not yet known.
   */
#ifdef FF_PSI
  if( ccShrdPrm.cvhu EQ CVHU_DropDTR_ATH_IGNORED OR
    ((psiShrdPrm.dtr_clearcall EQ TRUE) AND 
     (ccShrdPrm.cvhu EQ CVHU_DropDTR_IGNORED)) )
  {
    psiShrdPrm.dtr_clearcall = FALSE;  
    return (AT_CMPL);
  }
#else
  if( ccShrdPrm.cvhu EQ CVHU_DropDTR_ATH_IGNORED )
    return (AT_CMPL);
#endif

/*
 *-------------------------------------------------------------------
 * check for a call with CCBS possible
 *-------------------------------------------------------------------
 */
  if( pCCCmdPrm -> mltyDscFlg NEQ 0 )
    return( AT_BUSY );

/*
 *-------------------------------------------------------------------
 * check for a redial call
 *-------------------------------------------------------------------
 */
  /* Implements Measure 80 */
  if (cmhCC_check_RedialCall(AT_CMD_H) EQ TRUE )
  {
    return( AT_CMPL );
  }

  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT_REQ, CT_MOC );

  if (cId EQ NO_ENTRY)
    cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_DSC_REQ, CT_MOC );    /* also search for calls in disconnect state */

  if( cId NEQ NO_ENTRY )
  {
    if( psaCC_ctb(cId)->CCBSstat EQ CCBSS_PSSBL )
    {
      pCCCmdPrm -> mltyDscFlg = 0;

      cmhCC_flagCall( cId, &(pCCCmdPrm -> mltyDscFlg));
      psaCC_ctb(cId)->nrmCs  = MNCC_CAUSE_CALL_CLEAR;
      psaCC_ctb(cId)->curCmd = AT_CMD_H;
      psaCC_ctb(cId)->curSrc = srcId;
      psaCC_ClearCall (cId);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
      cmdLog.cId = cId+1;
      rAT_PercentCLOG( &cmdLog );
#endif
      return( AT_EXCT );
    }
  }

/*
 *-------------------------------------------------------------------
 * check for a CCBS recall
 *-------------------------------------------------------------------
 */
  cId = psaCC_ctbFindCall( (T_OWN)CMD_SRC_NONE, CS_ACT_REQ, CT_NI_MOC );

  if( cId NEQ NO_ENTRY )
  {
    psaCC_ctb(cId)->nrmCs  = MNCC_CAUSE_CALL_REJECT;
    psaCC_ClearCall (cId);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    cmdLog.retCode = AT_CMPL;
    rAT_PercentCLOG( &cmdLog );
#endif

    psaCC_FreeCtbNtry (cId);
    return( AT_CMPL );
  }

/*
 *-------------------------------------------------------------------
 * check for a pending SAT call
 *-------------------------------------------------------------------
 */
#ifdef SIM_TOOLKIT
  if (cmhCC_check_pending_satCall() EQ TRUE )
  {
    return( AT_CMPL );
  }
#endif /* SIM_TOOLKIT */
 
/*
 *-------------------------------------------------------------------
 * clear all calls except a waiting call
 *-------------------------------------------------------------------
 */
  pCCCmdPrm -> mltyDscFlg = 0;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    cmhCC_ClearCall( cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_H, &waitId );
  }

  if( pCCCmdPrm -> mltyDscFlg )
  {
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    rAT_PercentCLOG( &cmdLog );
#endif
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * disconnect a waiting call with user determined user busy
 *-------------------------------------------------------------------
 */
  /* Implements Measure 164 */
  if ( waitId NEQ NO_ENTRY )
  {
    cmhCC_disconnect_waiting_call ( srcId, waitId, AT_CMD_H,
                                    &(pCCCmdPrm -> mltyDscFlg) );
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * nothing to act on
 *-------------------------------------------------------------------
 */
  return( AT_CMPL );
}

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

  PURPOSE : This is the functional counterpart to the +CHUP AT command
            which is responsible to terminate a call.

            1. The next step is to clear all calls of the call table
            exept a waiting call. The function returns if at least one
            call could be found.
            2. If no call was found, the function searches for a waiting
            call. If a waiting call was found, the call will be
            terminated declaring the user as busy.
            3. If none of the above situations match, the function
            returns with a fail.

*/

GLOBAL T_ACI_RETURN sAT_PlusCHUP ( T_ACI_CMD_SRC srcId )
{
  SHORT cId;                  /* holds call id */
  SHORT waitId = NO_ENTRY;    /* holds call waiting id */
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif
  TRACE_FUNCTION ("sAT_CHUP()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * prepare log command
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_CHUP;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sCHUP.srcId   = srcId;
#endif
/*
 *-------------------------------------------------------------------
 * check for a redial call
 *-------------------------------------------------------------------
 */
  /* Implements Measure 80 */
  if (cmhCC_check_RedialCall(AT_CMD_CHUP) EQ TRUE )
  {
    return( AT_CMPL );
  }

/*
 *-------------------------------------------------------------------
 * check for a pending SAT call
 *-------------------------------------------------------------------
 */
#ifdef SIM_TOOLKIT
  if (cmhCC_check_pending_satCall() EQ TRUE )
  {
    return( AT_CMPL );
  }
#endif /* SIM_TOOLKIT */
 
/*
 *-------------------------------------------------------------------
 * clear only active call
 *-------------------------------------------------------------------
 */
  if( pCCCmdPrm -> mltyDscFlg NEQ 0 )
    return( AT_BUSY );

  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT);

  if( cId NEQ NO_ENTRY )
  {
    cmhCC_ClearCall(cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHUP, &waitId );
  }

  if( pCCCmdPrm -> mltyDscFlg )
  {
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    rAT_PercentCLOG( &cmdLog );
#endif
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * disconnect a waiting call with user determined user busy
 *-------------------------------------------------------------------
 */
  /* Implements Measure 164 */
  if ( waitId NEQ NO_ENTRY )
  {
    cmhCC_disconnect_waiting_call ( srcId, waitId, AT_CMD_CHUP,
                                    &(pCCCmdPrm -> mltyDscFlg) );
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * nothing to act on
 *-------------------------------------------------------------------
 */
  return( AT_CMPL );
}

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

  PURPOSE : This is the functional counterpart to the A AT command
            which is responsible to accept an incoming call. The A
            command accepts an incoming call if no call is currently
            active. Otherwise if a call is in active state the A command
            starts to modify the active call. If the call mode set by
            the +CMOD command indicates a single call no modification
            takes place and the A command returns with a fail.

*/

GLOBAL T_ACI_RETURN sAT_A ( T_ACI_CMD_SRC srcId )
{
  SHORT cId;                /* holds call id */
  T_CC_CMD_PRM * pCCCmdPrm; /* points to CC command parameters */

#if defined (GPRS) AND defined (DTI)
  T_ACI_RETURN  ret_value;
#endif  /* GPRS */

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif

  TRACE_FUNCTION ("sAT_A()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * handle command for GPRS
 *-------------------------------------------------------------------
 */
#if defined (GPRS) AND defined (DTI)

  if ( TRUE EQ cmhSM_sAT_A( srcId, &ret_value ) )
    return ret_value;

#endif  /* GPRS */

/*
 *-------------------------------------------------------------------
 * prepare log command
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_A;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sA.srcId      = srcId;
#endif

/*
 *-------------------------------------------------------------------
 * check for an active call
 *-------------------------------------------------------------------
 */
#ifdef FAX_AND_DATA

  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT );

  if( cId NEQ NO_ENTRY )
  {

  /*
   *-----------------------------------------------------------------
   * check call mode to modify the call
   *-----------------------------------------------------------------
   */
    if( cmhCC_ChckInCallMdfy( cId, AT_CMD_A ) )
    {
      cmhCC_flagCall( cId, &(pCCCmdPrm->mltyCncFlg));
      psaCC_ctb(cId)->curCmd = AT_CMD_A;
      psaCC_ctb(cId)->curSrc = srcId;
      psaCC_ModifyCall(cId);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
      cmdLog.cId = cId+1;
      rAT_PercentCLOG( &cmdLog );
#endif
      return( AT_EXCT );
    }
  /*
   *----------------------------------------------------------------------------------
   * ATA can be used to answer the second SAT call when the first call is active
   *----------------------------------------------------------------------------------
   */
#ifdef SIM_TOOLKIT
    cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_REQ, NO_VLD_CT );
#ifdef FF_SAT_E
    if( cId EQ NO_ENTRY )
    {
      cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_CSD_REQ, NO_VLD_CT );
    }
#endif /* FF_SAT_E */
    if( cId EQ NO_ENTRY )
    {
      TRACE_FUNCTION ("Already a call is active !!!"); 
      return( AT_FAIL);
    }
#else
   /* Added Below Two lines to fix ACI-SPR-22325*/
   TRACE_FUNCTION ("Already a call is active !!!"); 
   return( AT_FAIL );
#endif
  }
#endif    /* of #ifdef FAX_AND_DATA */


/*
 *-------------------------------------------------------------------
 * check for an incoming call to accept
 *-------------------------------------------------------------------
 */
  if( pCCCmdPrm -> mltyCncFlg NEQ 0 )

    return( AT_BUSY );

  cId = psaCC_ctbFindCall( (T_OWN)CMD_SRC_NONE, CS_ACT_REQ, CT_MTC );

  if( cId NEQ NO_ENTRY )
  {
    /* accept the call */
    cmhCC_flagCall( cId, &(pCCCmdPrm->mltyCncFlg));

    cmhCC_AcceptCall(cId, srcId, AT_CMD_A);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    rAT_PercentCLOG( &cmdLog );
#endif
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * check for a CCBS recall condition
 *-------------------------------------------------------------------
 */
  cId = psaCC_ctbFindCall( (T_OWN)CMD_SRC_NONE, CS_ACT_REQ, CT_NI_MOC );

  if( cId NEQ NO_ENTRY )
  {
    /* accept the call */
    {
      cmhCC_flagCall( cId, &(pCCCmdPrm->mltyCncFlg));

      cmhCC_NewCall(cId, srcId, AT_CMD_A);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
      cmdLog.cId = cId+1;
      rAT_PercentCLOG( &cmdLog );
#endif
      return( AT_EXCT );
    }
  }

/*
 *-------------------------------------------------------------------
 * check for a pending SAT call
 *-------------------------------------------------------------------
 */
#ifdef SIM_TOOLKIT
  /* triggered by SETUP CALL command */
    cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_REQ, NO_VLD_CT );

#ifdef FF_SAT_E
  if( cId EQ NO_ENTRY )
    /* triggered by OPEN CHANNEL command */
    cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_CSD_REQ, NO_VLD_CT );
#endif /* FF_SAT_E */

  if( cId NEQ NO_ENTRY )
  {
    if( psaCC_ctb(cId)->SATinv )
    {
      if( !cmhSAT_UserAcptCall( cId, (UBYTE)srcId ) )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CmdDetailsSAT );
        return( AT_FAIL );
      }
    }
    else
    {
      cmhCC_flagCall( cId, &(pCCCmdPrm->mltyCncFlg));
      cmhCC_NewCall(cId, srcId, AT_CMD_A);
    }

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    rAT_PercentCLOG( &cmdLog );
#endif

    return( AT_EXCT );
  }
#if defined (GPRS) AND defined (FF_SAT_E) AND defined (DTI)
  else
  {
    /* check for a pending SAT GPRS channel */
    if( cmhSAT_OpChnGPRSPend(PDP_CONTEXT_CID_INVALID, OPCH_WAIT_CNF))
    {
      if( !cmhSAT_UserAcptCntxt( (UBYTE)srcId ) )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CmdDetailsSAT );
        return( AT_FAIL );
      }
      return( AT_EXCT );
    }
  }
#endif  /* GPRS AND FF_SAT_E */
#endif  /* SIM_TOOLKIT */


/*
 *-------------------------------------------------------------------
 * call not found
 *-------------------------------------------------------------------
 */
  ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallNotFound );
  return( AT_FAIL );
}

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

  PURPOSE : This is the functional counterpart to the +CLIR AT command
            which is responsible to enable or disable the presentation
            of the own calling id for mobile originated calls.

*/

GLOBAL T_ACI_RETURN sAT_PlusCLIR ( T_ACI_CMD_SRC srcId,
                                   T_ACI_CLIR_MOD mode )
{
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */

  TRACE_FUNCTION ("sAT_PlusCLIR()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * process the mode parameter
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    case( CLIR_MOD_NotPresent ):
      break;

    case( CLIR_MOD_Subscript ):
    case( CLIR_MOD_Invoc     ):
    case( CLIR_MOD_Supp      ):
      pCCCmdPrm -> CLIRmode = mode;
      break;

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

  return( AT_CMPL );
}

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

  PURPOSE : This is the functional counterpart to the +CMOD AT command
            which is responsible to set the mode for mobile originated
            calls.

*/

GLOBAL T_ACI_RETURN sAT_PlusCMOD ( T_ACI_CMD_SRC srcId,
                                   T_ACI_CMOD_MOD mode )
{
  TRACE_FUNCTION ("sAT_PlusCMOD()");

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

  /* process the mode parameter */
  switch( mode )
  {
    case( CMOD_MOD_NotPresent ):
      break;

    case( CMOD_MOD_Single       ):

#ifdef FAX_AND_DATA
    case( CMOD_MOD_VoiceFax     ):
    case( CMOD_MOD_VoiceDat     ):
    case( CMOD_MOD_VoiceFlwdDat ):
#endif    /* of #ifdef FAX_AND_DATA */

      ccShrdPrm.CMODmode = mode;
      break;

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

  return( AT_CMPL );
}

#ifdef FAX_AND_DATA
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                  |
| STATE   : code                  ROUTINE : sAT_PlusCBST             |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the +CBST AT command
            which is responsible to set the bearer service parameters
            for following mobile originated calls.

*/

GLOBAL T_ACI_RETURN sAT_PlusCBST ( T_ACI_CMD_SRC srcId,
                                   T_ACI_BS_SPEED speed,
                                   T_ACI_CBST_NAM name,
                                   T_ACI_CBST_CE ce)
{
  TRACE_FUNCTION ("sAT_PlusCBST()");

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

  /* process the speed parameter */
  switch( speed )
  {
    case( BS_SPEED_NotPresent ):
      speed = ccShrdPrm.CBSTspeed;
      break;

    case( BS_SPEED_AUTO         ):
    case( BS_SPEED_300_V21      ):
    case( BS_SPEED_1200_V22     ):
    case( BS_SPEED_1200_75_V23  ):
    case( BS_SPEED_2400_V22bis  ):
    case( BS_SPEED_2400_V26ter  ):
    case( BS_SPEED_4800_V32     ):
    case( BS_SPEED_9600_V32     ):
    case( BS_SPEED_9600_V34     ):
    case( BS_SPEED_14400_V34    ):
/*  case( BS_SPEED_1200_V120    ): This layer 1 protocol is not supported
    case( BS_SPEED_2400_V120    ):
    case( BS_SPEED_4800_V120    ):
    case( BS_SPEED_9600_V120    ):
    case( BS_SPEED_14400_V120   ): */
    case( BS_SPEED_300_V110     ):
    case( BS_SPEED_1200_V110    ):
    case( BS_SPEED_2400_V110    ):
    case( BS_SPEED_4800_V110    ):
    case( BS_SPEED_9600_V110    ):
    case( BS_SPEED_14400_V110   ):
      break;

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

  /* process the name parameter */
  switch( name )
  {
    case( CBST_NAM_NotPresent ):
      name = ccShrdPrm.CBSTname;
      break;

    case( CBST_NAM_Asynch ):
    case( CBST_NAM_Synch  ):
      break;

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

  /* process the ce parameter */
  switch( ce )
  {
    case( CBST_CE_NotPresent ):
      ce = ccShrdPrm.CBSTce;
      break;

    case( CBST_CE_Transparent      ):
    case( CBST_CE_NonTransparent   ):
    case( CBST_CE_BothTransPref    ):
    case( CBST_CE_BothNonTransPref ):
      break;

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

  /* assign the parameters */
  ccShrdPrm.CBSTspeed = speed;
  ccShrdPrm.CBSTname  = name;
  ccShrdPrm.CBSTce    = ce;

  /* update CC setting for MTC */
  psaCC_Config();
  return( AT_CMPL );

}
#endif /* FAX_AND_DATA */

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

  PURPOSE : This is the functional counterpart to the +CSTA AT command
            which is responsible to set the type of address for further
            dialing commands.

*/

GLOBAL T_ACI_RETURN sAT_PlusCSTA ( T_ACI_CMD_SRC srcId,
                                   T_ACI_TOA * toa )
{
  T_CC_CMD_PRM * pCCCmdPrm; /* points to CC command parameters */

  TRACE_FUNCTION ("sAT_PlusCSTA()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * process the toa parameter
 *-------------------------------------------------------------------
 */
  if( ! toa ) return( AT_CMPL );

  switch( toa -> ton )
  {
    case( TON_Unknown       ):
    case( TON_International ):
    case( TON_National      ):
    case( TON_NetSpecific   ):
    case( TON_DedAccess     ):
      break;

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

  switch( toa -> npi )
  {
    case( NPI_Unknown       ):
    case( NPI_IsdnTelephony ):
    case( NPI_Data          ):
    case( NPI_Telex         ):
    case( NPI_National      ):
    case( NPI_Private       ):
      break;

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

  pCCCmdPrm -> CSTAtoa.ton = toa -> ton;
  pCCCmdPrm -> CSTAtoa.npi = toa -> npi;
  pCCCmdPrm -> CSTAdef     = FALSE;

  return( AT_CMPL );
}


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

  PURPOSE : This refers to a service that causes an incoming alerting
            call to be forwarded to a specified number. Action command
            does this.

*/

GLOBAL T_ACI_RETURN sAT_PlusCTFR  ( T_ACI_CMD_SRC    srcId,
                                    CHAR            *number,
                                    T_ACI_TOA       *type,
                                    CHAR            *subaddr,
                                    T_ACI_TOS       *satype)
{
  T_CC_CMD_PRM * pCCCmdPrm; /* points to CC command parameters */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif /* #if defined SMI OR defined MFW OR defined FF_MMI_RIV */
  SHORT cId;                /* holds call id */
  SHORT dscId;              /* holds call disconnect id */
  UBYTE idx;                /* holds index value */

  TRACE_FUNCTION ("sAT_PlusCTFR()");

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

  /*
   * Check that number contains a valid dial string.
   * A dial string is valid if it contains at least one valid dial
   * character, garbage within the dial string is ignored (also spaces).
   */
  if (strpbrk (number, "0123456789*#AaBbCc") EQ NULL)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  /*
   *-------------------------------------------------------------------
   * prepare log command
   *-------------------------------------------------------------------
   */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_CTFR;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cId                  = NOT_PRESENT_8BIT;
  cmdLog.cmdPrm.sCTFR.srcId   = srcId;
  cmdLog.cmdPrm.sCTFR.number  = number;
  cmdLog.cmdPrm.sCTFR.type    = type;
  cmdLog.cmdPrm.sCTFR.subaddr = subaddr;
  cmdLog.cmdPrm.sCTFR.satype  = satype;
#endif /* #if defined SMI OR defined MFW OR defined FF_MMI_RIV */

  /*
   *-------------------------------------------------------------------
   * find the call for which Call Deflection shall be invoked
   *-------------------------------------------------------------------
   */
  dscId = -1;

  for (cId = 0; cId < MAX_CALL_NR; cId++)
  {
    if ((ccShrdPrm.ctb[cId] NEQ NULL) AND
        (psaCC_ctb(cId)->calStat    EQ CS_ACT_REQ) AND
        (psaCC_ctb(cId)->calType    EQ CT_MTC))
    {
      dscId = cId;
      break;
    }
  }

  if ((dscId >= 0) AND
      (psaCC_ctb(dscId)->curCmd NEQ AT_CMD_NONE))
  {
    return( AT_BUSY );
  }

  /*
   * There is no check here whether CD is applicable for the specific
   * telecommunication service (22.004 Normative Annex A), as CD is
   * applicable for all CC telecommunication services.
   * GSM 07.07 says CD was only applicable for teleservice 11, but this
   * seems to be wrong.
   */

  /*
   *-------------------------------------------------------------------
   * Clear the incoming call with facility invoke component for CD
   *-------------------------------------------------------------------
   */
  /*lint -e{661} cId causes out of bounds access, it does not! */
  if( dscId >= 0 ) /* Implies cId also >= 0 */
  {
    cmhCC_flagCall( dscId, &(pCCCmdPrm -> mltyDscFlg));
    psaCC_ctb(cId)->nrmCs    = MNCC_CAUSE_CALL_CLEAR;
    psaCC_ctb(cId)->curCmd   = AT_CMD_CTFR;
    psaCC_ctb(cId)->curSrc   = srcId;

#ifdef FF_ATI
    io_setRngInd (IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for (idx = 0; idx < CMD_SRC_MAX; idx++)
    {
      R_AT (RAT_CRING_OFF, (T_ACI_CMD_SRC)idx)(dscId + 1);
    }

    CCD_START;
    {
      psaCC_asmCDReq (number, type, subaddr, satype);

      psaCC_asmComponent (dscId);

      psaCC_ClearCall (dscId);
    }
    CCD_END;

    psaCC_ctb(cId)->CDStat   = CD_Requested;

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = dscId + 1;
    rAT_PercentCLOG( &cmdLog );
#endif /* #if defined SMI OR defined MFW OR defined FF_MMI_RIV */

    return( AT_EXCT );
  }

  /*
   * No call with matching criteria has been found in the call table.
   */
  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
  return AT_FAIL;
}

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

  PURPOSE : find waiting held calls

*/

LOCAL T_ACI_RETURN find_waiting_held_call(SHORT *cwaId,
                                          SHORT *hldId,
                                          SHORT *rclId)
{
  SHORT cId;

  /* reinitialize */
  *cwaId = -1;
  *hldId = -1;
  *rclId = -1;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL)
    {
      if( psaCC_ctb(cId)->calStat  EQ CS_ACT_REQ     AND
          psaCC_ctb(cId)->calOwn   EQ ((T_OWN)CMD_SRC_NONE)   AND
          psaCC_ctb(cId)->calType  EQ CT_MTC         )
      {
        *cwaId = cId;
      }

      if( psaCC_ctb(cId)->calStat EQ CS_HLD )
      {
        if(*hldId EQ -1)
        {
          /* take only first found call on hold (ex: in case of multiparty) */
          *hldId = cId;
        }
      }

      if( psaCC_ctb(cId)->calStat  EQ CS_ACT_REQ     AND
          psaCC_ctb(cId)->calOwn   EQ ((T_OWN)CMD_SRC_NONE)   AND
          psaCC_ctb(cId)->calType  EQ CT_NI_MOC      )
      {
        *rclId = cId;
      }
    }
  }

  if((*cwaId >= 0 AND psaCC_ctb(*cwaId)->curCmd NEQ AT_CMD_NONE) OR
     (*hldId >= 0 AND psaCC_ctb(*hldId)->curCmd NEQ AT_CMD_NONE) OR
     (*rclId >= 0 AND psaCC_ctb(*rclId)->curCmd NEQ AT_CMD_NONE) )
  {
    return( AT_BUSY );
  }
  return(AT_CMPL);
}

/* SEND LOG info to MFW */
LOCAL void chld_ratlog( T_ACI_CMD_SRC  srcId,
                        T_ACI_CHLD_MOD mode,
                        CHAR           *call,
                        T_ACI_CHLD_ACT act,
                        SHORT          cId,
                        T_ACI_RETURN   acireturn )
{
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */

  /* prepare log command */
  cmdLog.atCmd                = AT_CMD_CHLD;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sCHLD.srcId   = srcId;
  cmdLog.cmdPrm.sCHLD.mode    = mode;
  cmdLog.cmdPrm.sCHLD.call    = call;

  cmdLog.cmdPrm.sCHLD.act = act;
  cmdLog.cId              = cId+1;
  cmdLog.retCode          = acireturn;


  rAT_PercentCLOG( &cmdLog );
#endif  /* SMI OR defined MFW */
}

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

  PURPOSE : ???
*/
LOCAL T_ACI_RETURN chld_RelHldOrUdub(T_ACI_CMD_SRC srcId)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        cId;
  UBYTE        idx;        /* holds index value */
  SHORT        dscId;      /* holds call disconnect id */

  TRACE_FUNCTION("chld_RelHldOrUdub");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *---------------------------------------------------------------
 * clear a waiting call
 *---------------------------------------------------------------
 */
  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  cId = psaCC_ctbFindCall( (T_OWN)CMD_SRC_NONE, CS_ACT_REQ, CT_MTC );

  if( cId >= 0 )
  {
    if( psaCC_ctb(cId)->curCmd NEQ AT_CMD_NONE )
      return( AT_BUSY );

    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelHldOrUdub;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    cmhCC_ClearCall(cId, MNCC_CAUSE_USER_BUSY, srcId, AT_CMD_CHLD, NULL);

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm -> CHLDmode, NULL, CHLD_ACT_Release, cId, AT_EXCT );

#ifdef FF_ATI
    io_setRngInd (IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)idx )( cId+1 );
    }

    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * clear a CCBS recall
 *---------------------------------------------------------------
 */
  cId = psaCC_ctbFindCall( (T_OWN)CMD_SRC_NONE, CS_ACT_REQ, CT_NI_MOC );

  if( cId >= 0 )
  {
    if( psaCC_ctb(cId)->curCmd NEQ AT_CMD_NONE )

      return( AT_BUSY );

    psaCC_ctb(cId)->nrmCs  = MNCC_CAUSE_USER_BUSY;

    psaCC_ClearCall (cId);

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm -> CHLDmode, NULL, CHLD_ACT_Release, cId, AT_CMPL );

    psaCC_FreeCtbNtry (cId);
    return( AT_CMPL );
  }

/*
 *---------------------------------------------------------------
 * or clear all held calls
 *---------------------------------------------------------------
 */
  dscId = -1;
  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL AND
        psaCC_ctb(cId)->calStat    EQ CS_HLD AND
        psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE)
    {
      cmhCC_ClearCall( cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL);
      dscId = cId;
    }
  }

  if( ! pCCCmdPrm -> mltyDscFlg )
  {
    return( AT_BUSY );
  }
  else if (dscId >= 0)
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelHldOrUdub;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Release, dscId, AT_EXCT );
    return( AT_EXCT );
  }
  else
  {
    return( AT_FAIL );
  }
}

/*-----------------------------------------------------------------
 * release all active calls, and accept held or waiting call
 *-----------------------------------------------------------------*/
LOCAL T_ACI_RETURN chld_RelActAndAcpt(T_ACI_CMD_SRC srcId)
{
  SHORT        cwaId;      /* holds call waiting id */
  SHORT        hldId;      /* holds call hold id */
  SHORT        rclId;      /* holds recall id */
  SHORT        dscId = -1; /* will be set if a call is disconnected (with its cId) */
  SHORT        cId;
  T_ACI_RETURN ret;
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */

  TRACE_FUNCTION("chld_RelActAndAcpt");

  /* find the waiting or held call */
  ret = find_waiting_held_call(&cwaId, &hldId, &rclId);

  TRACE_EVENT_P1("cwaId = %d", cwaId);
  if(ret EQ AT_BUSY)
    return(AT_BUSY);

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *---------------------------------------------------------------
 * clear all active calls
 *---------------------------------------------------------------
 */
  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL AND
        psaCC_ctb(cId)->calStat    EQ CS_ACT     AND
        psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE)
    {
      psaCC_StopDTMF (cId); /* HM 27.07.00 */
      dscId = cId;

      cmhCC_ClearCall( cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL );
    }
  }

/*
 *---------------------------------------------------------------
 * accept the waiting call
 *---------------------------------------------------------------
 */
  if( cwaId >= 0 )
  {
    cmhCC_flagCall( cwaId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelActAndAcpt;

    if( dscId NEQ -1 )
    {
      CHLDaddInfo = CHLD_ADD_INFO_ACC_CAL;
    }
    else
    {
      cmhCC_AcceptCall(cwaId, srcId, AT_CMD_CHLD);
    }

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Accept, cwaId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * accept the CCBS recall
 *---------------------------------------------------------------
 */
  if( rclId >= 0 )
  {
    cmhCC_flagCall( rclId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelActAndAcpt;

    /*
     * The MSC in GSM 04.93, figure 4.3.2 says the SETUP for the CCBS
     * call is sent immediately after the DISCONNECT for the existing
     * call was sent into the network, they do not wait for a RELEASE
     * from the network. This seems to be different for the call waiting
     * case, compare this with the MSC in GSM 11.10 clause 31.3.1.2.
     */
    cmhCC_NewCall(rclId, srcId, AT_CMD_D);

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Accept, rclId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * retrieve the held call
 *---------------------------------------------------------------
 */
  if( hldId >= 0 )
  {
    cmhCC_flagCall( hldId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelActAndAcpt;

    if( dscId NEQ -1 )
    {
      CHLDaddInfo = CHLD_ADD_INFO_RTV_CAL;
    }
    else
    {
      cmhCC_RetrieveCall(hldId, srcId);
    }

    /* inform MFW */
    chld_ratlog( srcId,
                 pCCCmdPrm->CHLDmode,
                 NULL,
                 (psaCC_ctb(hldId)->mptyStat EQ CS_ACT)? CHLD_ACT_RetrieveMpty:CHLD_ACT_Retrieve,
                 hldId,
                 AT_EXCT );

    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * at least one call was disconnected
 *---------------------------------------------------------------
 */
  if( dscId NEQ -1 )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelActAndAcpt;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Release, dscId, AT_EXCT );
    return( AT_EXCT );
  }
  return (AT_FAIL);
}


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

  PURPOSE : release a specific active call
*/
LOCAL T_ACI_RETURN chld_RelActSpec(T_ACI_CMD_SRC srcId, CHAR *call)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        spcId;      /* holds specified call id */

  T_ACI_RETURN retCode; 
  
  TRACE_FUNCTION("chld_RelActSpec");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;
  /* Implements Measure 117 */
  retCode = chld_Rel_MultipartySpec( srcId, &spcId,
                                     CHLD_MOD_RelActSpec, call );
  if ( retCode NEQ AT_CMPL )
  {
    return retCode;
  }
/*
 *---------------------------------------------------------------
 * clear the specific active call if possible
 *---------------------------------------------------------------
 */
  if (ccShrdPrm.ctb[spcId] EQ NULL OR psaCC_ctb(spcId)->calStat NEQ CS_ACT)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );        /* specific call does not match condition */
  }

  cmhCC_ClearCall ( spcId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL );

  pCCCmdPrm -> CHLDmode = CHLD_MOD_RelActSpec;
  CHLDaddInfo           = NO_CHLD_ADD_INFO;

  /* inform MFW */
  chld_ratlog( srcId, pCCCmdPrm->CHLDmode, call, CHLD_ACT_Release, spcId, AT_EXCT );
  return( AT_EXCT );
}

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

  PURPOSE : release a specific  call
*/
LOCAL T_ACI_RETURN chld_RelAnySpec(T_ACI_CMD_SRC srcId, CHAR *call)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        spcId;      /* holds specified call id */
  SHORT        waitId = NO_ENTRY; /* holds call waiting id */
  UBYTE        idx    = 0; /* temporary counter */

  T_ACI_RETURN retCode; 

  TRACE_FUNCTION("chld_RelAnySpec");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;
  /* Implements Measure 117 */
  retCode = chld_Rel_MultipartySpec( srcId, &spcId,
                                     CHLD_MOD_RelAnySpec, call );
  if ( retCode NEQ AT_CMPL )
  {
    return retCode;
  }
/*
 *---------------------------------------------------------------
 * clear the specific call if possible
 *---------------------------------------------------------------
 */
  if (ccShrdPrm.ctb[spcId] EQ NULL)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );        /* specific call does not match condition */
  }

  cmhCC_ClearCall ( spcId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, &waitId );

  /* The call that shall be released is a waiting call (stop ringing) */
  if( waitId NEQ NO_ENTRY )
  {
    cmhCC_flagCall( waitId, &(pCCCmdPrm -> mltyDscFlg));
    psaCC_ctb(waitId)->nrmCs  = MNCC_CAUSE_USER_BUSY;
    psaCC_ctb(waitId)->curCmd = AT_CMD_CHLD;
    psaCC_ctb(waitId)->curSrc = srcId;
    psaCC_ClearCall (waitId);
    
#ifdef AT_INTERPRETER
    io_setRngInd (IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
    for( idx = 0; idx < CMD_SRC_MAX; idx++ )
    {
      R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)idx )( waitId+1 );
    }
  }

  pCCCmdPrm->CHLDmode   = CHLD_MOD_RelAnySpec;
  CHLDaddInfo           = NO_CHLD_ADD_INFO;

  /* inform MFW */
  chld_ratlog( srcId, pCCCmdPrm->CHLDmode, call, CHLD_ACT_Release, spcId, AT_EXCT );
  return( AT_EXCT );
}


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

  PURPOSE : place all active calls on hold, and accept held or waiting
            call
*/
LOCAL T_ACI_RETURN chld_HldActAndAcpt(T_ACI_CMD_SRC srcId)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        cId;                /* holds call id */
  T_ACI_RETURN ret;
  SHORT        cwaId;              /* holds call waiting id */
  SHORT        hldId;              /* holds call hold id */
  SHORT        rclId;              /* holds recall id */
  BOOL         hldCalFlg  = FALSE; /* flags a held call */
  BOOL         mptyHldFlg = FALSE; /* flags a multiparty held call */
  T_ACI_CHLD_ACT chldact;          /* contains the type of CHLD activity when informing MFW */
  TRACE_FUNCTION("chld_HldActAndAcpt");

  /* find the waiting or held call */
  ret = find_waiting_held_call(&cwaId, &hldId, &rclId);

  if(ret EQ AT_BUSY)
    return(AT_BUSY);

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

//Spec 3GPP TS 22.083 Sec 1.6.83.2 which says - Although the call is offered to the subscriber, she cannot accept the call as long as she has one active call and one call on hold.
#if 0
  if( cwaId >=0 AND hldId >=0 )
  {
    /* check for Active Call if already Held Call and Waiting Call */
    for( cId = 0; cId < MAX_CALL_NR; cId++ )
    {
      if (ccShrdPrm.ctb[cId] NEQ NULL AND
          psaCC_ctb(cId)->calStat    EQ CS_ACT AND
          psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE )
      {
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_OneCallOnHold );
        return( AT_FAIL );    /* only one call could be on hold,
                                 no chance for the waiting call */
      }
    }
  }
#endif
/*
 *---------------------------------------------------------------
 * put all active calls on hold
 *---------------------------------------------------------------
 */
  /* Implements Measure 181 and 182 */
  if ( chld_HoldActiveCalls( srcId, &mptyHldFlg, &hldCalFlg, &cId ) EQ FALSE )
  {
    return( AT_FAIL ); /* no data calls supported */
  }  

/*
 *-------------------------------------------------------------------------
 * retrieve the held call first, if there is a active call and a hold call
 *-------------------------------------------------------------------------
 */
  if( hldCalFlg AND hldId >= 0 )
  {
    cmhCC_flagCall( hldId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;

    cmhCC_RetrieveCall(hldId, srcId);

    /* inform MFW */
    if( hldCalFlg )
    {
      chldact = (mptyHldFlg)? CHLD_ACT_SwapMpty:CHLD_ACT_Swap;
    }
    else
    {
      chldact = (psaCC_ctb(hldId)->mptyStat EQ CS_ACT)? CHLD_ACT_RetrieveMpty :CHLD_ACT_Retrieve;
    }
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, chldact, hldId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * accept the waiting call
 *---------------------------------------------------------------
 */
  if( cwaId >= 0 )
  {
    cmhCC_flagCall( cwaId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;

    if( hldCalFlg )
    {
      CHLDaddInfo = CHLD_ADD_INFO_ACC_CAL;
    }
    else
    {
      cmhCC_AcceptCall(cwaId, srcId, AT_CMD_CHLD);
    }

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Accept, cwaId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * accept the CCBS recall
 *---------------------------------------------------------------
 */
  if( rclId >= 0 )
  {
    cmhCC_flagCall( rclId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;

    if( hldCalFlg )
    {
      CHLDaddInfo = CHLD_ADD_INFO_DIAL_CAL;
    }
    else
    {
      cmhCC_NewCall(rclId, srcId, AT_CMD_CHLD);
    }
    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_Accept, rclId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * retrieve the held call
 *---------------------------------------------------------------
 */
  if( hldId >= 0 )
  {
    cmhCC_flagCall( hldId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;

    cmhCC_RetrieveCall(hldId, srcId);

    /* inform MFW */
    if( hldCalFlg )
    {
      chldact = (mptyHldFlg)? CHLD_ACT_SwapMpty:CHLD_ACT_Swap;
    }
    else
    {
      chldact = (psaCC_ctb(hldId)->mptyStat EQ CS_ACT)? CHLD_ACT_RetrieveMpty :CHLD_ACT_Retrieve;
    }
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, chldact, hldId, AT_EXCT );
    return( AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * at least one call was put on hold
 *---------------------------------------------------------------
 */
  if( hldCalFlg )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode,
                 NULL,
                 (mptyHldFlg)? CHLD_ACT_HoldMpty:CHLD_ACT_Hold,
                 cId, AT_EXCT );
    return( AT_EXCT );
  }
  return( AT_FAIL );
}

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

  PURPOSE : put all active calls on hold except the specified call
*/
LOCAL T_ACI_RETURN chld_HldActExc(T_ACI_CMD_SRC srcId, CHAR *call)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        spcId;      /* holds specified call id */
  SHORT        cId;        /* holds call id */
  BOOL         hldCalFlg  = FALSE; /* flags a held call */
  BOOL         mptyHldFlg = FALSE; /* flags a multiparty held call */
  T_ACI_CHLD_ACT chld_act;

  TRACE_FUNCTION("chld_HldActExc");

  if( call EQ NULL )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );  /* no call specified */
  }

  spcId = atoi( call );

  if( spcId EQ 0 OR spcId > MAX_CALL_NR )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

  spcId--;                        /* adapt to call table index */

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  /*
   *-------------------------------------------------------------
   * if specified call is active and no multiparty
   *-------------------------------------------------------------
   */
    /* no action needed */

  /*
   *-------------------------------------------------------------
   * if specified call is active and member of multiparty
   *-------------------------------------------------------------
   */
  if (ccShrdPrm.ctb[spcId] NEQ NULL AND
      psaCC_ctb(spcId)->calStat    EQ CS_ACT AND
      psaCC_ctb(spcId)->mptyStat   EQ CS_ACT AND
      psaCC_ctb(spcId)->curCmd     EQ AT_CMD_NONE)
  {
    /* If this is a multiparty with only one call left then we must not split! */
    if (psaCC_CountMPTY() > 1)
    {
      cmhCC_flagCall( spcId, &(pCCCmdPrm -> mltyCncFlg));

      psaCC_ctb(spcId)->curCmd = AT_CMD_CHLD;
      psaCC_ctb(spcId)->curSrc = srcId;

      psaCC_SplitMPTY(spcId);

      chld_act = CHLD_ACT_SplitMpty;
    }
    else
    {
      /* call is already active, so command has no effect */
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Unknown );
      return( AT_FAIL );
    }
  }

  /*
   *-------------------------------------------------------------
   * if specified call is on hold and no multiparty
   *-------------------------------------------------------------
   */
  else if (ccShrdPrm.ctb[spcId] NEQ NULL AND
           psaCC_ctb(spcId)->calStat    EQ CS_HLD AND
           psaCC_ctb(spcId)->mptyStat   EQ CS_IDL AND
           psaCC_ctb(spcId)->curCmd     EQ AT_CMD_NONE)
  {
    for( cId = 0; cId < MAX_CALL_NR; cId++ )
    {
      if (ccShrdPrm.ctb[cId] NEQ NULL AND
          psaCC_ctb(cId)->calStat    EQ CS_ACT AND
          psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE)
      {
        if( cmhCC_getcalltype(cId) NEQ VOICE_CALL )
        {
          pCCCmdPrm -> mltyCncFlg = 0;
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
          return( AT_FAIL );    /* no data calls supported */
        }

        hldCalFlg = TRUE;
        if( psaCC_ctb(cId)->mptyStat EQ CS_ACT )
        {
          mptyHldFlg = TRUE;
        }
        cmhCC_HoldCall(cId, srcId, AT_CMD_CHLD);
      }
    }

    cmhCC_flagCall( spcId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActExc;

    cmhCC_RetrieveCall(spcId, srcId);

    if( hldCalFlg )
    {
      chld_act = (mptyHldFlg)?
                       CHLD_ACT_SwapMpty:CHLD_ACT_Swap;
    }
    else
      chld_act = (mptyHldFlg)?
                       CHLD_ACT_RetrieveMpty:CHLD_ACT_Retrieve;
  }

  /*
   *-------------------------------------------------------------
   * if specified call is on hold and member of multiparty
   *-------------------------------------------------------------
   */
  else if (ccShrdPrm.ctb[spcId] NEQ NULL AND
           psaCC_ctb(spcId)->calStat    EQ CS_HLD AND
           psaCC_ctb(spcId)->mptyStat   EQ CS_ACT AND
           psaCC_ctb(spcId)->curCmd     EQ AT_CMD_NONE)
  {
    for( cId = 0; cId < MAX_CALL_NR; cId++ )
    {
      if (ccShrdPrm.ctb[cId] NEQ NULL AND
          psaCC_ctb(cId)->calStat    EQ CS_ACT AND
          psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE)
      {
        if( cmhCC_getcalltype(cId) NEQ VOICE_CALL )
        {
          pCCCmdPrm -> mltyCncFlg = 0;
          ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
          return( AT_FAIL );    /* no data calls supported */
        }

        hldCalFlg = TRUE;

        cmhCC_HoldCall(cId, srcId, AT_CMD_CHLD);
      }
    }

    cmhCC_flagCall( spcId, &(pCCCmdPrm -> mltyCncFlg));
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActExc;

    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    psaCC_ctb(spcId)->curCmd = AT_CMD_CHLD;
    psaCC_ctb(spcId)->curSrc = srcId;

    /* If this is a multiparty with only one call left then we must not split! */
    if (psaCC_CountMPTY() > 1)
    {
      psaCC_SplitMPTY(spcId);
      chld_act = CHLD_ACT_SplitMpty;
    }
    else
    {
      cmhCC_RetrieveCall(spcId, srcId);
      chld_act = CHLD_ACT_Retrieve;
    }
  }

  /*
   *-------------------------------------------------------------
   * if other command is running on specified call
   *-------------------------------------------------------------
   */
  else if (ccShrdPrm.ctb[spcId] NEQ NULL AND
           psaCC_ctb(spcId)->curCmd NEQ AT_CMD_NONE)
  {
    return( AT_BUSY );
  }

  /*
   *-------------------------------------------------------------
   * unknown condition
   *-------------------------------------------------------------
   */
  else
  {
    TRACE_ERROR ("Unknown condition");
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Unknown );
    return( AT_FAIL );
  }


  /*
   *-------------------------------------------------------------
   * send return code
   *-------------------------------------------------------------
   */
  if( pCCCmdPrm -> mltyCncFlg NEQ 0 )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActExc;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, call, chld_act, spcId, AT_EXCT );
    return( AT_EXCT );
  }
  else
  {
    return( AT_CMPL );
  }
}

/*-----------------------------------------------------------------
 * add a held call to the conversation
 *-----------------------------------------------------------------*/
LOCAL T_ACI_RETURN chld_AddHld(T_ACI_CMD_SRC srcId)
{
  SHORT        actId;              /* holds call active id */
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */

  TRACE_FUNCTION("chld_AddHld( )");

  /* search a held call */
  if( psaCC_ctbFindCall( OWN_SRC_INV, CS_HLD, NO_VLD_CT ) EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  actId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT );

  if( actId EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  cmhCC_flagCall( actId, &(pCCCmdPrm -> mltyCncFlg));

  psaCC_ctb(actId)->curCmd = AT_CMD_CHLD;
  psaCC_ctb(actId)->curSrc = srcId;

  psaCC_BuildMPTY(actId);

  pCCCmdPrm -> CHLDmode = CHLD_MOD_AddHld;

  /* inform MFW */
  chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_BuildMpty, actId, AT_EXCT );
  return( AT_EXCT );
}

/*-----------------------------------------------------------------
 * explicit call transfer
 *-----------------------------------------------------------------*/
LOCAL T_ACI_RETURN chld_Ect(T_ACI_CMD_SRC srcId)
{
  SHORT cId;                /* holds call id */
  SHORT actId;              /* holds call active id */
  SHORT hldId;              /* holds call hold id */
  T_CC_CMD_PRM * pCCCmdPrm; /* points to CC command parameters */

  TRACE_FUNCTION("chld_Ect");
/*
 *---------------------------------------------------------------
 * find the active(req) or held call
 *---------------------------------------------------------------
 */
  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  actId = hldId = -1;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL)
    {
      if( cmhCC_getcalltype(cId) NEQ VOICE_CALL )
      {
        /* not a valid id for ECT */
      }
      else if (psaCC_ctb(cId)->calStat  EQ CS_ACT OR
                (psaCC_ctb(cId)->calStat EQ CS_ACT_REQ AND
                 psaCC_ctb(cId)->calType EQ CT_MOC))
      {
        if( actId EQ -1 ) actId = cId;
      }
      else if( psaCC_ctb(cId)->calStat EQ CS_HLD )
      {
        if( hldId EQ -1 ) hldId = cId;
      }
    }
  }

  /* curCmd of actId will be updated only if hldId is valid. */
  if( hldId >= 0 AND
    psaCC_ctb(hldId)->curCmd NEQ AT_CMD_NONE )
  {
    TRACE_EVENT_P1("CHLD ECT: hldId busy with %d", psaCC_ctb(hldId)->curCmd);
    return( AT_BUSY );
  }
  /*
   * if command state is not idle and update the curCmd only if it is NONE
   */
  if(actId >= 0 AND hldId >= 0)
  {
    switch(psaCC_ctb(actId)->curCmd)
    {
    case(AT_CMD_NONE):
      psaCC_ctb(actId)->curCmd = AT_CMD_CHLD;
      psaCC_ctb(actId)->curSrc = srcId;
      break;
    case(AT_CMD_D):
      /* command state where actId might find itself */
      break;
    default:
      TRACE_EVENT_P1("CHLD ECT: actId busy with %d", psaCC_ctb(actId)->curCmd);
      return( AT_BUSY );
    }
  }

  if( actId >= 0 AND hldId >= 0 )
  {
    if( psaCC_ECT(hldId) NEQ 0 )
    {
      return(AT_FAIL);
    }
    /* Update params only if the facility message is successfully
       sent to the network */
    cmhCC_flagCall( actId, &(pCCCmdPrm -> mltyDscFlg));
    cmhCC_flagCall( hldId, &(pCCCmdPrm -> mltyDscFlg));
    psaCC_ctb(hldId)->curCmd = AT_CMD_CHLD;
    psaCC_ctb(hldId)->curSrc = srcId;
    ccShrdPrm.cIdMPTY        = actId;

    pCCCmdPrm -> CHLDmode = CHLD_MOD_Ect;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_ECT, actId, AT_EXCT );
    return( AT_EXCT );
  }

  TRACE_EVENT("CHLD: ECT: could not find interesting call ids");
  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
  return( AT_FAIL );
}

/*-----------------------------------------------------------------
 * activate call completion to busy subscriber
 *-----------------------------------------------------------------*/
LOCAL T_ACI_RETURN chld_Ccbs(T_ACI_CMD_SRC srcId)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        dscId = -1; /* will be set if a call is disconnected (with its cId) */
  SHORT cId;               /* holds call id */

  TRACE_FUNCTION("chld_Ccbs");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *---------------------------------------------------------------
 * find the call with CCBS possible
 *---------------------------------------------------------------
 */
  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL AND
        psaCC_ctb(cId)->calStat  EQ CS_DSC_REQ AND
        psaCC_ctb(cId)->calType  EQ CT_MOC     AND
        psaCC_ctb(cId)->CCBSstat EQ CCBSS_PSSBL)
    {
      dscId = cId;
      break;
    }
  }

  if( dscId >= 0 AND
      psaCC_ctb(dscId)->curCmd NEQ AT_CMD_NONE )

    return( AT_BUSY );

/*
 *---------------------------------------------------------------
 * clear a call with CCBS possible
 *---------------------------------------------------------------
 */
  /*lint -e{661} cId causes out of bounds access, it does not! */
  if( dscId >= 0 )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_Ccbs;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;
    psaCC_ctb(cId)->CCBSstat = CCBSS_REQ;

    cmhCC_ClearCall ( dscId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL );

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, CHLD_ACT_CCBS, dscId, AT_EXCT );
    return( AT_EXCT );
  }

  ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
  return( AT_FAIL );
}


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

  PURPOSE : Put a call on hold (and nothing else ==> do not accept 
            any other call)
*/
LOCAL T_ACI_RETURN chld_OnlyHold(T_ACI_CMD_SRC srcId)
{
  SHORT hldId;              /* holds call hold id */
  SHORT cId;                /* holds call id */
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  BOOL  hldCalFlg  = FALSE; /* flags a held call */
  BOOL  mptyHldFlg = FALSE; /* flags a multiparty held call */

  TRACE_FUNCTION("chld_OnlyHold");

  /* find held call */
  hldId = -1;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    if (ccShrdPrm.ctb[cId] NEQ NULL)
    {
      if( psaCC_ctb(cId)->calStat EQ CS_HLD )
      {
        if( hldId EQ -1 ) hldId = cId;
      }
    }
  }

  if( hldId >=0 )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_OneCallOnHold );
    return( AT_FAIL );    /* only one call could be on hold */
  }

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  /* put all active calls on hold */
  /* Implements Measure 181 and 182 */
  if ( chld_HoldActiveCalls( srcId, &mptyHldFlg, &hldCalFlg, &cId ) EQ FALSE )
  {
    return( AT_FAIL ); /* no data calls supported */
  }

  /* at least one call was put on hold */
  if( hldCalFlg )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_OnlyHold;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode,
                 NULL,
                 (mptyHldFlg)? CHLD_ACT_HoldMpty:CHLD_ACT_Hold,
                 cId, AT_EXCT );
    return( AT_EXCT );
  }
  return( AT_FAIL );
}

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

  PURPOSE : release diealling call (special function for FAE's
*/
LOCAL T_ACI_RETURN chld_RelDialCall(T_ACI_CMD_SRC srcId)
{
  T_CC_CMD_PRM *pCCCmdPrm; /* points to CC command parameters */
  SHORT        cId;
  
  TRACE_FUNCTION("chld_RelDialCall");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *---------------------------------------------------------------
 * clear the dialling call
 *---------------------------------------------------------------
 */
  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  cId = psaCC_ctbFindCall( (T_OWN)srcId, CS_ACT_REQ, CT_MOC );

  TRACE_EVENT_P1("Call Id of dialling call = %d",cId);

  if( cId >= 0 )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_RelDialCall;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    cmhCC_ClearCall(cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL);

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm -> CHLDmode, NULL, CHLD_ACT_Release, cId, AT_EXCT );

    return( AT_EXCT );
  }

  /* Unable to find call */
  return( AT_FAIL);
}


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

  PURPOSE : retrieve an held call (and nothing else)
            - waiting call's still knocked on
            - will hold active call
*/
LOCAL T_ACI_RETURN chld_RetrieveHoldCall(T_ACI_CMD_SRC srcId)
{
  T_CC_CMD_PRM  *pCCCmdPrm;          /* points to CC command parameters */
  SHORT          cId;                /* call id */
  SHORT          cwaId      = -1;    /* holds call waiting id */
  SHORT          hldId      = -1;    /* holds call hold id */
  SHORT          rclId      = -1;    /* holds recall id */
  BOOL           mptyHldFlg = FALSE; /* flags a multiparty held call */
  BOOL           hldCalFlg  = FALSE; /* flags a held call */
  T_ACI_CHLD_ACT chldact;            /* contains the type of CHLD activity when informing MFW */

  TRACE_FUNCTION("chld_RetrieveHoldCall");

  /* find the waiting or held call */
  if( find_waiting_held_call(&cwaId, &hldId, &rclId) EQ AT_BUSY)
  {
    return(AT_BUSY);
  }

  if( hldId < 0 )
  { /* no held call found */
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallNotFound );
    return( AT_FAIL );
  }

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm; /* temp copy */

/*
 *---------------------------------------------------------------
 * put all active calls on hold
 *---------------------------------------------------------------
 */
  /* Implements Measure 181 and 182 */
  if ( chld_HoldActiveCalls( srcId, &mptyHldFlg, &hldCalFlg, &cId ) EQ FALSE )
  {
    return( AT_FAIL ); /* no data calls supported */
  }

  /* maybe, one or more calls were put on hold */
  if( hldCalFlg )
  {
    pCCCmdPrm -> CHLDmode = CHLD_MOD_HldActAndAcpt;
    CHLDaddInfo           = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode,
                 NULL,
                 (mptyHldFlg)? CHLD_ACT_HoldMpty:CHLD_ACT_Hold,
                 cId, AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * retrieve the held call
 *---------------------------------------------------------------
 */
  cmhCC_flagCall(hldId, &(pCCCmdPrm -> mltyCncFlg));
  pCCCmdPrm -> CHLDmode = CHLD_MOD_RetrieveHoldCall;

  cmhCC_RetrieveCall(hldId, srcId);

  /* inform MFW */
  chldact = (psaCC_ctb(hldId)->mptyStat EQ CS_ACT)? CHLD_ACT_RetrieveMpty :CHLD_ACT_Retrieve;
  chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, chldact, hldId, AT_EXCT );
  return( AT_EXCT );
}


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

  PURPOSE : retrieve specific held call (and nothing else)
            - release waiting call
            - will hold active call
*/
LOCAL T_ACI_RETURN chld_RetrieveHoldCallSpec(T_ACI_CMD_SRC srcId, CHAR *call)
{
  T_CC_CMD_PRM  *pCCCmdPrm;          /* points to CC command parameters */
  SHORT          cId;                /* call id */
  SHORT          temp_cId;
  BOOL           mptyHldFlg = FALSE; /* flags a multiparty held call */
  BOOL           hldCalFlg  = FALSE; /* flags a held call */
  T_ACI_CHLD_ACT chldact;            /* contains the type of CHLD activity when informing MFW */

  TRACE_FUNCTION("chld_RetrieveHoldCallSpec");

  if( call EQ NULL )
  {
    TRACE_ERROR("CALL parameter is needed !!!");
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );  /* no call specified */
  }

  cId = atoi( call ); /* char --> int */

  if( (cId EQ 0) OR (cId > MAX_CALL_NR) )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

  cId--; /* adapt to call table index */

  pCCCmdPrm  = &cmhPrm[srcId].ccCmdPrm;

  /* test whether specified call is a held call */
  if ((ccShrdPrm.ctb[cId] EQ NULL)                  OR
      (psaCC_ctb(cId)->calStat NEQ CS_HLD)      OR
      (psaCC_ctb(cId)->curCmd  NEQ AT_CMD_NONE) OR
      (cmhCC_getcalltype(cId) NEQ VOICE_CALL))
  { /* no held call or no voice call --> error */
    pCCCmdPrm -> mltyCncFlg = 0;
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
    return( AT_FAIL );    /* no data calls supported */
  }


/*
 *---------------------------------------------------------------
 * put all active calls on hold
 *---------------------------------------------------------------
 */
  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  for( temp_cId = 0; temp_cId < MAX_CALL_NR; temp_cId++ )
  {
    T_CC_CALL_TBL *pCallTable = ccShrdPrm.ctb[temp_cId];

    if( pCallTable NEQ NULL              AND
        pCallTable->calStat    EQ CS_ACT AND
        pCallTable->curCmd     EQ AT_CMD_NONE )
    {
      if( cmhCC_getcalltype(temp_cId) NEQ VOICE_CALL )
      {
        pCCCmdPrm -> mltyCncFlg = 0;
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
        return( AT_FAIL );    /* no data calls supported */
      }

      if( (pCallTable->mptyStat EQ CS_IDL) OR
          ((pCallTable->mptyStat EQ CS_ACT) AND (mptyHldFlg EQ FALSE)) )
      {
        hldCalFlg = TRUE;
      }

      /* if active call is a multiparty call */
      if( pCallTable->mptyStat EQ CS_ACT )
      {
        mptyHldFlg = TRUE;
      }

      cmhCC_HoldCall(temp_cId, srcId, AT_CMD_CHLD);
    }
  }

  /* maybe, one or more calls were put on hold */
  if( hldCalFlg )
  {
    pCCCmdPrm->CHLDmode = CHLD_MOD_HldActAndAcpt;
    CHLDaddInfo = NO_CHLD_ADD_INFO;

    /* inform MFW */
    chld_ratlog( srcId, pCCCmdPrm->CHLDmode,
                 NULL,
                 (mptyHldFlg)? CHLD_ACT_HoldMpty:CHLD_ACT_Hold,
                 cId, AT_EXCT );
  }

/*
 *---------------------------------------------------------------
 * retrieve the held call
 *---------------------------------------------------------------
 */
  cmhCC_flagCall(cId, &(pCCCmdPrm -> mltyCncFlg));
  pCCCmdPrm -> CHLDmode = CHLD_MOD_RetrieveHoldCallSpec;

  cmhCC_RetrieveCall(cId, srcId);

  /* inform MFW */
  if (psaCC_ctb(cId)->mptyStat EQ CS_ACT)
    chldact = CHLD_ACT_RetrieveMpty;
  else
    chldact = CHLD_ACT_Retrieve;
  chld_ratlog( srcId, pCCCmdPrm->CHLDmode, NULL, chldact, cId, AT_EXCT );
  return( AT_EXCT );
}

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

  PURPOSE : This is the functional counterpart to the +CHLD AT command
            which is responsible to handle the supplementary services
            witin a call
*/
GLOBAL T_ACI_RETURN sAT_PlusCHLD  ( T_ACI_CMD_SRC    srcId,
                                    T_ACI_CHLD_MOD   mode,
                                    CHAR            *call)
{
  TRACE_FUNCTION ("sAT_PlusCHLD()");

  if( mode > CHLD_MOD_RelDialCall )
  { /* not allowed modes inside '+'-command */
    TRACE_EVENT("this mode is not allowed for sAT_PlusCHLD()");
    return( AT_FAIL );
  }
  else
  {
    return( cmhCC_CHLD_Serv(srcId, mode, call) );
  }
}


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

  PURPOSE : This is the functional counterpart to the %CHLD AT command
            which is responsible to handle the supplementary services
            witin a call
*/
GLOBAL T_ACI_RETURN sAT_PercentCHLD  ( T_ACI_CMD_SRC    srcId,
                                    T_ACI_CHLD_MOD   mode,
                                    CHAR            *call)
{
  TRACE_FUNCTION ("sAT_PercentCHLD()");

  return( cmhCC_CHLD_Serv(srcId, mode, call) );
}

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

  PURPOSE : This is the functional counterpart to the +CCUG AT command
            which is responsible to set the parameters for closed user
            group supplementary services.

            <mode>   : CUG mode.
            <index>  : CUG index.
            <info>   : CUG info.
*/

GLOBAL T_ACI_RETURN sAT_PlusCCUG  ( T_ACI_CMD_SRC   srcId,
                                    T_ACI_CCUG_MOD  mode,
                                    T_ACI_CCUG_IDX  index,
                                    T_ACI_CCUG_INFO info)
{
  T_CC_CMD_PRM * pCCCmdPrm; /* points to CC command parameters */

  TRACE_FUNCTION ("sAT_PlusCCUG()");

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

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * process the mode parameter
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    case( CCUG_MOD_NotPresent ):

      mode = pCCCmdPrm -> CCUGmode;
      break;

    case( CCUG_MOD_DisableTmp ):
    case( CCUG_MOD_EnableTmp  ):

      break;

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

/*
 *-------------------------------------------------------------------
 * process the index parameter
 *-------------------------------------------------------------------
 */
  switch( index )
  {
    case( CCUG_IDX_NotPresent ):

      index = pCCCmdPrm -> CCUGidx;
      break;

    case( CCUG_IDX_0  ):
    case( CCUG_IDX_1  ):
    case( CCUG_IDX_2  ):
    case( CCUG_IDX_3  ):
    case( CCUG_IDX_4  ):
    case( CCUG_IDX_5  ):
    case( CCUG_IDX_6  ):
    case( CCUG_IDX_7  ):
    case( CCUG_IDX_8  ):
    case( CCUG_IDX_9  ):
    case( CCUG_IDX_No ):

      break;

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

/*
 *-------------------------------------------------------------------
 * process the info parameter
 *-------------------------------------------------------------------
 */
  switch( info )
  {
    case( CCUG_INFO_NotPresent ):

      info = pCCCmdPrm -> CCUGinfo;
      break;

    case( CCUG_INFO_No          ):
    case( CCUG_INFO_SuppOa      ):
    case( CCUG_INFO_SuppPrefCug ):
    case( CCUG_INFO_SuppBoth    ):

      break;

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

/*
 *-------------------------------------------------------------------
 * assign the parameters
 *-------------------------------------------------------------------
 */
  pCCCmdPrm -> CCUGmode = mode;
  pCCCmdPrm -> CCUGidx  = index;
  pCCCmdPrm -> CCUGinfo = info;

  return( AT_CMPL );
}

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

  PURPOSE : This is the functional counterpart to the +VTS AT command
            which is responsible to send DTMF tones.
*/

GLOBAL T_ACI_RETURN sAT_PlusVTS   ( T_ACI_CMD_SRC    srcId,
                                    CHAR             dtmf,
                                    T_ACI_VTS_MOD    mode )
{
  SHORT        cId;                 /* holds call id */
  BOOL         param_ok;

  TRACE_FUNCTION ("sAT_PlusVTS()");

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


  cId = cmhCC_find_call_for_DTMF( );
  if (cId EQ NO_ENTRY)
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  /* allow to send DTMF tone one after another quickly
  if( psaCC_ctb(cId)->dtmfCmd NEQ AT_CMD_NONE )
    return( AT_BUSY );*/

  /* if DTMF are already being sent */
  if (( ccShrdPrm.dtmf.cnt AND mode NEQ VTS_MOD_ManStop ) OR
    ( ccShrdPrm.dtmf.cur AND (mode NEQ VTS_MOD_ManStop)))
  {
    TRACE_EVENT("DTMF are already being sent !");
    return( AT_BUSY );
  }
  else if ( !ccShrdPrm.dtmf.cur AND mode EQ VTS_MOD_ManStop )
  {
    TRACE_EVENT("Cannot stop a DTMF tone that hasn't been started!");
    return( AT_FAIL );
  }
  else if ( ccShrdPrm.dtmf.cur AND (ccShrdPrm.dtmf.cur NEQ dtmf ))
  {
    TRACE_EVENT("Cannot stop a different DTMF tone than the one that is started!");
    return( AT_FAIL );
  }

  /* process mode parameter */
  switch( mode )
  {
    case( VTS_MOD_Auto ):
      psaCC_ctb(cId)->dtmfMode = MNCC_DTMF_MOD_AUTO;
      break;

    case( VTS_MOD_ManStart ):
      psaCC_ctb(cId)->dtmfMode = MNCC_DTMF_MOD_MAN_START;
      ccShrdPrm.dtmf.cur = dtmf;
      break;

    case( VTS_MOD_ManStop ):
      psaCC_ctb(cId)->dtmfMode = MNCC_DTMF_MOD_MAN_STOP;
      break;

    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return( AT_FAIL );
  }

  psaCC_ctb(cId)->dtmfCmd = AT_CMD_VTS; /* wait for confirmation */
  psaCC_ctb(cId)->dtmfSrc = (T_OWN)srcId;
  /* has to remember tone sent in case of an abort */
  ccShrdPrm.dtmf.cnt = 1;
  ccShrdPrm.dtmf.dig[0] = dtmf;
  ccShrdPrm.dtmf.cId = cId;

  param_ok = cmhCC_SendDTMFdig ( AT_CMD_VTS, cId, dtmf, psaCC_ctb(cId)->dtmfMode);

  if( param_ok )
  {
    return( AT_EXCT );
  }
  else
  {
    ccShrdPrm.dtmf.cnt = 0;
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
}

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

  PURPOSE : This is the functional counterpart to the +CSNS AT command
            which is responsible to set the parameters for single
            numbering scheme.
*/

GLOBAL T_ACI_RETURN sAT_PlusCSNS  ( T_ACI_CMD_SRC    srcId,
                                    T_ACI_CSNS_MOD   mode)
{

  TRACE_FUNCTION ("sAT_PlusCSNS()");

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


/*
 *-------------------------------------------------------------------
 * check parameter mode
 *-------------------------------------------------------------------
 */
  switch( mode )
  {
    case( CSNS_MOD_NotPresent ):

      mode = CSNS_MOD_Voice;
      break;

    case( CSNS_MOD_Voice ):
#ifdef FAX_AND_DATA
    case( CSNS_MOD_VAFVoice ):
    case( CSNS_MOD_Fax ):
    case( CSNS_MOD_VADVoice ):
    case( CSNS_MOD_Data ):
    case( CSNS_MOD_VAFFax ):
    case( CSNS_MOD_VADData ):
    case( CSNS_MOD_VFD ):
#endif /* FAX_AND_DATA */
      break;

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

  ccShrdPrm.snsMode = mode;

  psaCC_Config( );

  return( AT_CMPL );
}

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

  PURPOSE : Reset all values to defaults.
*/

GLOBAL T_ACI_RETURN sAT_AndF      ( T_ACI_CMD_SRC srcId,
                                    SHORT         value)
{

  TRACE_FUNCTION ("sAT_AndF()");

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

/*
 *-------------------------------------------------------------------
 * check parameter value
 *-------------------------------------------------------------------
 */
  if( value NEQ 0 AND value NEQ ACI_NumParmNotPresent )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 * reset value to defaults
 *-------------------------------------------------------------------
 */
  cmh_Reset ( srcId, TRUE );

  return( AT_CMPL );
}


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

  PURPOSE : Reset all values to factory defaults in the GSM part of ACI.
*/

GLOBAL T_ACI_RETURN sGsmAT_Z ( T_ACI_CMD_SRC srcId )
{
  SHORT cId;                  /* holds call id */
  SHORT waitId = NO_ENTRY;    /* holds call waiting id */
  T_CC_CMD_PRM * pCCCmdPrm;   /* points to CC command parameters */

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif

  TRACE_FUNCTION ("sGsmAT_Z()");

/*
 *-------------------------------------------------------------------
 * command source is checked
 *-------------------------------------------------------------------
 */
  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

/*
 *-------------------------------------------------------------------
 * prepare log command
 *-------------------------------------------------------------------
 */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.atCmd                = AT_CMD_Z;
  cmdLog.cmdType              = CLOG_TYPE_Set;
  cmdLog.retCode              = AT_EXCT;
  cmdLog.sId                  = ACI_NumParmNotPresent;
  cmdLog.cmdPrm.sH.srcId      = srcId;
#endif  /* End of SMI Or defined MFW*/

/*
 *-------------------------------------------------------------------
 * clear all calls except a waiting call
 *-------------------------------------------------------------------
 */
  pCCCmdPrm -> mltyDscFlg = 0;

  for( cId = 0; cId < MAX_CALL_NR; cId++ )
  {
    /* Clear only calls in use ! */
    if (ccShrdPrm.ctb[cId] NEQ NULL)
    {
      cmhCC_ClearCall(cId,MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_Z, &waitId);
    }
  }

 if( pCCCmdPrm -> mltyDscFlg )
  {
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    rAT_PercentCLOG( &cmdLog );
#endif
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 * disconnect a waiting call with user determined user busy
 *-------------------------------------------------------------------
 */
  /* Implements Measure 165 */
  if ( waitId NEQ NO_ENTRY )
  {
    cmhCC_disconnect_waiting_call ( srcId, waitId, AT_CMD_Z,
                                    &(pCCCmdPrm -> mltyDscFlg) );
    return( AT_EXCT );
  }

/*
 *-------------------------------------------------------------------
 *   reset value to default if no call is active
 *-------------------------------------------------------------------
 */
  cmh_Reset ( srcId, TRUE );

  R_AT(RAT_Z, srcId)();

  return( AT_CMPL );
}

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

  PURPOSE : Reset all values to factory defaults.
*/

GLOBAL T_ACI_RETURN sAT_Z ( T_ACI_CMD_SRC srcId,
                            SHORT         value)
{

  TRACE_FUNCTION ("sAT_Z()");

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

/*
 *-------------------------------------------------------------------
 * check parameter value
 *-------------------------------------------------------------------
 */
  if( value NEQ 0 AND value NEQ ACI_NumParmNotPresent )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

/*
 *-------------------------------------------------------------------
 *   clear all calls and reset all value to default
 *-------------------------------------------------------------------
 */
  
#if defined (GPRS) AND defined (DTI)    
  return sGprsAT_Z ( srcId );
#else
  return sGsmAT_Z ( srcId );
#endif  /* GPRS */
}

#if defined (FAX_AND_DATA) AND defined (DTI)
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                  |
| STATE   : code                  ROUTINE : sAT_O                    |
+--------------------------------------------------------------------+

  PURPOSE : Return to online mode
*/

GLOBAL T_ACI_RETURN sAT_O ( T_ACI_CMD_SRC srcId )
{
  SHORT           cId;           /* holds call id */
  T_DTI_CONN_CB  *dti_conn_cb;
  T_DTI_ENTITY_ID entity_list[2]; 
#ifdef FF_PSI
  T_ACI_DTI_PRC_PSI *src_infos_psi = NULL;
#endif /* FF_PSI */
  TRACE_FUNCTION("sAT_O()");

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

/*
 *-------------------------------------------------------------------
 * find active call
 *-------------------------------------------------------------------
 */
  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT );

  if( cId EQ NO_ENTRY )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallNotFound );
    return( AT_FAIL );
  }

  switch( cmhCC_getcalltype(cId) )
  {
    case( TRANS_CALL ):
      entity_list[0] = DTI_ENTITY_TRA;
      dti_conn_cb = TRA_connect_dti_cb;
      break;

    case( NON_TRANS_CALL ):
      entity_list[0] = DTI_ENTITY_L2R;
      dti_conn_cb = L2R_connect_dti_cb;
      break;

    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
      return( AT_FAIL );
  }

  if( psaCC_ctb(cId)->curCmd NEQ AT_CMD_NONE ) 
    return( AT_BUSY );

  R_AT( RAT_CONNECT, srcId )
    ( AT_CMD_O, cmhCC_GetDataRate(&psaCC_ctb(cId)->
                                   BC[psaCC_ctb(cId)->curBC]),
      cId+1, FALSE );

  psaCC_ctb(cId)->curCmd = AT_CMD_O;
  psaCC_ctb(cId)->curSrc = srcId;


  if (IS_SRC_BT(srcId))
  {
    entity_list[1] = DTI_ENTITY_BLUETOOTH;
    dti_cntrl_est_dpath((UBYTE)srcId, entity_list, 2, SPLIT, dti_conn_cb);
  }
  else
  {
#ifdef FF_PSI
    src_infos_psi = find_element(psi_src_params,(UBYTE) srcId, cmhPSItest_srcId);
    memset(&psi_ato,0,sizeof(T_ACI_PSI_CALL_TYPE));
    if (src_infos_psi NEQ NULL)
    {
      psi_ato.src_id = (UBYTE)srcId;
      psi_ato.entity_to_conn = entity_list[0];
      psi_ato.num_entities = 1;
      psi_ato.mode = SPLIT;
      psi_ato.cb = dti_conn_cb;
      psi_ato.capability = DTI_CPBLTY_SER;
      psi_ato.cid = DTI_CID_NOTPRESENT;
      psi_ato.last_cmd = AT_CMD_O;
    }
    else
    {
#endif /* FF_PSI */
      dti_cntrl_est_dpath_indirect ( (UBYTE)srcId,
                                      entity_list,
                                      1,
                                      SPLIT,
                                      dti_conn_cb,
                                      DTI_CPBLTY_SER,
                                      DTI_CID_NOTPRESENT);
#ifdef FF_PSI
    }
#endif /* FF_PSI */
  }

  return( AT_EXCT );
}
#endif

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                 |
|                                 ROUTINE : sAT_PercentALS          |
+-------------------------------------------------------------------+

  PURPOSE : set the ALS mode for outgoing calls (voice)
            ALS_MOD_SPEECH:
               indicates bearer capability => BEARER_SERV_SPEECH
            ALS_MOD_AUX_SPEECH:
               indicates bearer capability => BEARER_SERV_AUX_SPEECH
*/

GLOBAL T_ACI_RETURN sAT_PercentALS( T_ACI_CMD_SRC srcId,
                                    T_ACI_ALS_MOD mode   )
{
  TRACE_FUNCTION("sAT_PercentALS()");

  if( !cmh_IsVldCmdSrc( srcId ) )
  {
    return( AT_FAIL );
  }

  /* line will really change? */
  if (mode EQ cmhPrm[srcId].ccCmdPrm.ALSmode)
  {
    return (AT_CMPL);
  }

  if ( ALSlock NEQ ALS_MOD_NOTPRESENT )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return( AT_FAIL );
  }

  if ( mode EQ ALS_MOD_SPEECH )
  {
    cmhPrm[srcId].ccCmdPrm.ALSmode = ALS_MOD_SPEECH;
    return( AT_CMPL );
  }
  else if ( mode EQ ALS_MOD_AUX_SPEECH )
  {
    /* E-Plus SIM-Card inserted (mcc=0x262, mnc=0x03) ? */
    if (cmhSIM_plmn_is_hplmn(0x262, 0x03F))
    {
      cmhPrm[srcId].ccCmdPrm.ALSmode = ALS_MOD_AUX_SPEECH;
      return( AT_CMPL );
    }
    else
    {
      simEntStat.curCmd = AT_CMD_ALS;
      simShrdPrm.owner = (T_OWN)srcId;
      simEntStat.entOwn = srcId;

      ccShrdPrm.als_cmd = ALS_CMD_SET;

      cmhCC_checkALS_Support();
      return (AT_EXCT);
    }
  }
  else
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                 |
|                                 ROUTINE : sAT_PercentCTTY         |
+-------------------------------------------------------------------+

  PURPOSE : Handling TTY
*/

GLOBAL T_ACI_RETURN sAT_PercentCTTY (T_ACI_CMD_SRC srcId,
                                     T_ACI_CTTY_MOD mode,
                                     T_ACI_CTTY_REQ req)
{

#ifdef FF_TTY
  SHORT       cId;             /* holds call id */
  T_TTY_CMD   ttyAction = TTY_OFF;
  T_MNCC_bcpara   *bc;

  TRACE_FUNCTION("sAT_PercentCTTY()");

   if (!cmh_IsVldCmdSrc( srcId ))
  {
    return AT_FAIL;
  }
  
  /*
   * find if any call is active
   */
  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT, NO_VLD_CT);
  
  if(cId NEQ NO_ENTRY )
  {
    T_CC_CALL_TBL *ctb = ccShrdPrm.ctb[cId];

    TRACE_EVENT ("sAT_PercentCTTY() Active call found ");

    /*
     * if command state is not idle
     */
    switch(ctb->curCmd)
    {
    case(AT_CMD_NONE):
      break;
    default:
      TRACE_EVENT_P1("CTTY: cId busy with %d", ctb->curCmd);
      return( AT_BUSY );
    }

    /*
     * Check if the active call is a TTY call
     */
    bc = &ctb->BC[ctb->curBC];

    if (bc->bearer_serv EQ MNCC_BEARER_SERV_SPEECH_CTM OR
        bc->bearer_serv EQ MNCC_BEARER_SERV_AUX_SPEECH_CTM)
    {
      if ((mode EQ CTTY_MOD_Disable) OR (mode EQ CTTY_MOD_Enable))
      {
        cmhPrm[srcId].ccCmdPrm.CTTYmode = mode;
      }

      switch (req)
      {
      case CTTY_REQ_Off:
        /*
         * stop the running TTY, a normal voice call
         */
        ccShrdPrm.ctmReq = MNCC_CTM_DISABLED;
        ccShrdPrm.ttyCmd = (UBYTE)TTY_OFF;
        
        cmhCC_TTY_Control (cId, TTY_STOP);
        return( AT_CMPL );

      case CTTY_REQ_On:
        ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
        ccShrdPrm.ttyCmd = (UBYTE)TTY_ALL;
        break;
      case CTTY_REQ_HCO:
        ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
        ccShrdPrm.ttyCmd = (UBYTE)TTY_HCO;
        break;
      case CTTY_REQ_VCO:
        ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
        ccShrdPrm.ttyCmd = (UBYTE)TTY_VCO;
        break;
      default:
        ACI_ERR_DESC (ACI_ERR_CLASS_Ext, EXT_ERR_Parameter);
        return AT_FAIL;
      }
      
      audio_dyn_set_tty (ttyAction = (T_TTY_CMD)ccShrdPrm.ttyCmd);

      /*
       * This is for the case when mode is changed from Voice to any other
       */
      ccShrdPrm.ctmState = TTY_STATE_ACTIVE;

      cmhCC_notifyTTY (CTTY_NEG_Grant, cmhCC_getTTYtrx_state (ttyAction));

      return AT_CMPL; 
    }
    else
    {
      /*
       * If the active call is a normal GSM call then its a wrong bearer cap
       */
      TRACE_EVENT_P1 ("TTY wrong BCAP: %d", (int)bc->bearer_serv);
      return (AT_FAIL);
    }
  }
  else
  {
    /*
     * If no active call then its a static switching set the bearer cap
     *  for next and subsequent calls
     */
    TRACE_EVENT ("sAT_PercentCTTY() No active call found ");
    
    if ((mode EQ CTTY_MOD_Disable) OR (mode EQ CTTY_MOD_Enable))
    {
      cmhPrm[srcId].ccCmdPrm.CTTYmode = mode;
    }
    switch (req)
    {
    case CTTY_REQ_Off:
      ccShrdPrm.ctmReq = MNCC_CTM_DISABLED;
      ccShrdPrm.ttyCmd = (UBYTE)TTY_OFF;
      psaCC_Config ();
      break;
    case CTTY_REQ_On:
      ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
      ccShrdPrm.ttyCmd = (UBYTE)TTY_ALL;
      psaCC_Config ();
      break;
    case CTTY_REQ_HCO:
      ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
      ccShrdPrm.ttyCmd = (UBYTE)TTY_HCO;
      psaCC_Config ();
      break;
    case CTTY_REQ_VCO:
      ccShrdPrm.ctmReq = MNCC_CTM_ENABLED;
      ccShrdPrm.ttyCmd = (UBYTE)TTY_VCO;
      psaCC_Config ();
      break;
    default:
      ACI_ERR_DESC (ACI_ERR_CLASS_Ext, EXT_ERR_Parameter);
      return AT_FAIL;
    }
    if (req EQ CTTY_REQ_Off)
    {
      if (ccShrdPrm.ctmState EQ TTY_STATE_IDLE)
      {
        ccShrdPrm.ctmState = TTY_STATE_NONE;
      }
    }
    else
    {
      if (ccShrdPrm.ctmState EQ TTY_STATE_NONE)
      {
        ccShrdPrm.ctmState = TTY_STATE_IDLE;
      }
    }
    return AT_CMPL;
  }
#else
  ACI_ERR_DESC (ACI_ERR_CLASS_Cme, CME_ERR_OpNotSupp);
  return AT_FAIL;
#endif  /* FF_TTY */
}

#ifdef DTI
#if defined (FF_WAP) || defined (FF_GPF_TCPIP) || defined (FF_SAT_E)
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                  |
| STATE   : code                  ROUTINE : sAT_PercentWAP           |
+--------------------------------------------------------------------+

  PURPOSE : set next call as a WAP call / unsent WAP call
*/

GLOBAL T_ACI_RETURN sAT_PercentWAP ( T_ACI_CMD_SRC srcId , SHORT setflag )
{
  TRACE_FUNCTION("sAT_PercentWAP()");

  switch (setflag)
  {
  case (0): /* unsent WAP call */
    /* End of processing of WAP entities              */
    /* WAP-dedicated variables shall be reinitialized */
    wapId     = NO_ENTRY;
    Wap_Call  = FALSE;
    wap_state = Wap_Not_Init;
    if ( wap_dti_id NEQ DTI_DTI_ID_NOTPRESENT )
    {
      dti_cntrl_erase_entry (wap_dti_id);
      wap_dti_id = DTI_DTI_ID_NOTPRESENT;
    }
    break;

  case (1): /* next call will be a WAP call */
    if (!Wap_Call)
    {
      Wap_Call = TRUE;
#ifdef FF_PPP
      /* FST: not possible in the moment -> see #ifdef before function definition */
      
      /* reset is_PPP_CALL */
      pppShrdPrm.is_PPP_CALL = FALSE;
#endif /* FF_PPP */
    }
    else
    {
      TRACE_EVENT("ERROR: a WAP Call is currently in progress");
      return AT_FAIL;
    }
    break;
  }

  return AT_CMPL;
}
#endif /* of WAP || FF_GPF_TCPIP || SAT E */
#endif /* DTI */

#if defined MFW AND defined TI_PS_FF_AT_P_CMD_MMITEST
/* MMI TEST AT COMMAND */


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

  PURPOSE : This command has been introduced in order to use the AT command interface for some MMI
 specific testing. It shoudnt be compiled without MMI.

*/


GLOBAL T_ACI_RETURN sAT_PercentMMITEST(T_ACI_CMD_SRC srcId, char *param)
{

  TRACE_FUNCTION ("sAT_PercentMMITEST ()");

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

  rAT_PercentMMITEST(param);

  return AT_CMPL;
}  /* sAT_PercentMMITEST */

#endif

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

  PURPOSE : initializing of redial parameter
*/
GLOBAL void rdlPrm_init(void)
{  
  TRACE_FUNCTION ("rdlPrm_init ()");

#ifdef TI_PS_FF_AT_P_CMD_RDLB
  rdlPrm.rdlBlN =   NO_NOTIF_USER;
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
  rdlPrm.rdlcId =   NO_ENTRY;
  rdlPrm.rdlMod =   AUTOM_REPEAT_OFF;
  rdlPrm.rdlModN =  NO_NOTIF_USER;
  rdlPrm.rdlBlMod = BLMODE_NO_PRESENT;


#if defined(_TARGET_)
  cmhCC_rd_mode_FFS(AUTOM_REP_NOT_PRESENT,READ_RDLmode); /* read redial mode from FFS */
  if(rdlPrm.rdlMod EQ AUTOM_REPEAT_ON)
  {
#ifdef TI_PS_FF_AT_P_CMD_RDLB
    if(cc_blacklist_ptr EQ NULL)
    {
      ACI_MALLOC(cc_blacklist_ptr,sizeof(T_ACI_CC_REDIAL_BLACKL));
      memset(cc_blacklist_ptr, 0 , sizeof(T_ACI_CC_REDIAL_BLACKL));
    }
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
  }
#endif /* _TARGET_ */  
}

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

  PURPOSE : 
*/
GLOBAL void rdlPrm_exit(void)
{  
  TRACE_FUNCTION ("rdlPrm_exit ()");

#ifdef TI_PS_FF_AT_P_CMD_RDLB
  rdlPrm.rdlBlN =   NO_NOTIF_USER;
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
  rdlPrm.rdlcId =   NO_ENTRY;
  rdlPrm.rdlMod =   AUTOM_REP_NOT_PRESENT;
  rdlPrm.rdlModN =  NO_NOTIF_USER;
  rdlPrm.rdlBlMod = BLMODE_NO_PRESENT;

#ifdef TI_PS_FF_AT_P_CMD_RDLB
  if(cc_blacklist_ptr NEQ NULL)
  {
    ACI_MFREE(cc_blacklist_ptr);
  }
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
}

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

  PURPOSE : This command has been introduced in order to set the 
            redial mode and notification state referring to outgoing 
            calls on ON/OFF
*/
GLOBAL T_ACI_RETURN sAT_PercentRDL(T_ACI_CMD_SRC srcId, 
                                      T_ACI_CC_REDIAL_MODE redial_mode,
                                      T_ACI_CC_REDIAL_NOTIF notification)
{ 
 int i;

  TRACE_FUNCTION ("sAT_PercentRDL ()");

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

  if(redial_mode EQ AUTOM_REP_NOT_PRESENT)
  {
    redial_mode = rdlPrm.rdlMod;
  }
  
  switch(notification)
  {
    case NOTIF_NO_PRESENT:
      notification = rdlPrm.rdlModN;
      break;
    case NOTIF_USER:
    case NO_NOTIF_USER:      
      rdlPrm.rdlModN = notification;
      break;
    default:
      ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
      return( AT_FAIL ); 
  }
  
  switch(redial_mode)
  {
      case AUTOM_REPEAT_OFF:
#if defined(_TARGET_)
        /* store redial mode in FFS */
        cmhCC_rd_mode_FFS(redial_mode,WRITE_RDLmode);
#endif /* _TARGET_ */
        /* stop redialling timer if necessary */
        if (rdlPrm.rdlcId NEQ NO_ENTRY)
        {
          TIMERSTOP(ACI_REPEAT_HND);
#ifdef SIM_TOOLKIT
          if( ( ccShrdPrm.ctb[rdlPrm.rdlcId]->SATinv & SAT_REDIAL ) )
          { /* This is the call invoked by SAT */
            T_ACI_SAT_TERM_RESP resp_data;
            psaSAT_InitTrmResp( &resp_data );
            psaSAT_SendTrmResp( RSLT_USR_CLR_DWN, &resp_data );
          }
          if(satShrdPrm.dur)
          {
            TIMERSTOP(ACI_SAT_MAX_DUR_HND);
            satShrdPrm.dur  = -1;
          }
#endif /* SIM_TOOLKIT */
          if(rdlPrm.rdlcId NEQ -1)
          {/* clear call id entry in call table if marked as used */
            psaCC_FreeCtbNtry (rdlPrm.rdlcId);
            for(i = 0; i < CMD_SRC_MAX; i++)
            {
              R_AT(RAT_RDL, (T_ACI_CMD_SRC)i)(REDIAL_STOP);
            }
          }
        }
        /* reset redial parameter */
        rdlPrm_init();
        return AT_CMPL;        
      case AUTOM_REPEAT_ON:
        rdlPrm.rdlMod = redial_mode;
#if defined(_TARGET_)
        /* store redial mode in FFS */
        cmhCC_rd_mode_FFS(redial_mode,WRITE_RDLmode);
#endif /* _TARGET_ */
#ifdef TI_PS_FF_AT_P_CMD_RDLB        
        /* allocate blacklist for phone numbers forbidden to call */
        if(cc_blacklist_ptr EQ NULL)
        {
          /* Check if we have enough RAM for the following ACI_MALLOC */
          USHORT free, alloc;
          int ret;
          ret = vsi_m_status ( hCommACI,
                               sizeof(T_ACI_CC_REDIAL_BLACKL),
                               PRIM_POOL_PARTITION,
                               &free,
                               &alloc );
          if (ret EQ VSI_ERROR || free EQ 0)
          {
            ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_MemFull);
            return (AT_FAIL);
          }
          ACI_MALLOC(cc_blacklist_ptr,sizeof(T_ACI_CC_REDIAL_BLACKL));
          memset(cc_blacklist_ptr, 0 , sizeof(T_ACI_CC_REDIAL_BLACKL));
        }
#endif /* TI_PS_FF_AT_P_CMD_RDLB */
        return AT_CMPL;
      default:
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );      
  }  
}

#ifdef TI_PS_FF_AT_P_CMD_RDLB
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)             MODULE  : CMH_CCS              |
| STATE   : code                      ROUTINE : sAT_PercentRDLB  |
+--------------------------------------------------------------------+

  PURPOSE : This command has been introduced in order to delete the 
            black list entries  (forbidden outgoing phone numbers)
*/
GLOBAL T_ACI_RETURN sAT_PercentRDLB(T_ACI_CMD_SRC srcId, 
                                        T_ACI_CC_REDIAL_BLMODE blacklist_mode,
                                        T_ACI_CC_REDIAL_NOTIF notification)
{    
  TRACE_FUNCTION ("sAT_PercentRDLB ()");

/*
 *-------------------------------------------------------------------
 * check command source
 *-------------------------------------------------------------------
 */  
  if(!cmh_IsVldCmdSrc (srcId)) 
  { 
    return( AT_FAIL );
  }
 
  if(rdlPrm.rdlMod EQ AUTOM_REPEAT_ON)
  {
  
    switch(blacklist_mode)
    {
      case BLMODE_NO_PRESENT:
        rdlPrm.rdlBlMod = BL_NO_DELETE; /* if no parameter is given the black list is not deleted */
        break;
      case BL_NO_DELETE:
      case BL_DELETE:
      /* store black list mode */
        rdlPrm.rdlBlMod = blacklist_mode;
        break;
      default:
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL );
    }
  
    /* store black list notification mode */
    switch(notification)
    {
      case NOTIF_NO_PRESENT:
        notification = rdlPrm.rdlBlN;
        break;
      case NOTIF_USER:
      case NO_NOTIF_USER:      
        rdlPrm.rdlBlN = notification;
        break;
      default:
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
        return( AT_FAIL ); 
    } 
     /* reset black list entries */
    if(rdlPrm.rdlBlMod EQ BL_DELETE)
    {
      cc_blacklist_ptr->blCount = 0;
    }
    return AT_CMPL;   
  }
  else
  {/* redial mode switched OFF */
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
}
#endif /* TI_PS_FF_AT_P_CMD_RDLB */

#ifdef TI_PS_FF_AT_P_CMD_CUSCFG
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCQ                  |
| STATE   : code                  ROUTINE : sAT_PercentCUSCFG          |
+--------------------------------------------------------------------+

  PURPOSE : This is the functional counterpart to the AT%CUSCFG set command
            which sets the customization state of the facility specified.

*/
GLOBAL T_ACI_RETURN sAT_PercentCUSCFG(T_ACI_CMD_SRC srcId, 
                                        T_ACI_CUSCFG_FAC facility,
                                        T_ACI_CUSCFG_MOD mode,
                                        CHAR  *        value)
{
  TRACE_FUNCTION ("sAT_PercentCUSCFG ()");

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

  switch(facility)
  {
  case CUSCFG_FAC_MO_SM_Control:
    cuscfgParams.MO_SM_Control_SIM = mode;
    break;

  case CUSCFG_FAC_MO_Call_Control:
    cuscfgParams.MO_Call_Control_SIM = mode;
    break;

  case CUSCFG_FAC_MO_SS_Control:
    cuscfgParams.MO_SS_Control_SIM = mode;
    break;

  case CUSCFG_FAC_MO_USSD_Control:
    cuscfgParams.MO_USSD_Control_SIM = mode;
    break;

  case CUSCFG_FAC_2_Digit_Call:
    cuscfgParams.Two_digit_MO_Call = mode;
    break;

  case CUSCFG_FAC_Ext_USSD_Res:
    cuscfgParams.Ext_USSD_Response = mode;
    break;

  case CUSCFG_FAC_T_MOBILE_Eons:
    cuscfgParams.T_MOBILE_Eons  = mode;
    break;

  case CUSCFG_FAC_USSD_As_MO_Call:
    cuscfgParams.USSD_As_MO_Call = mode;
    break;

  default:
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
  return(AT_CMPL);
}
#endif /* TI_PS_FF_AT_P_CMD_CUSCFG */

/* Implements Measure 80 */
/*
+------------------------------------------------------------------------------
|  Function    : cmhCC_check_RedialCall
+------------------------------------------------------------------------------
|  Purpose     : Checks for a Redial Call. 
|
|  Parameters  : at_cmd_id - AT Command Identifier.
|                            (AT_CMD_H OR AT_CMD_CHUP)
|
|  Return      : BOOL
+------------------------------------------------------------------------------
*/

LOCAL BOOL cmhCC_check_RedialCall( T_ACI_AT_CMD at_cmd_id )
{
  SHORT cId;
  int i;
  
  TRACE_FUNCTION ("cmhCC_check_RedialCall()");
  
  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_ACT_REQ, CT_MOC_RDL);

  if( cId NEQ NO_ENTRY )
  {
#ifdef SIM_TOOLKIT
    if( ( ccShrdPrm.ctb[cId]->SATinv & SAT_REDIAL ) )
    { /* This is the call invoked by SAT */
      T_ACI_SAT_TERM_RESP resp_data;
      psaSAT_InitTrmResp( &resp_data );
      psaSAT_SendTrmResp( RSLT_USR_CLR_DWN, &resp_data );
    }
#endif /* SIM_TOOLKIT */

    ccShrdPrm.ctb[cId]->calType = CT_MOC;

    if(rdlPrm.rdlMod EQ AUTOM_REPEAT_ON)
    {
      for(i = 0; i < CMD_SRC_MAX; i++)
      {
        R_AT(RAT_RDL, (T_ACI_CMD_SRC)i)(REDIAL_STOP);
      }
      rdlPrm.rdlcId = NO_ENTRY;
    }
    if (at_cmd_id EQ AT_CMD_H)
    {
      ccShrdPrm.ctb[cId]->nrmCs  = MNCC_CAUSE_CALL_CLEAR;
      psaCC_ClearCall (cId);
      psaCC_FreeCtbNtry (cId);
      return( TRUE );
    } 
  }
  else
  {/* redial timer is running */
    if ((rdlPrm.rdlMod EQ AUTOM_REPEAT_ON) AND (rdlPrm.rdlcId NEQ NO_ENTRY))
    {
#ifdef SIM_TOOLKIT
        if( ( ccShrdPrm.ctb[rdlPrm.rdlcId]->SATinv & SAT_REDIAL ) )
        { /* This is the call invoked by SAT */
          T_ACI_SAT_TERM_RESP resp_data;

          psaSAT_InitTrmResp( &resp_data );
          psaSAT_SendTrmResp( RSLT_USR_CLR_DWN, &resp_data );
        }
        /* Stop the SAT maximum duration timer */
        if(satShrdPrm.dur)
        {
          TIMERSTOP(ACI_SAT_MAX_DUR_HND);
          satShrdPrm.dur  = -1;
        }
#endif /* SIM_TOOLKIT */
      /* clear call id entry in call table if marked as used */
      psaCC_FreeCtbNtry (rdlPrm.rdlcId);

      for(i = 0; i < CMD_SRC_MAX; i++)
      {
        R_AT(RAT_RDL, (T_ACI_CMD_SRC)i)(REDIAL_STOP);
      }
      /* reset some redial parameter */
      rdlPrm.rdlcId =   NO_ENTRY;
      return( TRUE );
    }
  }
  return( FALSE );
}

/*
+------------------------------------------------------------------------------
|  Function    : cmhCC_check_pending_satCall()
+------------------------------------------------------------------------------
|  Purpose     : Checks for a Redial Call. 
|
|  Parameters  : None
|
|  Return      : BOOL
+------------------------------------------------------------------------------
*/
LOCAL BOOL cmhCC_check_pending_satCall( )
{
  SHORT cId;                  /* holds call id */
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;      /* holds logging info */
#endif
  /* triggered by SETUP CALL command */
  cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_REQ, NO_VLD_CT );
#ifdef FF_SAT_E
  if( cId EQ NO_ENTRY )
  {
    /* triggered by OPEN CHANNEL command */
    cId = psaCC_ctbFindCall( OWN_SRC_INV, CS_SAT_CSD_REQ, NO_VLD_CT );
  }
#endif
  if( cId NEQ NO_ENTRY )
  {
    if( ( ccShrdPrm.ctb[cId]->SATinv & SAT_REDIAL ) )
    { /* This is the call invoked by SAT */
      T_ACI_SAT_TERM_RESP resp_data;
      psaSAT_InitTrmResp( &resp_data );
      psaSAT_SendTrmResp( RSLT_USR_CLR_DWN, &resp_data );
    }
    if( psaCC_ctb(cId)->SATinv ) 
      cmhSAT_UserRejCall(psaCC_ctb(cId)->calStat);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
    cmdLog.cId = cId+1;
    cmdLog.retCode = AT_CMPL;
    rAT_PercentCLOG( &cmdLog );
#endif
    psaCC_FreeCtbNtry (cId);
    return( TRUE );
  }
  #if defined (GPRS) AND defined (FF_SAT_E) AND defined (DTI)
  /* check for pending SAT GPRS context */
  else
  {
    if( cmhSAT_OpChnGPRSPend(PDP_CONTEXT_CID_INVALID, OPCH_WAIT_CNF))
    {
      cmhSAT_UserRejCntxt();

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
      cmdLog.cId = cId+1;
      cmdLog.retCode = AT_CMPL;
      rAT_PercentCLOG( &cmdLog );
#endif
      return( TRUE );
    }
  }
#endif  /* GPRS AND FF_SAT_E */
  psaCC_FreeCtbNtry (cId);
  return( FALSE );
}

/* Implements Measure 181 and 182 */
/*
+------------------------------------------------------------------------------
|  Function    : chld_HoldActiveCalls
+------------------------------------------------------------------------------
|  Purpose     : Puts All Active Calls on Hold.
|
|  Parameters  : srcId - AT command source identifier.
|                mptyHldFlg - Points to a Flag that Helds a Call 
|                hldCalFlg  - Points to a Flag that Helds a MultiParty Call
|                cId       - context Id 
|
|  Return      : BOOL
+------------------------------------------------------------------------------
*/

LOCAL BOOL chld_HoldActiveCalls( T_ACI_CMD_SRC srcId,
                                 BOOL *mptyHldFlg, BOOL *hldCalFlg, SHORT *cId)
{
  T_CC_CMD_PRM *pCCCmdPrm;
  
  TRACE_FUNCTION("chld_HoldActiveCalls()");

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;
  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  for( *cId = 0; *cId < MAX_CALL_NR; (*cId)++ )
  {
    if (ccShrdPrm.ctb[*cId] NEQ NULL AND
        ccShrdPrm.ctb[*cId]->calStat    EQ CS_ACT AND
        ccShrdPrm.ctb[*cId]->curCmd     EQ AT_CMD_NONE)
    {
      if( cmhCC_getcalltype(*cId) NEQ VOICE_CALL )
      {
        pCCCmdPrm -> mltyCncFlg = 0;
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_CallTypeNoHold );
        return( FALSE ); /* no data calls supported */
      }

      if( (ccShrdPrm.ctb[*cId]->mptyStat EQ CS_IDL) OR
          ((ccShrdPrm.ctb[*cId]->mptyStat EQ CS_ACT) AND ((*mptyHldFlg) EQ FALSE)))
      {
        *hldCalFlg = TRUE;
      }

      /* if active call is a multiparty call */
      if( ccShrdPrm.ctb[*cId]->mptyStat EQ CS_ACT )
      {
        *mptyHldFlg = TRUE;
      }

      cmhCC_HoldCall(*cId, srcId, AT_CMD_CHLD);
    }
  }
  return( TRUE );
}

/* Implements Measure 117 */
/*
+------------------------------------------------------------------------------
|  Function    : chld_Rel_MultipartySpec
+------------------------------------------------------------------------------
|  Purpose     : Releases a Specific Multi Party Calls
|
|  Parameters  : srcId - AT command source identifier.
|                spcId - Holds specified call id.
|                chld_mode - CHLD Command Mode.
|                            (CHLD_MOD_RelAnySpec OR CHLD_MOD_RelActSpec)
|                call
|
|  Return      : T_ACI_RETURN (ACI Functional Return Codes)
+------------------------------------------------------------------------------
*/

LOCAL T_ACI_RETURN chld_Rel_MultipartySpec( T_ACI_CMD_SRC srcId, SHORT *spcId,
                                            T_ACI_CHLD_MOD chld_mode,
                                            CHAR *call )
{
  T_CC_CMD_PRM *pCCCmdPrm;
  SHORT cId;
  SHORT dscId = -1;

  TRACE_FUNCTION( "chld_Rel_MultypartySpec()" );

  pCCCmdPrm = &cmhPrm[srcId].ccCmdPrm;

  /* get specific call id */
  if( call EQ NULL )
  {
    TRACE_ERROR("CALL parameter is needed !!!");
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );  /* no call specified */
  }

  *spcId = atoi( call );

  if( (*spcId) EQ 0 OR (*spcId) > MAX_CALL_NR )
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }

  (*spcId)--;  /* adapt to call table index */

  pCCCmdPrm -> mltyCncFlg = 0;
  pCCCmdPrm -> mltyDscFlg = 0;

  if( (*spcId) EQ -1 )
  {
    for( cId = 0; cId < MAX_CALL_NR; cId++ )
    {
      if (ccShrdPrm.ctb[cId] NEQ NULL AND
          psaCC_ctb(cId)->mptyStat   EQ CS_ACT AND
          psaCC_ctb(cId)->curCmd     EQ AT_CMD_NONE)
      {
        psaCC_StopDTMF (cId);

        cmhCC_ClearCall ( cId, MNCC_CAUSE_CALL_CLEAR, srcId, AT_CMD_CHLD, NULL );
        dscId = cId;
      }
    }

    if( dscId NEQ -1 )
    {
      pCCCmdPrm -> CHLDmode = chld_mode;
      CHLDaddInfo           = NO_CHLD_ADD_INFO;

      /* inform MFW */
      chld_ratlog( srcId, pCCCmdPrm->CHLDmode, call, CHLD_ACT_ReleaseMpty, dscId, AT_EXCT );
      return( AT_EXCT );
    }
    ACI_ERR_DESC( ACI_ERR_CLASS_Cme, CME_ERR_OpNotAllow );
    return(AT_FAIL);
  }
  return(AT_CMPL);
}

/* Implements Measure 164 and 165 */
/*
+------------------------------------------------------------------------------
|  Function    : cmhCC_disconnect_waiting_call
+------------------------------------------------------------------------------
|  Purpose     : Disconnect a waiting call with user determined user busy
|
|  Parameters  : waitId     - Holds call waiting id.
|                at_cmd_id  - AT Command Identifier.
|                             (AT_CMD_H/AT_CMD_CHUP/AT_CMD_Z)
|                mltyDscFlg - Flag for MultiCall Operation
|
|  Return      : void
+------------------------------------------------------------------------------
*/

LOCAL void cmhCC_disconnect_waiting_call( T_ACI_CMD_SRC srcId,
                                          SHORT waitId,
                                          T_ACI_AT_CMD at_cmd_id,
                                          USHORT *mltyDscFlg )
{
  UBYTE          idx;
#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  T_ACI_CLOG     cmdLog;
#endif

  TRACE_FUNCTION ("cmhCC_disconnect_waiting_call()");

  cmhCC_flagCall( waitId, mltyDscFlg );
  ccShrdPrm.ctb[waitId]->nrmCs  = MNCC_CAUSE_USER_BUSY;
  ccShrdPrm.ctb[waitId]->curCmd = at_cmd_id;
  ccShrdPrm.ctb[waitId]->curSrc = srcId;
  psaCC_ClearCall (waitId);

#if defined SMI OR defined MFW OR defined FF_MMI_RIV
  cmdLog.cId = waitId+1;
  rAT_PercentCLOG( &cmdLog );
#endif

#ifdef FF_ATI
  io_setRngInd (IO_RING_OFF, CRING_SERV_TYP_NotPresent, CRING_SERV_TYP_NotPresent ); /* V.24 Ring Indicator Line */
#endif
  for( idx = 0; idx < CMD_SRC_MAX; idx++ )
  {
    R_AT( RAT_CRING_OFF, (T_ACI_CMD_SRC)idx )( waitId+1 );
  }
}

/* Implements Measure 64 */
/*
+------------------------------------------------------------------------------
|  Function    : cmhCC_CheckRedialTimer
+------------------------------------------------------------------------------
|  Purpose     : Checks the Redial Timer and Stops it, if neccessary
|
|  Parameters  : sim_toolkit_enable 
|
|  Return      : void
+------------------------------------------------------------------------------
*/

GLOBAL void cmhCC_CheckRedialTimer( BOOL sim_toolkit_enable )
{
  int i;

  TRACE_FUNCTION ( "cmhCC_CheckRedialTimer()" );

  /* stop redialling timer if necessary */
  if (rdlPrm.rdlcId NEQ NO_ENTRY)
  {
    TIMERSTOP(ACI_REPEAT_HND);

#ifdef SIM_TOOLKIT
    if( sim_toolkit_enable )
    {
      if( ( ccShrdPrm.ctb[rdlPrm.rdlcId]->SATinv & SAT_REDIAL ) )
      { /* This is the call invoked by SAT */
        T_ACI_SAT_TERM_RESP resp_data;

        psaSAT_InitTrmResp( &resp_data );
        psaSAT_SendTrmResp( RSLT_USR_CLR_DWN, &resp_data );
      }
      /* Stop SAT maximum redial duration timer */
      if(satShrdPrm.dur)
      {
        TIMERSTOP(ACI_SAT_MAX_DUR_HND);
        satShrdPrm.dur  = -1;
      }
    }
#endif /* SIM_TOOLKIT */

    psaCC_FreeCtbNtry (rdlPrm.rdlcId);  

    for(i = 0; i < CMD_SRC_MAX; i++)
    {
      R_AT(RAT_RDL, (T_ACI_CMD_SRC)i)(REDIAL_STOP);
    }

    /* reset some redial parameter */
    rdlPrm.rdlcId =   NO_ENTRY;
  }

}

#ifdef TI_PS_FF_AT_CMD_P_ECC
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                  |
| STATE   : code                  ROUTINE : sAT_PercentECC           |
+--------------------------------------------------------------------+
|  Description  : This is the functional counterpart to the AT%ECC 
|                 set command which sets additional ECC to local array
|                  in ACI
|  Parameters   : <srcId>     : Source Id
|                 <index>     : Index
|                 <ecc_numer> : ECC number to be stored
|
|  Return       : T_ACI_RETURN
+---------------------------------------------------------------------
*/

GLOBAL T_ACI_RETURN sAT_PercentECC( T_ACI_CMD_SRC srcId,
                                    U8 index,
                                    char *ecc_number)
{
  TRACE_FUNCTION ("sAT_PercentECC ()");

  /*
   *-------------------------------------------------------------------
   * check command source
   *-------------------------------------------------------------------
   */
  if(!cmh_IsVldCmdSrc (srcId))
  {
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
  /*
   *-------------------------------------------------------------------
   * check for valid index
   *-------------------------------------------------------------------
   */
  if (index >= ADDITIONAL_ECC_NUMBER_MAX)
  {
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme, CME_ERR_InvIdx);
    return( AT_FAIL );
  }
  /*
   *-------------------------------------------------------------------
   * check for valid length of ECC number
   *-------------------------------------------------------------------
   */
  if ((!strlen(ecc_number)) OR (strlen(ecc_number) > ADDITIONAL_ECC_NUMBER_LENGTH)) 
  {
    ACI_ERR_DESC(ACI_ERR_CLASS_Cme, CME_ERR_TxtToLong);
    return( AT_FAIL );
  }
  
  strncpy(additional_ecc_numbers[index], ecc_number, strlen(ecc_number));
  return(AT_CMPL);
}

/*
+-----------------------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                                 |
| STATE   : code                  ROUTINE : cmhCC_additional_ecc_numbers_initialize |
+-----------------------------------------------------------------------------------+
|  Description  : Initializes array which stores ECC numbers to default values
|
|  Parameters   : void
|  Return       : void
+------------------------------------------------------------------------------------
*/

GLOBAL void cmhCC_additional_ecc_numbers_initialize(void)
{
  TRACE_FUNCTION("cmhCC_additional_ecc_numbers_initialize()");
  //memset(additional_ecc_numbers, 0x00, ADDITIONAL_ECC_NUMBER_MAX*(ADDITIONAL_ECC_NUMBER_LENGTH));
  memset(additional_ecc_numbers, 0x00, ADDITIONAL_ECC_NUMBER_MAX*(ADDITIONAL_ECC_NUMBER_LENGTH+1)); //OMAPS00117704/OMAPS00117705
}

/*
+---------------------------------------------------------------------------+
| PROJECT : GSM-PS (6147)         MODULE  : CMH_CCS                         |
| STATE   : code                  ROUTINE : cmhCC_isNrInAdditionalECC       |
+---------------------------------------------------------------------------+
|  Description  : Checks the passed number with additional ECC numbers
|
|  Parameters   : <number> : Dialed number
|  Return       : BOOL
+----------------------------------------------------------------------------
*/

GLOBAL BOOL cmhCC_isNrInAdditionalECC(char *number)
{
  U8 idx;

  TRACE_FUNCTION("cmhCC_isNrInAdditionalECC()");

  for (idx=0; idx < ADDITIONAL_ECC_NUMBER_MAX; idx++) 
  {
    if (!strcmp(number, additional_ecc_numbers[idx]))
    {
      return (TRUE);
    }
  }
  return (FALSE);
}
#endif /* TI_PS_FF_AT_CMD_P_ECC */

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

  PURPOSE : This is a set call for +CVHU for the control of the voice 
  hangup
  
*/
GLOBAL T_ACI_RETURN sAT_PlusCVHU ( T_ACI_CMD_SRC srcId, T_ACI_CVHU_MODE mode)
{
  TRACE_FUNCTION("sAT_PlusCVHU()");

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

  switch(mode)
  {
  case CVHU_DropDTR_IGNORED:
  case CVHU_DropDTR_ATH_IGNORED:
  case CVHU_DropDTR_Same_AndD:
    ccShrdPrm.cvhu = mode;
    return(AT_CMPL);
  default:
    ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Parameter );
    return( AT_FAIL );
  }
}
/*==== EOF ========================================================*/