view src/aci2/aci/cmh_smr.c @ 662:8cd8fd15a095

SIM speed enhancement re-enabled and made configurable TI's original code supported SIM speed enhancement, but Openmoko had it disabled, and OM's disabling of speed enhancement somehow caused certain SIM cards to start working which didn't work before (OM's bug #666). Because our FC community is much smaller in year 2020 than OM's community was in their day, we are not able to find one of those #666-affected SIMs, thus the real issue they had encountered remains elusive. Thus our solution is to re-enable SIM speed enhancement and simply wait for if and when someone runs into a #666-affected SIM once again. We provide a SIM_allow_speed_enhancement global variable that allows SIM speed enhancement to be enabled or disabled per session, and an /etc/SIM_spenh file in FFS that allows it to enabled or disabled on a non-volatile basis. SIM speed enhancement is now enabled by default.
author Mychaela Falconia <falcon@freecalypso.org>
date Sun, 24 May 2020 05:02:28 +0000
parents 93999a60b835
children
line wrap: on
line source

/* 
+----------------------------------------------------------------------------- 
|  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 ========================================================*/