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

#if defined (GPRS) && defined (DTI)

#ifndef CMH_SMR_C
#define CMH_SMR_C
#endif

#include "aci_all.h"
/*==== INCLUDES ===================================================*/
#include "dti.h"      /* functionality of the dti library */
#include "aci_cmh.h"
#include "ati_cmd.h"
#include "aci_cmd.h"

#include "aci.h"

#include "dti_conn_mng.h"
#include "dti_cntrl_mng.h"

#include "gaci.h"
#include "gaci_cmh.h"
#include "psa.h"
#include "psa_sm.h"
#include "psa_gppp.h"

#include "cmh.h"
#include "cmh_sm.h"
#include "cmh_gppp.h"
#include "gaci_srcc.h"
#include "psa_uart.h"

#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
#include "wap_aci.h"
#include "psa_tcpip.h"

#include "psa_cc.h"
#include "cmh_cc.h"
#include "psa_sat.h"
#include "cmh_sat.h"

#include "dcm_f.h"
#endif /* (CO_UDP_IP) || defined (FF_GPF_TCPIP) */

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


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


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

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

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


static void dumpContextInfo(SHORT cid)
{
  TRACE_EVENT_P2("ERROR in context state: cid %d, state %d", 
                cid, pdp_context[cid-1].state);
  TRACE_EVENT_P3("dump: nsapi %d, srcID %d, connected entity %d", 
                  pdp_context[cid-1].nsapi, pdp_context[cid-1].owner,
                  pdp_context[cid-1].entity_id);
  if(smEntStat.curCmd NEQ AT_CMD_NONE)
  {
    TRACE_EVENT_P1("dump running command: %d", smEntStat.curCmd); 
  }
  TRACE_EVENT_P3("dump link_ids: new %d sn %d uart %d", 
      pdp_context[cid-1].link_id_new, pdp_context[cid-1].link_id_sn,
      pdp_context[cid-1].link_id_uart); 
}

#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
static BOOL is_ip_dti_id(T_DTI_ENTITY_ID dti_id)
{
  if(is_gpf_tcpip_call()) {
    GPF_TCPIP_STATEMENT(return dti_id EQ DTI_ENTITY_TCPIP);
  }
  else {
    return dti_id EQ DTI_ENTITY_IP;
  }
}
#endif

static void get_dns_address(char* dns1, char *dns2, UBYTE *pco, UBYTE len)
{
  ULONG tmp_dns1, tmp_dns2, gateway;
  utl_analyze_pco(pco,len, &tmp_dns1, &tmp_dns2, &gateway);

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

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finished         ROUTINE : cmhSM_Activated              |
+-------------------------------------------------------------------+

  PURPOSE : confirms a successful context activation

*/
GLOBAL SHORT cmhSM_Activated ( T_SMREG_PDP_ACTIVATE_CNF *pdp_cnf )
{
  T_CGEREP_EVENT_REP_PARAM  event;
  char dns1[16], dns2[16];
  SHORT _cid = work_cids[cid_pointer] - 1;
  T_ACI_AT_CMD curCmd = smEntStat.curCmd;
  UBYTE ip[4];
  int i = 0;

  TRACE_FUNCTION ("cmhSM_Activated()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( get_state_working_cid() )
  {
    case( CS_ACTIVATING ):

      R_AT( RAT_CGACT, smEntStat.entOwn )(pdp_context[_cid].link_id_new);

      set_state_working_cid( CS_ACTIVATED );

      dti_cntrl_entity_connected( pdp_context[_cid].link_id_new, DTI_ENTITY_SNDCP, DTI_OK );
      pdp_context[_cid].link_id_sn = pdp_context[_cid].link_id_new;
      pdp_context[_cid].link_id_new = DTI_LINK_ID_NOTPRESENT;

      sprintf(pdp_context[_cid].allocated_pdp_addr, "%03hd.%03hd.%03hd.%03hd",
                pdp_cnf->pdp_address.buff[0],
                pdp_cnf->pdp_address.buff[1],
                pdp_cnf->pdp_address.buff[2],
                pdp_cnf->pdp_address.buff[3] );

      cmhSM_set_PCO((SHORT)(_cid + 1), PCO_NETWORK,
                                &pdp_cnf->sdu.buf[pdp_cnf->sdu.o_buf >> 3],
                                (UBYTE) (pdp_cnf->sdu.l_buf >> 3));

      get_dns_address(dns1, dns2,
                      (UBYTE*)pdp_context[_cid].network_pco.pco,
                      pdp_context[_cid].network_pco.len);

      TRACE_EVENT_P3("PDP Address: %s, DNS1: %s, DNS2: %s",
                     pdp_context[_cid].allocated_pdp_addr,dns1,dns2);

#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
      /* if WAP/TCPIP over GPRS is in progress, request WAP configuration */
      if ( is_ip_dti_id(pdp_context[_cid].entity_id) )
      {
        psaTCPIP_Configure(NULL, pdp_context[_cid].allocated_pdp_addr,
                           NULL, (UBYTE*)dns1, (UBYTE*)dns2, 1500, 
                           cmhSM_IP_activate_cb );
      }
#endif /* (CO_UDP_IP) || defined (FF_GPF_TCPIP) */

      /*
       *  do we need one more context activation
       */
      if ( FALSE EQ cmhSM_next_work_cid( curCmd ) )
      {
        if( AT_CMD_CGACT EQ curCmd)
        {
          gaci_RAT_caller ( RAT_OK, (SHORT) (_cid + 1), (UBYTE) curCmd, 0 );

          /* log result */
          cmh_logRslt ( pdp_context[_cid].owner, RAT_OK, curCmd, -1, -1, -1 );
        }
      }
      break;

    case( CS_ESTABLISH_2 ):
    /*
     *---------------------------------------------------------------
     * inform PPP
     *---------------------------------------------------------------
     */
      cmhSM_set_PCO((SHORT)(_cid + 1), PCO_NETWORK,
                                &pdp_cnf->sdu.buf[pdp_cnf->sdu.o_buf >> 3],
                                (UBYTE) (pdp_cnf->sdu.l_buf >> 3));

      sprintf(pdp_context[_cid].allocated_pdp_addr, "%03hd.%03hd.%03hd.%03hd",
                pdp_cnf->pdp_address.buff[0],
                pdp_cnf->pdp_address.buff[1],
                pdp_cnf->pdp_address.buff[2],
                pdp_cnf->pdp_address.buff[3] );
      
      cmhSM_pdp_address_to_ip(&pdp_context[_cid].allocated_pdp_addr, ip);

      psaGPPP_PDP_Activate(pdp_cnf->ppp_hc, pdp_cnf->msid, ip,
                                          &pdp_cnf->sdu.buf[pdp_cnf->sdu.o_buf >> 3], 
                                          (UBYTE) (pdp_cnf->sdu.l_buf >> 3));

      set_state_working_cid( CS_ESTABLISH_3 );

      dti_cntrl_entity_connected( pdp_context[_cid].link_id_new, DTI_ENTITY_SNDCP, DTI_OK );

      pdp_context[_cid].link_id_sn = pdp_context[_cid].link_id_new;
      pdp_context[_cid].link_id_new = DTI_LINK_ID_NOTPRESENT;

      break;
      
    default:
      return -1;
  }
  
  /*
  *   %CGEV - GPRS event reporting
  */
  strcpy(event.act.pdp_type, pdp_context[_cid].con.pdp_type);
  strcpy(event.act.pdp_addr, pdp_context[_cid].allocated_pdp_addr);
  event.act.cid      = _cid + 1;
  
  if (smShrdPrm.direc == DIREC_MO)
  {
    for( i = 0; i < CMD_SRC_MAX; i++ )
    {
        R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_ME_ACT, &event );
    }
  }
  else
  {
    for( i = 0; i < CMD_SRC_MAX; i++ )
    {
        R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_NW_ACT, &event );
    }
  }

  return 0;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finished         ROUTINE :                              |
+-------------------------------------------------------------------+

  PURPOSE : 

*/

LOCAL void cp_pdp_rej_prim(T_SMREG_PDP_ACTIVATE_REJ * pdp_activate_rej,
                           T_PPP_PDP_ACTIVATE_REJ *activate_result)
{
 
  activate_result->ppp_cause = pdp_activate_rej->smreg_cause;

}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finished         ROUTINE : cmhSM_NoActivate             |
+-------------------------------------------------------------------+

  PURPOSE : indicates a context activation failed

*/
GLOBAL SHORT cmhSM_NoActivate ( void )
{
  T_CGEREP_EVENT_REP_PARAM  event;
  T_CONTEXT_STATE   state;
  T_DTI_CONN_LINK_ID link_id;
  int i = 0;
 
  TRACE_FUNCTION ("cmhSM_NoActivate()");
/*
 *-------------------------------------------------------------------
 * Set error cause for SIM owner
 *-------------------------------------------------------------------
 */
#ifdef FF_SAT_E
  gaci_SAT_err(smShrdPrm.pdp_rej->smreg_cause);
#endif /* FF_SAT_E */
/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */
  switch( state = get_state_working_cid() )
  {
    case CS_UNDEFINED:
    case CS_DEFINED:
    case CS_ESTABLISH_1:
    case CS_ESTABLISH_3:
    case CS_ACTIVATED:
    case CS_WAITS_FOR_ACTIVATING:
    case CS_DATA_LINK:
    case CS_DEACTIVATE_NORMAL:
    case CS_CONTEXT_REACTIVATION_1:
    case CS_CONTEXT_REACTIVATION_2:
    case CS_BREAKDOWN_LINK_ERROR:
    case CS_BREAKDOWN_LINK_NORMAL:
      dumpContextInfo(work_cids[cid_pointer]);
      return 0;
    case CS_ACTIVATING:
      link_id = cmhSM_get_link_id_SNDCP_peer(work_cids[cid_pointer], SNDCP_PEER_NORMAL);

      switch(pdp_context[work_cids[cid_pointer] - 1].entity_id)
      {
        case DTI_ENTITY_PKTIO:
        case DTI_ENTITY_PSI:          
          set_state_working_cid( CS_DEACTIVATE_NORMAL);
          dti_cntrl_close_dpath_from_dti_id (EXTRACT_DTI_ID(link_id));
/*          gaci_RAT_caller(RAT_NO_CARRIER, work_cids[cid_pointer], AT_CMD_CGDATA, 0); */
          break;
#if defined (CO_UDP_IP) OR defined (FF_GPF_TCPIP)
        case DTI_ENTITY_IP:
        GPF_TCPIP_STATEMENT(case DTI_ENTITY_TCPIP:)
          set_state_working_cid( CS_DEFINED);
          dti_cntrl_close_dpath_from_dti_id (EXTRACT_DTI_ID(link_id));
          /* tell WAP ACI that contextactivation was rejected */
          psaTCPIP_Deactivate(cmhSM_IP_activate_cb);
          dti_cntrl_entity_disconnected( link_id, DTI_ENTITY_SNDCP );
          break;
#endif /* WAP OR FF_SAT_E OR FF_GPF_TCPIP */          
        default:
          /* in this case is SMREG_PDP_ACTIVATE_REJ the same as SMREG_DEACTIVATE_CNF */

          /* set parameter for SMREG_DEACTIVATE_CNF */
          smShrdPrm.nsapi_set = 1 << smShrdPrm.pdp_rej->smreg_nsapi;
          cmhSM_Deactivated(); /* SMREG_DEACTIVATE_CNF */
     
          /* the last expected primitive from SM */
          smEntStat.curCmd = AT_CMD_NONE;
          return 0;
      }

     /*
      *   GPRS event reporting
      */
      strcpy(event.act.pdp_type, pdp_context[work_cids[cid_pointer] - 1].con.pdp_type);
      strcpy(event.act.pdp_addr, pdp_context[work_cids[cid_pointer] - 1].allocated_pdp_addr);
      event.act.cid = work_cids[cid_pointer];
      for( i = 0; i < CMD_SRC_MAX; i++ )
      {
        R_AT( RAT_CGEREP, i ) ( CGEREP_EVENT_ME_DEACT, &event );
        R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_ME_DEACT, &event );
      }

      cmhSM_GiveNSapiFree(work_cids[cid_pointer]);
      cmhSM_contextDeactivated();  
      break;
    case CS_ESTABLISH_2:
    case CS_ABORT_ESTABLISH:
      /* in this case is SMREG_PDP_ACTIVATE_REJ the same as SMREG_DEACTIVATE_CNF */

      /* set parameter for SMREG_DEACTIVATE_CNF */
      smShrdPrm.nsapi_set = 1 << smShrdPrm.pdp_rej->smreg_nsapi;

      cmhSM_Deactivated(); /* SMREG_DEACTIVATE_CNF */
     
      /* the last expected primitive from SM */
      smEntStat.curCmd = AT_CMD_NONE;

      if ( state NEQ CS_ESTABLISH_2)
      {
        return 0;
      }

     /*
     *---------------------------------------------------------------
     * inform PPP
     *---------------------------------------------------------------
     */
      {
        PALLOC(act_rej_temp,PPP_PDP_ACTIVATE_REJ); /* ppass*/
        cp_pdp_rej_prim(smShrdPrm.pdp_rej,act_rej_temp);
        gpppShrdPrm.setPrm[gpppEntStat.entOwn].pdp_rej = act_rej_temp;
      }

      if( psaGPPP_PDP_Reject() < 0 )
      {
        TRACE_EVENT( "FATAL RETURN psaPPP_PDP_Reject in +CGDATA" );
        ACI_ERR_DESC( ACI_ERR_CLASS_Ext, EXT_ERR_Internal );
        return -1 ;
      }

      set_state_working_cid( CS_ABORT_ESTABLISH );
      break;
    default:
      return -1;
  }

  return 0;
}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finished         ROUTINE : cmhSM_NetActivate            |
+-------------------------------------------------------------------+

  PURPOSE : indicates a network asked for a PDP context activation

*/
GLOBAL void cmhSM_NetActivate ( void )
{
  T_CGEREP_EVENT_REP_PARAM  event;
  SHORT i = 0,                            /* holds index  counter */
        context_reactivation = 0, cid;

  TRACE_FUNCTION ("cmhSM_NetActivate()");

  /*
   *  in first only one requested context activation is provided
   *  and the request will be rejected if an other context will be
   *  activated
   */

  /*
   *  it's no check to CC neccesary, because this is no class A mobile
   */

  if ( TRUE EQ cmhSM_is_smreg_ti_used( smShrdPrm.act_ind.smreg_ti, &cid ) )
    context_reactivation = 1;

  /*
   *  no PDP context is during the setup
   */
  if ( work_cids[cid_pointer] EQ INVALID_CID                      &&
       gprs_ct_index < MAX_GPRS_CALL_TABLE_ENTRIES                &&
       ( TRUE EQ srcc_reserve_sources( SRCC_PPPS_SNDCP_LINK, 1 )  ||
         context_reactivation EQ 1)                                   )
  {
/*
 *-------------------------------------------------------------------
 * ring for call, if no call is in use
 *-------------------------------------------------------------------
 */

#ifdef AT_INTERPRETER
    /* V.24 Ring Indicator Line */
    /* io_setRngInd ( IO_RS_ON, CRING_TYP_NotPresent, CRING_TYP_NotPresent dummy parameters here, need real ones when used); */
#endif

    /* fill gprs call table */
    memcpy(&gprs_call_table[gprs_ct_index].sm_ind, &smShrdPrm.act_ind, sizeof(T_SMREG_PDP_ACTIVATE_IND));

    /* no context reactivation */
    if ( context_reactivation NEQ 1 )
    {
      gprs_call_table[gprs_ct_index].reactivation = GCTT_NORMAL;
      *gprs_call_table[gprs_ct_index].L2P = 0;
      gprs_call_table[gprs_ct_index].cid = INVALID_CID;
      gprs_ct_index++;

      for( i = 0 ; i < CMD_SRC_MAX; i++ )
      {
        R_AT( RAT_CRING, i )  ( CRING_MOD_Gprs, CRING_TYP_GPRS, CRING_TYP_NotPresent );
      }
    }
    else
    { /* context reactivation */
      gprs_call_table[gprs_ct_index].reactivation = GCTT_REACTIVATION ;
      strcpy(gprs_call_table[gprs_ct_index].L2P, "PPP");
      gprs_call_table[gprs_ct_index].cid    = cid;
      gprs_ct_index++;
    }

  }
  else
  /*
   *  one or more PDP contexts are during the setup
   */
  {
    psaSM_PDP_No_activate(smShrdPrm.act_ind.smreg_ti, SMREG_RC_INSUF_RES);

   /*
    *   GPRS event reporting
    */
    cmhSM_pdp_typ_to_string(smShrdPrm.act_ind.pdp_type, event.reject.pdp_type);
    memcpy(&event.reject.pdp_addr,
           &smShrdPrm.act_ind.pdp_address.buff,
           smShrdPrm.act_ind.pdp_address.c_buff);
    for( i = 0; i < CMD_SRC_MAX; i++ )
    {
      R_AT( RAT_CGEREP, i ) ( CGEREP_EVENT_REJECT, &event );
      R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_REJECT, &event );
    }
  }
}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finnished        ROUTINE : cmhSM_Deactivated            |
+-------------------------------------------------------------------+

  PURPOSE : confirms a successful PDP context deactivation

*/
GLOBAL void cmhSM_Deactivated ( void )
{
  T_CGEREP_EVENT_REP_PARAM  event;
  T_CONTEXT_STATE           state;
  SHORT                     cid, 
                            i, 
                            reactivation = 0,
                            rat_id = RAT_MAX;
  UBYTE                     cme_err = CME_ERR_GPRSUnspec, /* error number */
                            cmdBuf = smEntStat.curCmd;    /* buffers current command */
  USHORT                    temp_nsapiSet = smShrdPrm.nsapi_set;
  T_DTI_CONN_LINK_ID        dti_id_sn;
  UBYTE srcId = srcId_cb;
  
  TRACE_FUNCTION ("cmhSM_Deactivated()");

/*
 *-------------------------------------------------------------------
 * check for command context
 *-------------------------------------------------------------------
 */

  while ( CS_INVALID_STATE NEQ (state = get_state_over_nsapi_set( &smShrdPrm.nsapi_set, &cid )) )
  {
    dti_id_sn = cmhSM_get_link_id_SNDCP_peer( cid, SNDCP_PEER_NORMAL );

    switch ( state )
    {
      case CS_UNDEFINED:
      case CS_DEFINED:
      case CS_WAITS_FOR_ACTIVATING:
      case CS_ESTABLISH_1:
      case CS_ESTABLISH_3:
      case CS_ACTIVATED:
      case CS_DATA_LINK:
      default:
        dumpContextInfo(cid);
        continue;
      case CS_ESTABLISH_2:
        set_state_over_cid ( cid, CS_ABORT_ESTABLISH );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        break;
      case CS_ABORT_ESTABLISH:
      case CS_BREAKDOWN_LINK_ERROR:
        TRACE_EVENT("state: CS_BREAKDOWN_LINK_ERROR");
        set_state_over_cid ( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        if(ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Disable)
          rat_id = RAT_NO_CARRIER;
        else
          rat_id = RAT_CME;
        break;
      case CS_BREAKDOWN_LINK_NORMAL:
        TRACE_EVENT("state: CS_BREAKDOWN_LINK_NORMAL");
        set_state_over_cid ( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        rat_id = RAT_NO_CARRIER;
        break;
      case CS_DEACTIVATE_NORMAL:
        TRACE_EVENT("state: CS_DEACTIVATE_NORMAL") ;
        set_state_over_cid ( cid, CS_DEFINED );
#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
        if ( is_ip_dti_id(pdp_context[cid-1].entity_id) )
        {
          /* tell WAP ACI that contextactivation was rejected */
          psaTCPIP_Deactivate(cmhSM_IP_activate_cb);
          dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        }
        else
#endif /* CO_UDP_IP || FF_GPF_TCPIP */
        {
          dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
          cmhSM_disconnect_cid(cid, GC_TYPE_NULL);
        }
        break;
      case CS_ACTIVATING:
        TRACE_EVENT("state: CS_ACTIVATING");
        set_state_over_cid ( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        if(pdp_context[cid - 1].entity_id EQ DTI_ENTITY_NULL)
        {       
          rat_id = RAT_CME;
        }
        cmhSM_disconnect_cid(cid, GC_TYPE_NULL);
        break;
      case CS_CONTEXT_REACTIVATION_1:
        TRACE_EVENT("state: CD_CONTEXT_REACTIVATION_1");
        set_state_over_cid(cid, CS_CONTEXT_REACTIVATION_2);
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        smEntStat.curCmd = AT_CMD_NONE;
        cmhSM_GiveNSapiFree(cid);
        continue;
      case CS_CONTEXT_REACTIVATION_2:
        TRACE_EVENT("state: CD_CONTEXT_REACTIVATION_2");
        set_state_over_cid ( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        smEntStat.curCmd = AT_CMD_NONE;
        rat_id = RAT_NO_CARRIER;
        reactivation = 1;
        break;
    }

    if ( reactivation EQ 0 )
    {
      if ( smEntStat.entOwn EQ get_owner_over_cid(cid) )
        switch( smEntStat.curCmd )
        {
          case( AT_CMD_CGDATA ):
          case( AT_CMD_CGACT ):
            smEntStat.curCmd = AT_CMD_NONE;
            cid_pointer  = 0;
            *work_cids = 0;
        }
    }

   /*
    *   GPRS event reporting
    */
    strcpy(event.act.pdp_type, pdp_context[cid - 1].con.pdp_type);
    strcpy(event.act.pdp_addr, pdp_context[cid - 1].allocated_pdp_addr);
    event.act.cid      = cid;
    for( i = 0; i < CMD_SRC_MAX; i++ )
    {
      R_AT( RAT_CGEREP, i ) ( CGEREP_EVENT_ME_DEACT, &event );
      R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_ME_DEACT, &event );
    }

    cmhSM_GiveNSapiFree(cid);

    if ( rat_id NEQ RAT_MAX )
    {
      gaci_RAT_caller ( rat_id, cid, cmdBuf, cme_err );

      rat_id = RAT_MAX;
      cid_pointer  = 0;
      *work_cids = 0;

      cmhSM_context_reactivation();
    }
  }

  cmhSM_context_deactivated(temp_nsapiSet);
  cmhSM_contextDeactivated();
}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finnished        ROUTINE : cmhSM_NetDeactivate          |
+-------------------------------------------------------------------+

  PURPOSE : indicates a PDP context deactivation

*/
GLOBAL void cmhSM_NetDeactivate ( void )
{
  T_CGEREP_EVENT_REP_PARAM  event;
  T_CONTEXT_STATE           state;
  SHORT                     cid, 
                            i = 0, 
                            inform_ppp = 1, 
                            rat_id = RAT_MAX;
  UBYTE                     cme_err = CME_ERR_Unknown, /* error number */
                            cmdBuf = AT_CMD_NONE;      /* buffers current command */
  USHORT                    temp_nsapiSet = smShrdPrm.nsapi_set;
  T_DTI_CONN_LINK_ID        dti_id_sn;
  UBYTE srcId = srcId_cb;
  
  TRACE_FUNCTION ("cmhSM_NetDeactivate()");

  while ( CS_INVALID_STATE NEQ (state = get_state_over_nsapi_set( &smShrdPrm.nsapi_set, &cid )) )
  {
    dti_id_sn = cmhSM_get_link_id_SNDCP_peer( cid, SNDCP_PEER_NORMAL );

    switch ( state )
    {
      case CS_UNDEFINED:
      case CS_DEFINED:
      case CS_ESTABLISH_1:
      case CS_WAITS_FOR_ACTIVATING:
        continue;
      case CS_ESTABLISH_2:
      case CS_ESTABLISH_3:
        set_state_over_cid( cid, CS_ABORT_ESTABLISH );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        break;
      case CS_ABORT_ESTABLISH:
        set_state_over_cid( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        inform_ppp = 0;
        if(ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Disable)
          rat_id = RAT_NO_CARRIER;
        else
          rat_id = RAT_CME;
        break;
      case CS_BREAKDOWN_LINK_ERROR:
        set_state_over_cid( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        if(ati_user_output_cfg[srcId].CMEE_stat EQ CMEE_MOD_Disable)
          rat_id = RAT_NO_CARRIER;
        else
          rat_id = RAT_CME;
        inform_ppp = 0;
        break;
      case CS_BREAKDOWN_LINK_NORMAL:
        set_state_over_cid( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_disconnect_cid(cid, GC_TYPE_DATA_LINK);
        rat_id = RAT_NO_CARRIER;
        inform_ppp = 0;
        break;
      case CS_DATA_LINK:
        set_state_over_cid( cid, CS_BREAKDOWN_LINK_NORMAL );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        break;
      case CS_ACTIVATED:
        inform_ppp = 0;
        set_state_over_cid( cid, CS_DEFINED );
#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
        if ( is_ip_dti_id(pdp_context[cid-1].entity_id) )
        {
          /* tell WAP ACI that contextactivation was rejected */
          psaTCPIP_Deactivate(cmhSM_IP_activate_cb);
          dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        }
        else
#endif /* CO_UDP_IP || FF_GPF_TCPIP */
        {
          dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
          cmhSM_disconnect_cid(cid, GC_TYPE_NULL);
        }
        break;
      case CS_DEACTIVATE_NORMAL:
        inform_ppp = 0;
        set_state_over_cid( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
        if ( is_ip_dti_id(pdp_context[cid-1].entity_id) )
        {
          /* tell WAP ACI that contextactivation was rejected */
          psaTCPIP_Deactivate(cmhSM_IP_activate_cb);
        }
        else
#endif /* CO_UDP_IP || FF_GPF_TCPIP */
        {
          cmhSM_disconnect_cid(cid, GC_TYPE_NULL);
        }
        break;
      case CS_ACTIVATING:
        inform_ppp = 0;
        set_state_over_cid( cid, CS_DEFINED );
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
#if defined (CO_UDP_IP) || defined (FF_GPF_TCPIP)
        if ( is_ip_dti_id(pdp_context[cid-1].entity_id) )
        {
          /* tell WAP ACI that contextactivation was rejected */
          psaTCPIP_Deactivate(cmhSM_IP_activate_cb);
        }
        else
#endif /* CO_UDP_IP OR FF_GPF_TCPIP */
        {
          cmhSM_disconnect_cid(cid, GC_TYPE_NULL);
        }
        if(pdp_context[cid - 1].entity_id EQ DTI_ENTITY_NULL)
        {
          rat_id = RAT_CME;
        }
        break;
      case CS_CONTEXT_REACTIVATION_1:
        set_state_over_cid(cid, CS_CONTEXT_REACTIVATION_2);
        cmhSM_stop_context_reactivation();
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        cmhSM_GiveNSapiFree(cid);
        continue;
      case CS_CONTEXT_REACTIVATION_2:
        set_state_over_cid( cid, CS_DEFINED );
        cmhSM_stop_context_reactivation();
        dti_cntrl_entity_disconnected( dti_id_sn, DTI_ENTITY_SNDCP );
        rat_id = RAT_NO_CARRIER;
        inform_ppp = 0;
        break;
    }

    if ( inform_ppp )
    {
    /*
     *---------------------------------------------------------------
     * inform PPP
     *---------------------------------------------------------------
     */  
      psaGPPP_Terminate( PPP_LOWER_LAYER_UP );
    }

    if ( smEntStat.entOwn EQ get_owner_over_cid(cid) )
      switch( smEntStat.curCmd )
      {
        case( AT_CMD_CGDATA ):
        case( AT_CMD_CGACT ):
          smEntStat.curCmd = AT_CMD_NONE;
          cid_pointer  = 0;
          *work_cids = 0;
      }

   /*
    *   GPRS event reporting
    */
    strcpy(event.act.pdp_type, pdp_context[cid - 1].con.pdp_type);
    strcpy(event.act.pdp_addr, pdp_context[cid - 1].allocated_pdp_addr);
    event.act.cid      = cid;
    for( i = 0; i < CMD_SRC_MAX; i++ )
    {
      R_AT( RAT_CGEREP, i ) ( CGEREP_EVENT_NW_DEACT, &event ); 
      R_AT( RAT_P_CGEV, i ) ( CGEREP_EVENT_NW_DEACT, &event );
    }
    
    cmhSM_GiveNSapiFree  (cid);

    if ( rat_id NEQ RAT_MAX )
    {
      gaci_RAT_caller ( rat_id, cid, cmdBuf, cme_err );

      cid_pointer  = 0;
      *work_cids = 0;
      rat_id = RAT_MAX;
    }
  }

  cmhSM_context_deactivated(temp_nsapiSet);
  cmhSM_contextDeactivated();

  /* inform SAT if needed */
#if defined (FF_SAT_E)
  cmhSAT_OpChnGPRSDeact();
#endif 
  
}

/*
+-------------------------------------------------------------------+
| PROJECT : GPRS (8441)      MODULE  : CMH_SMR                      |
| STATE   : finnished        ROUTINE : cmhSM_NetModify              |
+-------------------------------------------------------------------+

  PURPOSE : indicates a network initiated PDP context modification

*/
GLOBAL void cmhSM_NetModify ( USHORT nsapi_set, T_smreg_qos *smreg_qos )
{
  SHORT   cid, i = 0;

  TRACE_FUNCTION ("cmhSM_NetModify()");

  while ( CS_INVALID_STATE NEQ get_state_over_nsapi_set( &nsapi_set, &cid ) )
    {
      pdp_context[cid - 1].qos.preced    = smreg_qos->preced;
      pdp_context[cid - 1].qos.delay     = smreg_qos->delay;
      pdp_context[cid - 1].qos.relclass  = smreg_qos->relclass;
      pdp_context[cid - 1].qos.peak      = smreg_qos->peak;
      pdp_context[cid - 1].qos.mean      = smreg_qos->mean;

      for( i = 0 ; i < CMD_SRC_MAX; i++ )
      {
        R_AT( RAT_QOS_MOD, i ) ( cid, smreg_qos ); 
      }
    }
}

#endif /* GPRS */
/*==== EOF ========================================================*/

