FreeCalypso > hg > fc-magnetite
diff src/g23m-gprs/gmm/gmm_kernl.c @ 183:219afcfc6250
src/g23m-gprs: initial import from TCS3.2/LoCosto
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 13 Oct 2016 04:24:13 +0000 |
parents | |
children | 907458d58a86 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gprs/gmm/gmm_kernl.c Thu Oct 13 04:24:13 2016 +0000 @@ -0,0 +1,3113 @@ +/* ++----------------------------------------------------------------------------- +| Project : GPRS (8441) +| Modul : gmm_kernl.c ++----------------------------------------------------------------------------- +| 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 modul is part of the entity GMM and implements all +| procedures and functions as described in the +| SDL-documentation (KERN-statemachine) ++----------------------------------------------------------------------------- +*/ + + +#ifndef GMM_KERNF_C +#define GMM_KERNF_C +#endif + +#define ENTITY_GMM + +/*==== INCLUDES =============================================================*/ + +#include <stdio.h> +#include "typedefs.h" /* to get Condat data types */ +#include "vsi.h" /* to get a lot of macros */ +#include "macdef.h" +#include "gprs.h" +#include "gsm.h" /* to get a lot of macros */ +#include "ccdapi.h" /* to get CCD API */ +#include "cnf_gmm.h" /* to get cnf-definitions */ +#include "mon_gmm.h" /* to get mon-definitions */ +#include "prim.h" /* to get the definitions of used SAP and directions */ +#include "gmm.h" /* to get the global entity definitions */ + +#include "gmm_f.h" /* to get global functions */ +#include "gmm_txs.h" /* to get some signals */ +#include "gmm_rdys.h" /* to get some signals */ +#include "gmm_kernp.h" /* to get kern_gmmreg_detach_req */ +#include "gmm_kernf.h" /* to get local functions */ +#include "gmm_kernl.h" /* to get local label functions */ +#include <string.h> /* to get memcpy() */ +#include "gmm_syncs.h" +#include "gmm_rdyf.h" +#include "gmm_em.h" /* To get Engineering Mode functions */ + + +/*==== CONST ================================================================*/ + +/*==== LOCAL VARS ===========================================================*/ + +/*==== PRIVATE FUNCTIONS ====================================================*/ + +/*==== PUBLIC FUNCTIONS =====================================================*/ + +/* ++------------------------------------------------------------------------------ +| Function : kern_attach_1 ++------------------------------------------------------------------------------ +| Description : The label ATTACH_1 +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_attach_1 ( void ) +{ + GMM_TRACE_FUNCTION( "kern_attach_1" ); + { + T_gmobile_identity gmobile_identity; + MCAST (attach_request, ATTACH_REQUEST); /* T_ATTACH_REQUEST */ + + kern_attach_rau_init(); + + if ( GMM_LLC_STATE_UNASSIGNED == gmm_data->kern.attach_cap.llc_state ) + { + /* + * If no TLLI has yet been assigned to the lower layers. If a valid P-TMSI + * is available, GMM derives a foreign TLLI from that P-TMSI, otherwise GMM + * generates a random TLLI. + */ + kern_local_attach( FOREIGN_TLLI, INVALID_TLLI ); + } + + kern_ulong2mobile_identity ( gmm_data->ptmsi.current, &gmobile_identity ); + + kern_build_ms_network_capability ( &attach_request->ms_network_capability ); + + if (gmm_data->config.cipher_on) + { + attach_request->ms_network_capability.gea_1 = GEA_1_YES; + TRACE_EVENT ("ciphering on requested"); + } + else + { + attach_request->ms_network_capability.gea_1 = GEA_1_NO; + TRACE_EVENT ("ciphering off requested"); + } + + attach_request-> + attach_type.type_of_attach = gmm_data->kern.attach_cap.attach_proc_type; + attach_request-> + ciphering_key_sequence_number.key_sequence + = gmm_data->kern.auth_cap.cksn; + attach_request->drx_parameter = gmm_data->drx_parameter; + attach_request->gmobile_identity = gmobile_identity; + + attach_request->routing_area_identification = gmm_data->kern.attach_cap.rai_accepted; + + /* Internally we work always with 3-digit-MNC, adapt this before coding */ + if (attach_request->routing_area_identification.mnc[2] EQ 0xf) + { + attach_request->routing_area_identification.c_mnc = 2; + } + else + { + attach_request->routing_area_identification.c_mnc = SIZE_MNC; + } + + rr_csf_get_radio_access_capability( &attach_request->ra_cap ); + +#ifdef TDSGEN + attach_request->ra_cap.acc_tech_typ=1; + attach_request->ra_cap.flag_ra_cap2=1; + attach_request->ra_cap.v_ra_cap2=1; + attach_request->ra_cap.ra_cap2.acc_cap.pow_class= 1; + attach_request->ra_cap.ra_cap2.acc_cap.v_a5_bits=0; + attach_request->ra_cap.ra_cap2.acc_cap.es_ind=1; + attach_request->ra_cap.ra_cap2.acc_cap.ps=0; + attach_request->ra_cap.ra_cap2.acc_cap.vgcs=0; + attach_request->ra_cap.ra_cap2.acc_cap.vbs=0; + attach_request->ra_cap.ra_cap2.acc_cap.v_ms_struct=0; + attach_request->ra_cap.ra_cap2.acc_tech_typ=3; +#endif + + /* + * The READY_TIMER is negotiated + * this parameter is optional and is used, if the MS wants to indicate a + * preferred value vor the ready timer + */ + attach_request->v_ready_timer = FALSE; + + switch (gmm_data->kern.attach_cap.attach_proc_type) + { + case AT_WHILE_IMSI_AT: + /* + * 44.2.1.2.8 + */ + if (GMMRR_TMSI_INVALID == gmm_data->tmsi) + /* + * <R.GMM.ACINIT.M.009> + */ + { + attach_request->v_tmsi_status = TRUE; + attach_request->tmsi_status.tmsi_flag = FALSE; + } + else + { + attach_request->v_tmsi_status = FALSE; + attach_request->tmsi_status.tmsi_flag = TRUE; + } + break; + + case AT_COMB: + attach_request->v_tmsi_status = TRUE; + if (GMMRR_TMSI_INVALID == gmm_data->tmsi) + /* + * <R.GMM.ACINIT.M.009> + */ + { + attach_request->tmsi_status.tmsi_flag = FALSE; + } + else + { + attach_request->tmsi_status.tmsi_flag = TRUE; + } + break; + case AT_GPRS: + default: + attach_request->v_tmsi_status = FALSE; + break; + } + + /* + * <R.GMM.AGINIT.M.004> + */ + if ( gmm_data->ptmsi_signature.available ) + { + attach_request->v_p_tmsi_signature = TRUE; + attach_request-> p_tmsi_signature.p_tmsi_signature_value + = gmm_data->ptmsi_signature.value; + } + else + { + attach_request->v_p_tmsi_signature = FALSE; + } + /* + * <R.GMM.AGINIT.M.007> + */ + TRACE_EVENT ( "Info: START: T3310" ); + sig_kern_rdy_start_timer_req ( kern_T3310, gmm_data->kern.t3310_val ); + /* + * increments th counter for T3310 + */ + gmm_data->kern.ct3310++; + + switch(GET_STATE(KERN)) + { + case KERN_GMM_REG_INITIATED: + break; + default: + kern_gmmrr_attach_started(); + break; + } + SET_STATE ( KERN, KERN_GMM_REG_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_INITIATED ); +#endif + /* + * CURRENT_TLLI is used instead of FOREIGN_TLLI, because + * in kern_local_attach it is possible the the RANDOM TLLI was used + */ + sig_kern_tx_data_req ( CURRENT_TLLI, ATTACH_REQUEST ); + } + GMM_RETURN; +} /* kern_attach_1() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_resume_grr_der ++------------------------------------------------------------------------------ +| Description : The LABEL KERN_RESUME_GRR_DER sends the resume primitive to GRR +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_resume_grr_der ( void ) +{ + GMM_TRACE_FUNCTION( "kern_resume_grr_der" ); + { + PALLOC ( gmmrr_resume_req, GMMRR_RESUME_REQ ); + /* + * GMM enters state DEGEG_SUSPENDED if it was in DEREG_NO_IMSI + * So I have to tae careto enter NO_IMSI again. + */ + if (gmm_data->sim_gprs_invalid) + { + SET_STATE (KERN, KERN_GMM_DEREG_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); +#endif + } + else + { + SET_STATE (KERN, KERN_GMM_DEREG_RESUMING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_RESUMING ); +#endif + } + gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_ON; + gmm_data->kern.gmmrr_resume_sent=TRUE; + PSEND ( hCommGRR, gmmrr_resume_req ); + } + gmm_data->kern.suspension_type &= ~GMM_SUSP_LOCAL_DETACH; + GMM_RETURN; +} /* kern_resume_grr_der() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_resume_grr_reg ++------------------------------------------------------------------------------ +| Description : The LABEL KERN_RESUME_GRR_DER sends the resume primitive to GRR +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_resume_grr_reg ( void ) +{ + GMM_TRACE_FUNCTION( "kern_resume_grr_reg" ); + { + PALLOC ( gmmrr_resume_req, GMMRR_RESUME_REQ ); + SET_STATE (KERN, KERN_GMM_REG_RESUMING); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_RESUMING); +#endif + gmm_data->kern.gmmrr_resume_sent = TRUE; + gmm_data->kern.attach_cap.grr_state = GMM_GRR_STATE_ON; + PSEND ( hCommGRR, gmmrr_resume_req ); + } + GMM_RETURN; +} /* kern_resume_grr_reg() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_reg_at_local_disable ++------------------------------------------------------------------------------ +| Description : The label REG_AT_LOCAL_DISABLE +| is called, when GMM is in state GMM-REGISTERED.SUSPENDED +| and MMI has request GPRS_DISABLE +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_reg_at_local_disable ( void ) +{ + GMM_TRACE_FUNCTION( "kern_reg_at_local_disable" ); + + SET_STATE ( KERN, KERN_GMM_NULL_IMSI ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI ); +#endif + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_DISABLE_GPRS; + + kern_local_detach( GMMCS_INT_PROTOCOL_ERROR, /* TCS 2.1 */ + FALSE, GMM_LOCAL_DETACH_PROC_ENTER_DEREG ); + + if ( GMM_MM_REG_NORMAL_SERVICE == GET_STATE(MM) ) + { + kern_gmmreg_attach_cnf ( GMMREG_AT_IMSI ); + } + GMM_RETURN; +} /* kern_reg_at_local_disable () */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_imsi_detach_der_susp ++------------------------------------------------------------------------------ +| Description : The label IMSI_DETACH_DER_SUSP +| suspends GRR and enters the appropriate substate to wait for +| response from GRR +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_imsi_detach_der_susp ( void ) +{ + GMM_TRACE_FUNCTION( "kern_imsi_detach_der_susp" ); + + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_IMSI_DETACH); + GMM_RETURN; +} /* kern_imsi_detach_der_susp() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_imsi_detach_reg_susp ++------------------------------------------------------------------------------ +| Description : The label IMSI_DETACH_REG_SUSP +| suspends GRR and enters the appropriate substate to wait for +| response from GRR +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_imsi_detach_reg_susp ( void ) +{ + GMM_TRACE_FUNCTION( "kern_imsi_detach_reg_susp" ); + + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING); +#endif + /* + * kern_llgmm_unassign(); + */ + kern_llgmm_suspend(LLGMM_CALL); + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE,GMM_SUSP_IMSI_DETACH); + GMM_RETURN; +} /* kern_imsi_detach_reg_susp() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_no_cell_limited ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_NO_CELL_LIMITED +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_no_cell_limited ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_no_cell_limited" ); + + SET_STATE ( KERN, KERN_GMM_REG_NO_CELL_AVAILABLE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_NO_CELL_AVAILABLE ); +#endif + kern_llgmm_suspend(LLGMM_NO_GPRS_SERVICE); + GMM_RETURN; +} /* kern_enter_reg_no_cell_limited() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_rau_susp ++------------------------------------------------------------------------------ +| Description : The label RAU_SUSP +| is the continuing of the gmmrr_cell_ind primitive in state +| GMM_DEREGISTERED_SUSPENDED +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_rau_susp ( void ) +{ + GMM_TRACE_FUNCTION( "kern_rau_susp" ); + + if ( gmm_data->kern.attach_cap.gmmreg ) + { + switch ( gmm_data->kern.attach_cap.mobile_class ) + { + case GMMREG_CLASS_CC: + kern_reg_at_local_disable(); + GMM_RETURN; + case GMMREG_CLASS_CG: + if ( GMM_MM_DEREG != GET_STATE(MM) ) + { + kern_imsi_detach_reg_susp(); + GMM_RETURN; + } + break; + default: + break; + } + } + + + + /* + * TLLI will be assigned in rau_init + * + * kern_llgmm_assign(); + */ + kern_rau(); + GMM_RETURN; +} /* kern_rau_susp() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_limited_susp ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_LIMITED_SUSP +| is the continuing of the gmmrr_cell_ind primitive in state +| GMM_DEREGISTERED_SUSPENDED +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_limited_susp ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_limited_susp" ); + + if ( gmm_data->kern.attach_cap.gmmreg ) + { + switch ( gmm_data->kern.attach_cap.mobile_class ) + { + case GMMREG_CLASS_CC: + kern_reg_at_local_disable(); + GMM_RETURN; + case GMMREG_CLASS_CG: + if ( GMM_MM_REG_NORMAL_SERVICE != GET_STATE(MM) ) + { + kern_gmmreg_attach_cnf ( GMMREG_AT_GPRS ); + } + break; + default: + if ( GMM_MM_REG_NORMAL_SERVICE == GET_STATE(MM) ) + { + kern_gmmreg_attach_cnf ( GMMREG_AT_COMB ); + } + break; + } + } + kern_enter_reg_limited(); + GMM_RETURN; +} /* kern_enter_reg_limiied_susp() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_normal_susp ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_NORMAL_SUSP +| is the continuing of the gmmrr_cell_ind primitive in state +| GMM_DEREGISTERED_SUSPENDED +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_normal_susp ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_normal_susp" ); + + if ( gmm_data->kern.attach_cap.gmmreg ) + { + switch ( gmm_data->kern.attach_cap.mobile_class ) + { + case GMMREG_CLASS_CC: + kern_disable(); + break; + case GMMREG_CLASS_CG: + if ( GMM_MM_DEREG != GET_STATE(MM) ) + { + kern_imsi_detach_reg_susp(); + } + else + { + kern_enter_reg_normal(); + } + break; + default: + switch ( GET_STATE(MM) ) + { + case GMM_MM_DEREG: + case GMM_MM_REG_UPDATE_NEEDED: + /* Combined RAU + * MSC 3.4.3 IMSI attach while already GPRS attached + */ + kern_llgmm_assign (); + kern_rau (); + break; + default: + case GMM_MM_REG_NORMAL_SERVICE: + case GMM_MM_REG_NO_CELL_AVAILABLE: + case GMM_MM_REG_INITATED_VIA_GPRS: + kern_enter_reg_normal(); + break; + } + + break; + } + } + else + { + if ( gmm_data->kern.timeout_t3312 ) + { + /* + * <R.GMM.RAUTIMER.M.009> + */ + kern_periodic_rau(); + } + else + { + kern_gmmrr_stop_waiting_for_transmission(); + kern_enter_reg_normal(); + } + + } + GMM_RETURN; +} /* kern_enter_reg_normal_susp() */ + + + +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_limited ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_LIMITED +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_limited ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_limited" ); + + SET_STATE ( KERN, KERN_GMM_REG_LIMITED_SERVICE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_LIMITED_SERVICE ); +#endif + kern_llgmm_suspend(LLGMM_LIMITED); + GMM_RETURN; +} /* kern_enter_reg_limited_service() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_rau_init ++------------------------------------------------------------------------------ +| Description : The label RAU_INIT +| +| RAU will have been initiated +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void kern_rau_init ( void ) +{ + + + + GMM_TRACE_FUNCTION( "kern_rau_init" ); + { + /* T_ROUTING_AREA_UPDATE_REQUEST */ + MCAST (routing_area_update_request, ROUTING_AREA_UPDATE_REQUEST); + + kern_attach_rau_init(); + + routing_area_update_request->ciphering_key_sequence_number.key_sequence + = gmm_data->kern.auth_cap.cksn; + + routing_area_update_request->v_drx_parameter = TRUE; + routing_area_update_request->drx_parameter + = gmm_data->drx_parameter; + + routing_area_update_request->routing_area_identification + = gmm_data->kern.attach_cap.rai_accepted; + + /* Internally we work always with 3-digit-MNC, adapt this before coding */ + if (routing_area_update_request->routing_area_identification.mnc[2] EQ 0xf) + routing_area_update_request->routing_area_identification.c_mnc = 2; + else + routing_area_update_request->routing_area_identification.c_mnc = SIZE_MNC; + + rr_csf_get_radio_access_capability( &routing_area_update_request->ra_cap ); + + #ifdef TDSGEN + routing_area_update_request->ra_cap.acc_tech_typ=1; + routing_area_update_request->ra_cap.flag_ra_cap2=1; + routing_area_update_request->ra_cap.v_ra_cap2=1; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.pow_class= 1; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.v_a5_bits=0; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.es_ind=1; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.ps=0; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.vgcs=0; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.vbs=0; + routing_area_update_request->ra_cap.ra_cap2.acc_cap.v_ms_struct=0; + routing_area_update_request->ra_cap.ra_cap2.acc_tech_typ=3; + #endif + + /* + * this parameter is optional and is used, if the MS wants to indicate + * a preferred value vor the ready timer + */ + routing_area_update_request->v_ready_timer = FALSE; + + if ( gmm_data->ptmsi_signature.available ) + { + routing_area_update_request->v_p_tmsi_signature = TRUE; + routing_area_update_request->p_tmsi_signature.p_tmsi_signature_value + = gmm_data->ptmsi_signature.value; + } + else + { + routing_area_update_request->v_p_tmsi_signature = FALSE; + } + +#ifdef REL99 + /* Routing area update request in Release 99 has one more + * optional fields - PDP context status. + * The mobile doesn't change its capabilities while in operation. + * So MS network capability need not be sent with the RAU request. + * The old SGSN will pass the MS network capability sent during attach + * to the new SGSN. The new SGSN reuses this value. + */ + routing_area_update_request->v_ms_network_capability = FALSE; /* TCS 4.0 */ + switch (gmm_data->kern.sig_cell_info.sgsnr_flag)/*!gmm_data->release99 =>old code*/ /* TCS 4.0 */ + { + default: + case PS_SGSN_UNKNOWN: + case PS_SGSN_98_OLDER: + routing_area_update_request->v_pdp_context_status = FALSE; /* TCS 4.0 */ + routing_area_update_request->v_gmobile_identity = FALSE; /* TCS 4.0 */ + break; + case PS_SGSN_99_ONWARDS: + /* + * PDP context status + */ + if (INVALID_PDP_CONTEXT_STATUS == gmm_data->kern.attach_cap.pdp_context_status) + { + /*GMM doesn't have valid pdp_context_status. Do not include it in RAU*/ + routing_area_update_request->v_pdp_context_status = FALSE; /* TCS 4.0 */ + } else { /*Valid pdp_context_status present*/ + routing_area_update_request->v_pdp_context_status = TRUE; /* TCS 4.0 */ + routing_area_update_request->pdp_context_status.nsapi_set = /* TCS 4.0 */ + gmm_data->kern.attach_cap.pdp_context_status; /* TCS 4.0 */ + } + + /* + * P-TMSI is required in case of UMTS only + */ + routing_area_update_request->v_gmobile_identity = FALSE; /* TCS 4.0 */ + + break; + } +#endif + + /* + * I used T3310 instead of T3330 + */ + TRACE_EVENT ( "Info: START: T3310 (instead of T3330)" ); + sig_kern_rdy_start_timer_req ( kern_T3310, gmm_data->kern.t3310_val ); + /* + * <R.GMM.RAUTIMER.M.021> + */ + sig_kern_rdy_start_t3312_req (); + /* + * increments the counter for T3310 + */ + gmm_data->kern.ct3310++; + + + /* + * <R.GMM.TLLIUSE.M.003> + * if not GMM_PERIODIC_RAU then forein TLLI has o be used + */ + switch ( gmm_data->tlli.current_type) + { + case INVALID_TLLI: + if (kern_rai_changed()) + { + kern_local_attach ( FOREIGN_TLLI, OLD_TLLI ); + } + else + { + kern_local_attach ( LOCAL_TLLI, OLD_TLLI ); + } + break; + case LOCAL_TLLI: + case CURRENT_TLLI: + case OLD_TLLI: + /* + * only set to foreign TLLI if it is not done already + */ + if (kern_rai_changed ()) + /* + * set to foreign TLLI if RA is crossed or if not updated yet + */ + { + kern_local_attach ( FOREIGN_TLLI, OLD_TLLI ); + } + break; + case FOREIGN_TLLI: + case RANDOM_TLLI: + default: + break; + } + + /* + * #5900 + * PATCH UBUOB 3.4.02: in cases of repetition of RAU, no ATTACH_STARTED_REQ should be + * sent; therefore check state before sending the primitive + */ + switch(GET_STATE(KERN)) + { + case KERN_GMM_RAU_INITIATED: + /* do not repeat ATTACH_STARTED_REQ in this state! */ + break; + default: + kern_gmmrr_attach_started(); + break; + } + /* end patch */ + SET_STATE ( KERN, KERN_GMM_RAU_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_RAU_INITIATED ); +#endif + + sig_kern_tx_data_req (CURRENT_TLLI,ROUTING_AREA_UPDATE_REQUEST); + } + GMM_RETURN; +} /* kern_rau_init () */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_periodic_rau ++------------------------------------------------------------------------------ +| Description : The label PERIODIC_RAU +| +| Periodic RAU +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void kern_periodic_rau ( void ) +{ + GMM_TRACE_FUNCTION( "kern_periodic_rau" ); + + gmm_data->kern.attach_cap.rau_initiated = GMM_PERIODIC_RAU; + gmm_data->kern.attach_cap.update_proc_type = COMBINED_RAU; + { + /* T_ROUTING_AREA_UPDATE_REQUEST */ + MCAST (routing_area_update_request, ROUTING_AREA_UPDATE_REQUEST); + + routing_area_update_request->v_gmobile_identity = FALSE; + routing_area_update_request->v_ms_network_capability = FALSE; + routing_area_update_request->v_pdp_context_status = FALSE; + + if ( GMMREG_AT_GPRS != gmm_data->kern.attach_cap.attach_type + && GMMRR_NET_MODE_I == gmm_data->kern.sig_cell_info.net_mode) + /* + * <R.GMM.RCINIT.M.016> + * + * 24.008 9.4.1.3. TMSI Status + * + * This IE shall be included if the MS performs a + * combined GPRS attach and no valid TMSI is available + */ + { + if (GMMRR_TMSI_INVALID == gmm_data->tmsi ) + { + routing_area_update_request->v_tmsi_status = TRUE; + routing_area_update_request->tmsi_status.tmsi_flag = FALSE; + } + else + { + routing_area_update_request->v_tmsi_status = FALSE; + } + } + else + { + routing_area_update_request->v_tmsi_status = FALSE; + } + + + if (gmm_data->kern.timeout_t3312 + && GMMREG_CLASS_CG != gmm_data->kern.attach_cap.mobile_class + && GMMREG_AT_IMSI != gmm_data->kern.attach_cap.attach_type + && GMMRR_NET_MODE_I == gmm_data->kern.sig_cell_info.net_mode + && + (gmm_data->kern.attach_cap.mm_lau_attempted + || GMMRR_SERVICE_NONE== gmm_data->kern.old_sig_cell_info.gmm_status) + ) + /* + * <R.GMM.RAUTIMER.M.018> + * The network does not know, that the mobile was IMSI attached in + * the old wrong cell, so that GMM has to IMSI-attach the MS if entering + * net mode I + */ + { + /* + 24.008 ch. 4.7.2.2: + If the MS is both IMSI attached for GPRS and non-GPRS services , and if the MS lost coverage of + the registered PLMN and timer T3312 expires, then: + + a) if the MS returns to coverage in a cell that supports GPRS and that indicates that the network + is in network operation mode I, then the MS shall either perform the combined routing area + update procedure indicating "combined RA/LA updating with IMSI attach"; or + */ + if (gmm_data->kern.attach_cap.mm_lau_attempted) + { + routing_area_update_request->update_type.update_type_value + = COMBINED_RAU_IMSI_ATTACH; + } + else + { + /* + * if (GMMRR_SERVICE_NONE== gmm_data->kern.old_sig_cell_info.gmm_status) + * Last cell had no GPRS covarage + */ + routing_area_update_request->update_type.update_type_value + = COMBINED_RAU; + } + + } + else + { + routing_area_update_request->update_type.update_type_value + = PERIODIC_RAU; + } + gmm_data->kern.attach_cap.update_proc_type = routing_area_update_request->update_type.update_type_value; + + kern_llgmm_suspend(LLGMM_PERIODIC_RAU); + kern_rau_init(); + + } + GMM_RETURN; +} /* kern_periodic_rau () */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_normal ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_NORMAL +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_normal ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_normal" ); + + /* + * kern_llgmm_assign(); + */ + kern_llgmm_resume (); + SET_STATE ( KERN, KERN_GMM_REG_NORMAL_SERVICE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_NORMAL_SERVICE ); +#endif +#ifndef GMM_TCS4 + if ( gmm_data->kern.attach_cap.gmmsm ) + { + PALLOC (gmmsm_establish_cnf, GMMSM_ESTABLISH_CNF); + gmm_data->kern.attach_cap.gmmsm = FALSE; + PSEND ( hCommSM, gmmsm_establish_cnf ); + } +#endif + kern_gmmreg_attach_cnf((BYTE)(GMM_MM_REG_NORMAL_SERVICE==GET_STATE(MM)? + GMMREG_AT_COMB:GMMREG_AT_GPRS)); + + GMM_RETURN; +} /* kern_enter_reg_normal() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_reg_normal_upon_gmmrr_cell_ind ++------------------------------------------------------------------------------ +| Description : The label ENTER_REG_NORMAL... +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_reg_normal_upon_gmmrr_cell_ind ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_reg_normal_upon_gmmrr_cell_ind" ); + + kern_gmmrr_stop_waiting_for_transmission(); + kern_enter_reg_normal(); + GMM_RETURN; +} /* kern_enter_reg_normal() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_normal_attach ++------------------------------------------------------------------------------ +| Description : The label NORM_ATTACH +| +| MSC : 3.8 Attach +| +| MSC : 3.8.1 Normal Attach +| MSC : 3.8.1.1 Initiation +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_norm_attach ( void ) +{ + GMM_TRACE_FUNCTION( "kern_norm_attach" ); + + gmm_data->kern.attach_cap.attach_proc_type = AT_GPRS; + TRACE_EVENT("Info: Normal ATTACH"); + kern_attach_1 (); + GMM_RETURN; +} /* kern_norm_attach() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_comb_attach ++------------------------------------------------------------------------------ +| Description : The label COMB_ATTACH +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_comb_attach ( void ) +{ + GMM_TRACE_FUNCTION( "kern_comb_attach" ); + +/* + * 19760: <gprs attach while imsi attached> shall not be used + * leave following code in case we need to switch back + * + switch (GET_STATE(MM)) + { + default: + gmm_data->kern.attach_cap.attach_proc_type = AT_WHILE_IMSI_AT; + TRACE_EVENT("Info: Comb. ATTACH while IMSI attached"); + break; + case GMM_MM_DEREG: + case GMM_MM_REG_INITATED_VIA_GPRS: + case GMM_MM_REG_UPDATE_NEEDED: + gmm_data->kern.attach_cap.attach_proc_type = AT_COMB; + TRACE_EVENT("Info: Comb. ATTACH"); + break; + } + * + */ + + gmm_data->kern.attach_cap.attach_proc_type = AT_COMB; + TRACE_EVENT("Info: Comb. ATTACH"); + + kern_mm_attach_started (); + kern_attach_1(); + + GMM_RETURN; +} /* kern_comb_attach() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_attach ++------------------------------------------------------------------------------ +| Description : The label ATTACH +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_attach ( void ) +{ + GMM_TRACE_FUNCTION( "kern_attach" ); + + /* Set GRR in state to transmit user data if not aready done */ + kern_gmmrr_stop_waiting_for_transmission(); + + switch (gmm_data->kern.attach_cap.attach_type) + { + case GMMREG_AT_IMSI: + if (gmm_data->sim_gprs_invalid) + { + SET_STATE(KERN,KERN_GMM_DEREG_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_NO_IMSI); +#endif + } + else + { + if (GMM_MM_DEREG == GET_STATE(MM) + && MMGMM_LIMITED_SERVICE != gmm_data->kern.sig_cell_info.mm_status) + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + SET_STATE(KERN,KERN_GMM_DEREG_PLMN_SEARCH); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_PLMN_SEARCH); +#endif + } + } + GMM_RETURN; + case GMMREG_AT_COMB: + if (GMM_GRR_STATE_OFF==gmm_data->kern.attach_cap.grr_state) + { + kern_gmmrr_enable(); + } + if (GMMRR_NET_MODE_III==gmm_data->kern.sig_cell_info.net_mode + && GMMREG_CLASS_BC== gmm_data->kern.attach_cap.mobile_class + ) + { + if( GMM_MM_DEREG == GET_STATE(MM) + && MMGMM_LIMITED_SERVICE != gmm_data->kern.sig_cell_info.mm_status) + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + SET_STATE(KERN,KERN_GMM_DEREG_PLMN_SEARCH); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_PLMN_SEARCH); +#endif + } + GMM_RETURN; + } + break; + default: + if (GMM_GRR_STATE_OFF==gmm_data->kern.attach_cap.grr_state) + { + kern_gmmrr_enable(); + } + break; + } + + + + /* + * Upon some error causes MS has o rettach after RAU_REJ. + * So procedure should be set to ATTACH + */ + gmm_data->kern.attach_cap.rau_initiated = GMM_NO_RAU; + + if ( GMMREG_CLASS_CG == gmm_data->kern.attach_cap.mobile_class + || GMMREG_AT_GPRS == gmm_data->kern.attach_cap.attach_type) + { + kern_norm_attach(); + } + else + { + switch ( gmm_data->kern.sig_cell_info.net_mode ) + { + case GMMRR_NET_MODE_I: + + kern_comb_attach(); + break; + case GMMRR_NET_MODE_II: + if ( GMM_MM_DEREG != GET_STATE(MM) + || MMGMM_LIMITED_SERVICE == gmm_data->kern.sig_cell_info.mm_status) + { + kern_norm_attach (); + } + else + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + break; + case GMMRR_NET_MODE_III: + switch ( gmm_data->kern.attach_cap.mobile_class) + { + case GMMREG_CLASS_BG: + if ( GMM_MM_DEREG != GET_STATE(MM)) + { + + kern_imsi_detach_der_susp (); + } + else + { + + kern_norm_attach(); + } + break; + case GMMREG_CLASS_BC: + if ( GMM_MM_DEREG == GET_STATE(MM) + && MMGMM_LIMITED_SERVICE != gmm_data->kern.sig_cell_info.mm_status) + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + SET_STATE(KERN, KERN_GMM_DEREG_PLMN_SEARCH); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_PLMN_SEARCH); +#endif + } + break; + case GMMREG_CLASS_A: + /* + * react as in NMO II + */ + if ( GMM_MM_DEREG != GET_STATE(MM) + || MMGMM_LIMITED_SERVICE == gmm_data->kern.sig_cell_info.mm_status) + { + kern_norm_attach (); + } + else + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + break; + default: + TRACE_ERROR ("unexpected MS class"); + break; + } + break; + default: + TRACE_ERROR ("unknown network mode"); + break; + } + + } + GMM_RETURN; +} +/* ++------------------------------------------------------------------------------ +| Function : kern_disable ++------------------------------------------------------------------------------ +| Description : The label DISABLE +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_disable () +{ + GMM_TRACE_FUNCTION( "kern_disable" ); + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_DISABLE_GPRS; + kern_detach(); + GMM_RETURN; +} +/* ++------------------------------------------------------------------------------ +| Function : kern_detach ++------------------------------------------------------------------------------ +| Description : The label DETACH +| +| +| Parameters : void +| gmm_data->kern.detach_cap.detach_type MUST be set ! +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_detach() +{ + +#ifdef REL99 + T_gmobile_identity gmobile_identity; /* TCS 4.0 */ +#endif + + GMM_TRACE_FUNCTION( "kern_detach" ); + { + MCAST ( u_detach_request, U_DETACH_REQUEST ); /* T_U_DETACH_REQUEST */ + + u_detach_request->u_detach_type.power_off = PO_NORMAL_DETACH; + + switch ( gmm_data->kern.detach_cap.detach_type ) + { + case GMMREG_DT_DISABLE_GPRS: + gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_CC; + /* NO break */ + case GMMREG_DT_GPRS: + if ( GMM_MM_DEREG != GET_STATE(MM) + && GMMRR_NET_MODE_I == gmm_data->kern.sig_cell_info.net_mode) + { + /* + * <R.GMM.DINITM.M.007> + */ + kern_mm_start_t3212 (); + } + /* + * LABEL NORM_DETACH + */ + u_detach_request->u_detach_type.u_type_of_detach = DT_GPRS; + kern_llgmm_suspend(LLGMM_PERIODIC_RAU); + + break; + + case GMMREG_DT_COMB: + gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_CC; + if ( GMM_MM_DEREG == GET_STATE(MM) + || GMMRR_NET_MODE_I != gmm_data->kern.sig_cell_info.net_mode) + { + gmm_data->kern.detach_cap.detach_type = DT_GPRS; + /* + * LABEL NORM_DETACH + */ + u_detach_request->u_detach_type.u_type_of_detach = DT_GPRS; + } + else + { + /* + * LABEL COMB_DETACH + */ + u_detach_request->u_detach_type.u_type_of_detach = DT_COMB; + } + kern_llgmm_suspend(LLGMM_PERIODIC_RAU); + break; + /* break; */ + case GMMREG_DT_POWER_OFF: + case GMMREG_DT_SOFT_OFF: + u_detach_request->u_detach_type.power_off = PO_POWER_OFF; + /* NO break; */ + case GMMREG_DT_LIMITED_SERVICE: + case GMMREG_DT_SIM_REMOVED: + gmm_data->kern.attach_cap.mobile_class = GMMREG_CLASS_CC; + if ( GMM_MM_DEREG != GET_STATE(MM) + && GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) + { + /* + * LABEL COMB_DETACH + */ + u_detach_request->u_detach_type.u_type_of_detach = DT_COMB; + } + else + { + u_detach_request->u_detach_type.u_type_of_detach = DT_GPRS; + } + kern_llgmm_suspend(LLGMM_PERIODIC_RAU); + break; + case GMMREG_DT_IMSI: + u_detach_request->u_detach_type.u_type_of_detach = DT_IMSI; + break; + default: + TRACE_ERROR ( "Unexpected detach type in detach label" ); + break; + } + /* + * <R.GMM.DINITM.M.005> + */ + gmm_data->kern.ct3321 = 0; //44.2.2.1.3 Richard Byrne + +#ifdef REL99 + /* Detach request sent to a Release 99 network has two addional + * parameters. PTMSI and PTMSI signature + */ + switch (gmm_data->kern.sig_cell_info.sgsnr_flag)/*!gmm_data->release99 =>old code*/ /* TCS 4.0 */ + { + default: + case PS_SGSN_UNKNOWN: + case PS_SGSN_98_OLDER: + u_detach_request->v_gmobile_identity = FALSE; /* TCS 4.0 */ + u_detach_request->v_p_tmsi_signature_2 = FALSE; /* TCS 4.0 */ + break; + case PS_SGSN_99_ONWARDS: + /* + * PTMSI + */ + kern_ulong2mobile_identity( gmm_data->ptmsi.current, &gmobile_identity ); /* TCS 4.0 */ + u_detach_request->v_gmobile_identity = TRUE; /* TCS 4.0 */ + u_detach_request->gmobile_identity = gmobile_identity; /* TCS 4.0 */ + + /* + * PTMSI Signature + */ + if(gmm_data->ptmsi_signature.available) /* TCS 4.0 */ + { /* TCS 4.0 */ + u_detach_request->v_p_tmsi_signature_2 =TRUE; /* TCS 4.0 */ + u_detach_request->p_tmsi_signature_2.p_tmsi_signature_value /* TCS 4.0 */ + = gmm_data->ptmsi_signature.value; /* TCS 4.0 */ + } /* TCS 4.0 */ + else /* TCS 4.0 */ + { /* TCS 4.0 */ + u_detach_request->v_p_tmsi_signature_2=FALSE; /* TCS 4.0 */ + } /* TCS 4.0 */ + break; + } +#endif + + + kern_mm_detach_started (); + + sig_kern_tx_data_req ( CURRENT_TLLI, U_DETACH_REQUEST ); + + + switch ( gmm_data->kern.detach_cap.detach_type ) + { + case GMMREG_DT_IMSI: + /* + * <R.GMM.DINITM.M.006>, + * <R.GMM.ORATIMSI.M.001> + */ + SET_STATE ( KERN, KERN_GMM_REG_IMSI_DETACH_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_IMSI_DETACH_INITIATED ); +#endif + break; + case GMMREG_DT_SOFT_OFF: + /* + * if mm_imsi attached is reset than MM is requested in function + * mm_imsi_detach_ind to indicate detach_done + */ + if(GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) + { + SET_STATE ( MM, GMM_MM_DEREG ); + } + + vsi_t_stop ( GMM_handle, kern_T3302); + sig_kern_rdy_stop_t3302_req(); + vsi_t_stop ( GMM_handle, kern_T3310); + vsi_t_stop ( GMM_handle, kern_T3311); + + sig_kern_rdy_start_timer_req ( kern_TPOWER_OFF, TPOWER_OFF_VALUE ); + SET_STATE ( KERN, KERN_GMM_DEREG_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_INITIATED ); +#endif + break; + case GMMREG_DT_POWER_OFF: + /* + * if mm_imsi attached is reset than MM is requested in function + * mm_imsi_detach_ind to indicate detach_done + */ + if(GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) + { + SET_STATE ( MM, GMM_MM_DEREG ); + } + vsi_t_stop ( GMM_handle, kern_T3302); + sig_kern_rdy_stop_t3302_req(); + vsi_t_stop ( GMM_handle, kern_T3310); + vsi_t_stop ( GMM_handle, kern_T3311); + sig_kern_rdy_start_timer_req ( kern_TPOWER_OFF, TPOWER_OFF_VALUE ); + SET_STATE ( KERN, KERN_GMM_DEREG_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_INITIATED ); +#endif + break; + case GMMREG_DT_LIMITED_SERVICE: + kern_l_sim_rem_reg_lim (); + break; + default: + TRACE_EVENT (" START T3321" ); + sig_kern_rdy_start_timer_req ( kern_T3321, gmm_data->kern.t3321_val ); + + SET_STATE ( KERN, KERN_GMM_DEREG_INITIATED ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_INITIATED ); +#endif + break; + } + } + GMM_RETURN; +} /* kern_detach() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_rau ++------------------------------------------------------------------------------ +| Description : The label RAU +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_rau ( void ) +{ + GMM_TRACE_FUNCTION( "kern_rau" ); + { + + + gmm_data->kern.attach_cap.rau_initiated = GMM_RAU; + switch ( gmm_data->kern.sig_cell_info.net_mode ) + { + case GMMRR_NET_MODE_I: + kern_llgmm_suspend(LLGMM_RAU); + break; + case GMMRR_NET_MODE_II: + if (kern_lau_needed() + && !gmm_data->kern.detach_cap.gmmreg) + { + kern_llgmm_suspend(LLGMM_CALL); + } + else + { + kern_llgmm_suspend(LLGMM_RAU); + } + break; + case GMMRR_NET_MODE_III: + switch ( gmm_data->kern.attach_cap.mobile_class) + { + case GMMREG_CLASS_A: + kern_llgmm_suspend(LLGMM_RAU); + break; + case GMMREG_CLASS_BG: + if ( GMM_MM_DEREG != GET_STATE(MM) + && MMGMM_LIMITED_SERVICE != gmm_data->kern.sig_cell_info.mm_status ) + { + kern_llgmm_suspend(LLGMM_CALL); + } + else + { + kern_llgmm_suspend(LLGMM_RAU); + } + break; + case GMMREG_CLASS_BC: + if (GMMREG_AT_GPRS == gmm_data->kern.attach_cap.attach_type) + { + kern_llgmm_suspend(LLGMM_RAU); + } + else + /* + * GSM attach_type + */ + { + if (kern_lau_needed()) + { + kern_llgmm_suspend(LLGMM_CALL); + } + else + { + if (kern_rai_changed()) + { + kern_llgmm_suspend(LLGMM_RAU); + } + } + } + break; + default: + kern_llgmm_suspend(LLGMM_RAU); + break; + } + break; + default: + TRACE_ERROR ("unkown net mode"); + break; + } + } /* PALLOC */ + + kern_rau_limited (); + GMM_RETURN; +} /* kern_rau() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_aac_over_5 ++------------------------------------------------------------------------------ +| Description : The label AAC_OVER_5 +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +void kern_aac_over_5 ( USHORT cause ) +{ + GMM_TRACE_FUNCTION( "kern_aac_over_5" ); + + /* <R.GMM.DDATMATT.M.001> + * If entry into this state was caused by b) or d) of procedure <AGABNORM> + * with cause 'Retry upon entry into a new cell', GPRS attach shall be + * performed when a new cell is entered. + */ + +/*if ( cause NEQ GMMCS_RETRY_IN_NEW_CELL ) TCS 2.1 + {*/ + /* + * <R.GMM.AGABNORM.M.026> + */ + TRACE_EVENT ( "Info: START: T3302" ); + TRACE_1_INFO ("ATTACH or RAU will be retried %.1f minutes later", + gmm_data->kern.t3302_val/(60000.0)); + + vsi_t_start ( GMM_handle , kern_T3302, gmm_data->kern.t3302_val ); + sig_kern_rdy_start_t3302_req(); + /*}*/ + + gmm_data->gu = GU2_NOT_UPDATED; + if (GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated) + { + kern_sim_del_locigprs (); + } + kern_sim_gmm_update(); + + if ((GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated && + AT_GPRS != gmm_data->kern.attach_cap.attach_proc_type ) + || (GMM_NO_RAU != gmm_data->kern.attach_cap.rau_initiated && + (COMBINED_RAU == gmm_data->kern.attach_cap.update_proc_type ) + || (COMBINED_RAU_IMSI_ATTACH == gmm_data->kern.attach_cap.update_proc_type ))) + { + if ( GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated ) + /* + * GMM is in state REG_INITIATED + * we try to attach for GSM + */ + { + + gmm_data->kern.attach_cap.enter_attempting_to_update_after_lau=TRUE; + + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + + kern_local_detach( cause, FALSE, + GMM_LOCAL_DETACH_PROC_SUSP_LAU); + } + else + /* + * GMM is in state RAU_INITIATED + * we try to start LAU + */ + { + gmm_data->kern.attach_cap.enter_attempting_to_update_after_lau=TRUE; + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + kern_mm_attach_rej ( GMMCS_AAC_OVER_5); /* TCS 2.1 */ + + } + else + { + if ( GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated ) + { + /* + * Optional: The MS may optionally enter state GMM-DEREG.PLMN-SEARCH + * instead of GMM-DEREG.ATTEMPTING-TO-ATTACH. (Version 6.4.0) + * + * <R.GMM.AGABNORM.M.027>, <R.GMM.AGABNORM.M.030> + */ + /* + * SET_STATE ( KERN, KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH ); + */ + gmm_data->kern.attach_cap.enter_attempting_to_update_after_lau=TRUE; + + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + + kern_local_detach( cause, FALSE, + GMM_LOCAL_DETACH_PROC_RESUME); + } + else + { + SET_STATE ( KERN, KERN_GMM_REG_ATTEMPTING_TO_UPDATE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_ATTEMPTING_TO_UPDATE ); +#endif + } + } + GMM_RETURN; + +} /* kern_aac_over_5() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_l_sim_rem_reg_lim ++------------------------------------------------------------------------------ +| Description : The label L_SIM_REM_REG_LIM +| SIM removed in state GMM-REGISTERED in a limited substate ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_l_sim_rem_reg_lim ( void ) +{ + GMM_TRACE_FUNCTION( "kern_l_sim_rem_reg_lim" ); + + /* + * local GPRS only detach with any error cause + * 2.parameter is only used for attach procedure + * + * <R.GMM.DETACH.M.005> + */ + /* + * Optional: The MS may optionally enter state GMM-DEREG.PLMN-SEARCH + * instead of GMM-DEREG.ATTEMPTING-TO-ATTACH. (Version 6.4.0) + * + * <R.GMM.AGABNORM.M.027>, <R.GMM.AGABNORM.M.030> + * + SET_STATE ( KERN, SET_STATE ( KERN, KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ ) ); + */ + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_LIMITED_SERVICE; + + kern_local_detach( GMMCS_SIM_REMOVED, FALSE, /* TCS 2.1 */ + GMM_LOCAL_DETACH_PROC_ENTER_NULL_IMSI_LIMITED_SERVICE_REQ); + /* + * <R.GMM.DSUBFANO.M.003> + */ + + GMM_RETURN; +} /* kern_l_sim_rem_reg_lim() */ +/* ++------------------------------------------------------------------------------ +| Function : kern_l_sim_rem_reg ++------------------------------------------------------------------------------ +| Description : The label L_SIM_REM_REG +| SIM removed in state GMM-REGISTERED ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_l_sim_rem_reg ( void ) +{ + GMM_TRACE_FUNCTION( "kern_l_sim_rem_reg" ); + + SET_STATE ( KERN, KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI_LIMITED_SERVICE_REQ ); +#endif + + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_LIMITED_SERVICE; + kern_detach( ); + + GMM_RETURN; +} /* kern_l_sim_rem_reg() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_aac ++------------------------------------------------------------------------------ +| Description : The label AAC +| +| Parameters : error_cause +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_aac ( USHORT cause ) +{ + GMM_TRACE_FUNCTION( "kern_aac" ); + /* <R.GMM.AGABNORM.M.020> */ + gmm_data->kern.aac ++; + + TRACE_1_INFO ("error cause: 0x%x",cause); + TRACE_1_INFO(" aac: %d", gmm_data->kern.aac ); + + gmm_data->kern.detach_cap.error_cause = cause; + /* + * reset the counter for timer T3310 + */ + gmm_data->kern.ct3310 = 0; + /* + * <R.GMM.AGABNORM.M.021> + */ + gmm_data->kern.attach_cap.t3310_value=0; + vsi_t_stop ( GMM_handle , kern_T3310); + if (GMM_NO_RAU==gmm_data->kern.attach_cap.rau_initiated) + { + kern_gmmreg_detach ( GMMREG_DT_GPRS, + cause, + GMMREG_SEARCH_RUNNING, + cause); + } + + kern_gmmrr_attach_finished(); + + if ( gmm_data->kern.aac < MAX_AAC ) + /* + * AAC_UNDER_5 + */ + { + if ( AT_GPRS != gmm_data->kern.attach_cap.attach_proc_type ) + { + if ( kern_lai_changed () ) + { + /* + * <R.GMM.ACABNORM.M.006> + */ + kern_mm_attach_rej ( GMMCS_AAC_UNDER_5 ); /* TCS 2.1 */ + } + } + + /* <R.GMM.DDATMATT.M.001> + * If entry into this state was caused by b) or d) of procedure <AGABNORM> + * with cause 'Retry upon entry into a new cell', GPRS attach shall be + * performed when a new cell is entered. + */ + /* Richard Byrne 44.2.1.2.8 remove if ( cause NEQ GMMCS_RETRY_IN_NEW_CELL ) */ /* TCS 2.1 */ + { + /* + * <R.GMM.AGABNORM.M.022> + */ + TRACE_EVENT ( "Info: START: T3311" ); + vsi_t_start ( GMM_handle , kern_T3311, gmm_data->kern.t3311_val ); + } + switch ( gmm_data->kern.attach_cap.rau_initiated ) + { + case GMM_NO_RAU: + SET_STATE ( KERN, KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_ATTEMPTING_TO_ATTACH ); +#endif + break; + case GMM_RAU: + /* + * <R.GMM.AGABNORM.M.023> + */ + SET_STATE ( KERN, KERN_GMM_REG_ATTEMPTING_TO_UPDATE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_ATTEMPTING_TO_UPDATE ); +#endif + break; + case GMM_PERIODIC_RAU: + /* + * <R.GMM.RNABNORM.M.022> + */ + kern_enter_reg_normal(); + break; + default: + TRACE_ERROR ("unexcpected RAU case"); + break; + } + + } + else + /* + * LABEL AAC_OVER_5 + * + * acc expired + */ + { + kern_aac_over_5 (cause); + } + GMM_RETURN; +} /* kern_aac() */ + + +/* ++------------------------------------------------------------------------------ +| Function : kern_err_cause ++------------------------------------------------------------------------------ +| Description : The label ERR_CAUSE +| +| Parameters : error_cause +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_err_cause ( USHORT error_cause, BOOL det_acc_sent ) +{ + GMM_TRACE_FUNCTION( "kern_err_cause" ); + + gmm_data->kern.detach_cap.error_cause = error_cause; + + TRACE_1_INFO ("error cause: %x",error_cause); + + /* + * <R.GMM.AGREJECT.M.003>, <R.GMM.AGREJECT.M.004>, + * <R.GMM.AGREJECT.M.006>, <R.GMM.DSUBFANO.M.003>, + * <R.GMM.AGREJECT.M.011>, <R.GMM.AGREJECT.M.012>, + * <R.GMM.AGREJECT.M.029>, <R.GMM.AGREJECT.M.028>, + * <R.GMM.AGREJECT.M.034>, <R.GMM.AGREJECT.M.015>, + * <R.GMM.AGREJECT.M.016>, <R.GMM.DSUBFANO.M.013> + */ + + switch ( error_cause ) + { + case GMMCS_IMSI_UNKNOWN: /* TCS 2.1 */ + /* No SIM upate. GPRS is still available */ + /* + * <R.GMM.DNACM.M.040> + */ + /* + * kern_mm_attach_rej ( error_cause ); + * called in kern_local_detach + */ + + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_IMSI; + + kern_local_detach( error_cause, det_acc_sent, GMM_LOCAL_DETACH_PROC_ENTER_REG_NORMAL); + + break; + case GMMCS_NO_MS_ID: /* TCS 2.1 */ + /* + * This case can not be reached in attach_procedure, + * so I may reset the attach parameters, the mobile + * is just in state DEREGISTERED. + */ + kern_sim_del_locigprs(); + gmm_data->gu = GU2_NOT_UPDATED; + kern_sim_gmm_update(); + /* + * <R.GMM.RCREJECT.M.016>, <R.GMM.RCREJECT.M.035> + */ + gmm_data->kern.detach_cap.detach_type = GMM_DT_RE_ATTACH; + + kern_local_detach ( error_cause, det_acc_sent, GMM_LOCAL_DETACH_PROC_RE_ATTACH); + break; + case GMMCS_IMPLICIT_DETACHED: /* TCS 2.1 */ + if ( GMMREG_AT_COMB==gmm_data->kern.attach_cap.attach_proc_type ) + { + /* + * <R.GMM.RCREJECT.M.036> + */ + kern_mm_attach_rej ( error_cause ); + + /* + * <R.GMM.RCREJECT.M.030> + */ + kern_gmmreg_detach (GMMREG_DT_COMB, + GMMCS_IMPLICIT_DETACHED, /* TCS 2.1 */ + GMMREG_SEARCH_RUNNING, + error_cause); + } + else + { + kern_gmmreg_detach (GMMREG_DT_GPRS, + GMMCS_IMPLICIT_DETACHED, /* TCS 2.1 */ + GMMREG_SEARCH_RUNNING, + error_cause); + } + gmm_data->kern.detach_cap.detach_type = GMM_DT_RE_ATTACH; + kern_local_detach( error_cause, det_acc_sent, GMM_LOCAL_DETACH_PROC_RE_ATTACH); + + break; + case GMMCS_GPRS_NOT_ALLOWED_IN_PLMN: /* TCS 2.1 */ + memcpy (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[0].mcc, + gmm_data->kern.sig_cell_info.env.rai.plmn.mcc, SIZE_MCC); + memcpy (gmm_data->kern.attach_cap.list_of_forbidden_plmns_for_gprs_service[0].mnc, + gmm_data->kern.sig_cell_info.env.rai.plmn.mnc, SIZE_MNC); + + gmm_data->kern.sig_cell_info.gmm_status=GMMRR_SERVICE_LIMITED; + + kern_sim_del_locigprs(); + gmm_data->gu = GU3_ROAMING_NOT_ALLOWED; + kern_sim_gmm_update(); + kern_mm_attach_rej ( error_cause ); + + + if ( GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated + && GMMREG_AT_COMB == gmm_data->kern.attach_cap.attach_proc_type + && kern_lau_needed()) + /* + * If GMM had tried to comb. attach then if MM is not registered it has + * to do so. + */ + { + /* + * <GMM.R.ACREJECT.M.014> + */ + /* + * <GMM.R.ACREJECT.M.015> + * <GMM.R.ACREJECT.M.016> + */ + gmm_data->kern.suspension_type |= GMM_SUSP_LAU; + } + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + kern_local_detach( error_cause, det_acc_sent, + GMM_LOCAL_DETACH_PROC_UNASSIGN); + + break; + + case GMMCS_GPRS_NOT_ALLOWED: /* TCS 2.1 */ + gmm_data->sim_gprs_invalid = TRUE; + kern_sim_del_locigprs(); + gmm_data->gu = GU3_ROAMING_NOT_ALLOWED; + kern_sim_gmm_update(); + /* + * LABEL ERRCS_GPRS_NOT_ALLOWED + * + * <R.DNACM.M.041> + */ + /* + * <GMM.R.RCREJECT.M.033> + */ + kern_mm_start_t3212(); + /* + * <R.GMM.RCREJECT.M.011>, <R.GMM.AGREJECT.M.013> + * <R.GMM.ACREJECT.M.012> + */ + /* + * <GMM.R.ACREJECT.M.015> + * <GMM.R.ACREJECT.M.016> + */ + /* ANITE TC 44.2.1.2.6 */ + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + kern_local_detach( error_cause, det_acc_sent, GMM_LOCAL_DETACH_PROC_DISABLE); + break; + case GMMCS_GSM_GPRS_NOT_ALLOWED: /* TCS 2.1 */ + gmm_data->sim_gprs_invalid = TRUE; + kern_sim_del_locigprs(); + gmm_data->gu = GU3_ROAMING_NOT_ALLOWED; + kern_sim_gmm_update(); + /* + * <R.GMM.AGREJECT.M.034>, <R.GMM.ACREJECT.M.009> + * <R.GMM.DNACM.M.025>, <R.GMM.RCREJECT.M.009> + */ + /* + * kern_mm_attach_rej ( error_cause ); + * called in kern_local_detach + */ + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_COMB; + kern_local_detach( error_cause, det_acc_sent, + GMM_LOCAL_DETACH_PROC_COMB_DISABLE); + break; + + default: + kern_sim_del_locigprs(); + gmm_data->gu = GU3_ROAMING_NOT_ALLOWED; + kern_sim_gmm_update(); + + /* + * LABEL ERR_CAUSE_2 + */ + /* NO break; */ + switch ( error_cause ) + { + case GMMCS_PLMN_NOT_ALLOWED: /* TCS 2.1 */ + case GMMCS_ROAMING_NOT_ALLOWED: /* TCS 2.1 */ + /* + * <R.GMM.AGREJECT.M.021>, <R.GMM.AGREJECT.M.022> + */ + /* + * MM knows, what is to do + * because the cause is forwarded be the mmgmm_attach_rej_req + * primitive + */ + /* NO BREAK */ + case GMMCS_LA_NOT_ALLOWED: /* TCS 2.1 */ + +#ifdef REL99 + case GMMCS_NO_SUITABLE_CELL_IN_LA: /*Cause #15*/ /* TCS 4.0 */ +#endif + + /* + * sometimes GRR responses to GMMRR_RESUME_IND verry fast and does not know + * that RR is in limited, so GMM will set state before. + */ + gmm_data->kern.sig_cell_info.mm_status = MMGMM_LIMITED_SERVICE; + sig_kern_sync_set_mm_state(MMGMM_LIMITED_SERVICE); + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_COMB; + kern_local_detach( error_cause, det_acc_sent, + GMM_LOCAL_DETACH_PROC_UNASSIGN); + break; + case GMMCS_ILLEGAL_ME: /* TCS 2.1 */ + case GMMCS_ILLEGAL_MS: /* TCS 2.1 */ + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_COMB; + kern_local_detach( error_cause, det_acc_sent, + GMM_LOCAL_DETACH_PROC_COMB_DISABLE); + break; + default: + /* + * <R.GMM.ODNOIMSI.M.001>, <R.GMM.DSUBFANO.M.003> + */ + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + kern_local_detach( error_cause, det_acc_sent, GMM_LOCAL_DETACH_PROC_ENTER_NULL_NO_IMSI); + break; + } + break; + /* END of LABEL ERR_CAUSE_2 */ + } + GMM_RETURN; +} /* kern_err_cause() */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_enter_der ++------------------------------------------------------------------------------ +| Description : The label ENTER_DER +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_enter_der ( void ) +{ + GMM_TRACE_FUNCTION( "kern_enter_der" ); + + if (gmm_data->kern.attach_cap.mobile_class_changed + && GMMREG_CLASS_CC!=gmm_data->kern.attach_cap.mobile_class) + { + gmm_data->kern.attach_cap.mobile_class_changed=FALSE; + kern_gmmrr_enable(); + } + + + kern_reset_cipher (); + + + switch ( gmm_data->kern.detach_cap.detach_type ) + { + case GMMREG_DT_POWER_OFF: + SET_STATE ( KERN, KERN_GMM_NULL_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); +#endif + break; + case GMMREG_DT_SOFT_OFF: + if (gmm_data->sim_gprs_invalid) + { + SET_STATE ( KERN,KERN_GMM_NULL_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); +#endif + } + else + { + SET_STATE ( KERN,KERN_GMM_NULL_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); +#endif + } + break; + case GMMREG_DT_SIM_REMOVED: + SET_STATE ( KERN, KERN_GMM_NULL_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); +#endif + if (GMMRR_NET_MODE_I==gmm_data->kern.sig_cell_info.net_mode) + { + kern_mm_imsi_detach_ind (GMMCS_SIM_REMOVED, MMGMM_PERFORM_DETACH, + GMMREG_DT_SIM_REMOVED ); /* TCS 2.1 */ + } + break; + case GMMREG_DT_DISABLE_GPRS: + if (gmm_data->sim_gprs_invalid) + { + SET_STATE ( KERN,KERN_GMM_NULL_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); +#endif + } + else + { + SET_STATE ( KERN,KERN_GMM_NULL_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); +#endif + } + kern_mm_activate_mm (); + break; + default: + if (GMMRR_NET_MODE_III==gmm_data->kern.sig_cell_info.net_mode + && GMMREG_CLASS_BC== gmm_data->kern.attach_cap.mobile_class + && kern_lau_needed()) + { + /* start attach GSM */ + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_NOT_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + break; + } + else + { + if (gmm_data->sim_gprs_invalid) + { + SET_STATE ( KERN, KERN_GMM_NULL_NO_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_NO_IMSI); +#endif + } + else + { + SET_STATE ( KERN, KERN_GMM_NULL_IMSI); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_NULL_IMSI); +#endif + } + /* GPRS DISABLE */ + kern_gmmrr_disable(); + kern_mm_activate_mm (); + } + break; + } + /* + * The used P-TMSI signature should be deleted + */ + gmm_data->ptmsi_signature.available = FALSE; + gmm_data->ptmsi_signature.value = INVALID_PTMSI_SIGNATURE; + + GMM_RETURN; +} /* kern_enter_der () */ + + +/* ++------------------------------------------------------------------------------ +| Function : kern_attach_complete_end ++------------------------------------------------------------------------------ +| Description : The label ATTACH_COMPLETE_END +| +| ATTACH accept procedure completion end +| +| Parameters : result_value - the returned attach type +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_attach_complete_end ( UBYTE result_value ) +{ + GMM_TRACE_FUNCTION( "kern_attach_complete_end" ); + + kern_gmmrr_stop_waiting_for_transmission(); + + /* + *<R.GMM.AGACCEPT.M.027>, <R.GMM.PATTCNF.M.001> + */ + switch (result_value) + { + case NORMAL_ATTACHED: + if (GMM_MM_REG_NORMAL_SERVICE != GET_STATE(MM)) + { + if (GMMREG_AT_COMB==gmm_data->kern.attach_cap.attach_type + && GMMRR_NET_MODE_III != gmm_data->kern.sig_cell_info.net_mode) + { + kern_gmmreg_attach_cnf_sr ( GMMREG_AT_GPRS, SEARCH_RUNNING ); + } + else + { + kern_gmmreg_attach_cnf ( GMMREG_AT_GPRS ); + } + break; + } + /* NO break */ + case COMBINED_ATTACHED: + kern_gmmreg_attach_cnf ( GMMREG_AT_COMB ); + break; + default: + TRACE_ERROR ("unknown result value"); + break; + } + + +#ifndef GMM_TCS4 + if ( gmm_data->kern.attach_cap.gmmsm ) + { + PALLOC (gmmsm_establish_cnf, GMMSM_ESTABLISH_CNF); + gmm_data->kern.attach_cap.gmmsm = FALSE; + PSEND ( hCommSM, gmmsm_establish_cnf ); + } +#endif + if (gmm_data->kern.attach_cap.attempting_to_update_mm ) + { + SET_STATE ( KERN, KERN_GMM_REG_ATTEMPTING_TO_UPDATE_MM ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_ATTEMPTING_TO_UPDATE_MM ); +#endif + gmm_data->kern.attach_cap.attempting_to_update_mm = FALSE; + } + else + { + /* gmmrr_cell_res + */ + SET_STATE(GU,GU_UPDATE_NOT_NEEDED); + SET_STATE ( KERN, KERN_GMM_REG_NORMAL_SERVICE ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_NORMAL_SERVICE ); +#endif + } + GMM_RETURN; +} /* kern_attach_complete_end () */ + + + +/* ++------------------------------------------------------------------------------ +| Function : kern_rau_complete_end ++------------------------------------------------------------------------------ +| Description : The label RAU_COMPLETE_END +| +| RAU accept procedure completion end +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_rau_complete_end ( UBYTE result_value ) +{ + GMM_TRACE_FUNCTION( "kern_rau_complete_end" ); + + /* gmmrr_cell_ind + * is sent in kern_attach_complete_end + */ + kern_llgmm_resume (); + + gmm_data->kern.attach_cap.rau_initiated = GMM_NO_RAU; + + if( gmm_data->sim_gprs_invalid) + { + TRACE_EVENT("Detach because SIM removed"); + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_COMB; + kern_detach( ); + } + else if ( gmm_data->kern.detach_cap.gmmreg ) + /* + * MO DETACH was requested + */ + { + TRACE_0_INFO("Detach Request again"); + switch ( gmm_data->kern.detach_cap.detach_type ) + { + case GMMREG_DT_IMSI: + case GMMREG_DT_COMB: + case GMMREG_DT_SIM_REMOVED: + switch (gmm_data->kern.sig_cell_info.net_mode) + { + case GMMRR_NET_MODE_I: + kern_detach( ); + break; + case GMMRR_NET_MODE_II: + /* + * if deatch procedure collision and GSM is already detached we + * are finished + */ + if (GMM_MM_DEREG != GET_STATE(MM)) + { + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING); +#endif + kern_llgmm_suspend(LLGMM_CALL); + kern_gmmrr_suspend(GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + kern_detach( ); + } + break; + case GMMRR_NET_MODE_III: + kern_detach( ); + break; + default: + TRACE_ERROR ("unknown net mode"); + break; + } + break; + case GMMREG_DT_DISABLE_GPRS: + kern_local_detach( GMMCS_INT_NOT_PRESENT, FALSE, GMM_LOCAL_DETACH_PROC_ENTER_DEREG); /* TCS 2.1 */ + break; + case GMMREG_DT_GPRS: + case GMMREG_DT_POWER_OFF: + case GMMREG_DT_SOFT_OFF: + kern_detach( ); + break; + default: + TRACE_ERROR ("Unexpected detach type in primitive GMMREG_DETACH_REQ"); + break; + } + } + else if (GMMRR_NET_MODE_III==gmm_data->kern.sig_cell_info.net_mode + && GMMRR_CLASS_BC == gmm_data->kern.attach_cap.mobile_class) + { + TRACE_EVENT("Detach because NMO III and BC"); + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + kern_detach( ); + } + else + { + kern_attach_complete_end(result_value); + } + GMM_RETURN; +} /* kern_rau_complete_end () */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_rau_complete ++------------------------------------------------------------------------------ +| Description : The label RAU_COMPLETE +| +| RAU accept procedure completion +| +| Parameters : result_value - the returned attach type +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_rau_complete ( UBYTE result_value ) +{ + GMM_TRACE_FUNCTION( "kern_rau_complete" ); + + sig_kern_tx_data_req ( CURRENT_TLLI, ROUTING_AREA_UPDATE_COMPLETE ); + + /* + * If Cell Notification is set in the RAU ACCEPT message, the + * RAU COMPLETE if send, can be considered as the initial Cell Update. + * The Next cell update can use LLC NULL frame. + * Reference 3GPP TS 24.008 section 4.7.2.1.1 + */ + if (gmm_data->cell_notification EQ FIRST_CELL_NOTIFY) + { + gmm_data->cell_notification = NOT_FIRST_CELL_NOTIFY; /* TCS 4.0 */ + } + + kern_rau_complete_end(result_value); + GMM_RETURN; +} /* kern_rau_complete () */ + +/* ++------------------------------------------------------------------------------ +| Function : kern_attach_complete ++------------------------------------------------------------------------------ +| Description : The label ATTACH_COMPLETE +| +| ATTACH and RAU accept procedure completion +| +| Parameters : attach_complete - idicates whether AIR ATTACH-COMPLETE +| message has to sent or not +| receive_n_pdu_number_list +| +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_attach_complete ( + UBYTE result_value, + BOOL attach_complete, + BOOL v_receive_n_pdu_number_list, + T_receive_n_pdu_number_list * receive_n_pdu_number_list) +{ + GMM_TRACE_FUNCTION( "kern_attach_complete" ); + gmm_data->kern.attach_cap.attach_complete = attach_complete; + + if ( GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated ) + /* + * ATTACH procedure + */ + { + if ( attach_complete ) + { + /* + * <R.GMM.AGACCEPT.M.018>, <R.GMM.TLLIUSE.M011> + */ + sig_kern_tx_data_req ( CURRENT_TLLI, ATTACH_COMPLETE ); + + /* + * If Cell Notification is set in the ATTACH ACCEPT message, the + * ATTACH COMPLETE if send, can be considered as the initial Cell Update. + * The Next cell update can use LLC NULL frame. + * Reference 3GPP TS 24.008 section 4.7.2.1.1 + */ + if (gmm_data->cell_notification EQ FIRST_CELL_NOTIFY) + { + gmm_data->cell_notification = NOT_FIRST_CELL_NOTIFY; /* TCS 4.0 */ + } + + } + kern_attach_complete_end( result_value ); + +#ifdef GMM_TCS4 + { + PALLOC (mmpm_attach_ind, MMPM_ATTACH_IND); + PSEND ( hCommSM, mmpm_attach_ind ); + } +#endif + + } + else + /* + * RAU procedure + */ + { + MCAST (routing_area_update_complete, ROUTING_AREA_UPDATE_COMPLETE); + if (v_receive_n_pdu_number_list ) + { + int i; +#ifdef GMM_TCS4 + PALLOC (gmmsm_sequence_ind,MMPM_SEQUENCE_IND); +#else + PALLOC (gmmsm_sequence_ind,GMMSM_SEQUENCE_IND); +#endif + gmmsm_sequence_ind->c_npdu_list + = receive_n_pdu_number_list->c_receive_n_pdu_number_list_val; + for (i=0;i<receive_n_pdu_number_list->c_receive_n_pdu_number_list_val;i++) + { + gmmsm_sequence_ind->npdu_list[i].nsapi + = receive_n_pdu_number_list->receive_n_pdu_number_list_val[i].nsapi; + gmmsm_sequence_ind->npdu_list[i].receive_n_pdu_number_val + = receive_n_pdu_number_list->receive_n_pdu_number_list_val[i].receive_n_pdu_number_val; + } +#ifdef GMM_TCS4 + PSEND ( hCommUPM, gmmsm_sequence_ind ); +#else + PSEND ( hCommSM, gmmsm_sequence_ind ); +#endif + SET_STATE ( KERN, KERN_GMM_RAU_WAIT_FOR_NPDU_LIST ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_RAU_WAIT_FOR_NPDU_LIST ); +#endif + GMM_RETURN; + } + else + { + routing_area_update_complete->v_receive_n_pdu_number_list = 0; + if ( attach_complete ) + { + kern_rau_complete(result_value); + } + else + { + kern_rau_complete_end(result_value); + } + } + } + GMM_RETURN; +} /* kern_attach_complete () */ + + + +/* ++------------------------------------------------------------------------------ +| Function : kern_attach_accept ++------------------------------------------------------------------------------ +| Description : The label ATTACH_ACCEPT +| +| ATTACH and RAU accept procedure +| +| This procedure is called when the attach or rau accepüt message +| is received +| +| Parameters : message_id - RAU ACCEPT or ATTACH ACCEPT message +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_attach_accept +( + T_result_gmm * result, + T_force_to_standby * force_to_standby, + T_rau_timer * rau_timer, + /* attach: radio_priority */ + T_routing_area_identification *routing_area_identification, + BOOL v_p_tmsi_signature, + T_p_tmsi_signature * p_tmsi_signature, + BOOL v_ready_timer, + T_ready_timer * ready_timer, + BOOL v_gmobile_identity, + T_gmobile_identity * gmobile_identity, + BOOL v_mobile_identity, + T_mobile_identity * mobile_identity, + /* + * only RAU + */ + BOOL v_receive_n_pdu_number_list, + T_receive_n_pdu_number_list * receive_n_pdu_number_list, + USHORT cause, + BOOL v_eqv_plmn_list, /* TCS 2.1 */ + T_eqv_plmn_list * eqv_plmn_list, /* TCS 2.0 */ + BOOL v_t3302, + T_t3302 * t3302, + BOOL v_cell_notification +) +{ + GMM_TRACE_FUNCTION( "kern_attach_accept" ); + + TRACE_2_INFO("ACCEPT.rai.lac %#x rac %#x", + routing_area_identification->lac, + routing_area_identification->rac); + + gmm_data->kern.attach_cap.attach_acc_after_po = TRUE; + gmm_data->kern.timeout_t3312 = FALSE; + + if (v_t3302) + { + gmm_data->kern.t3302_val = rdy_get_timer ( (T_rau_timer *)t3302 ); + } + +#ifdef REL99 + /* If cell notification field is present GMM should update its + * context with the information. + * Whenever a LLGMM_TRIGGER_REQ is sent, this field should be + * checked. If it indicates that cell notification is supported + * GMM should inform this to LLC with a special cause value. + * LLC, on receiving this special cause value can use NULL frame + * for cell updates. + * The first cell notification shouldn't use LLC NULL frame. The + * values FIRST_CELL_NOTIFY and NOT_FIRST_CELL_NOTIFY are introduced + * to take care of this + */ +#endif + + + if (v_cell_notification) + { + +#ifdef REL99 + gmm_data->cell_notification = FIRST_CELL_NOTIFY; /* TCS 4.0 */ +#else + TRACE_0_INFO("R99: cell notification supported by network, but not supported by the MS"); +#endif + + } + +#ifdef REL99 + else /*SGSN doesn't support cell notification*/ /* TCS 4.0 */ + { /* TCS 4.0 */ + gmm_data->cell_notification = NO_CELL_NOTIFY; /* TCS 4.0 */ + } + +/* The following #ifdef is added due to a limitation in TDC. + * TDC in the current release(ver 14) doesn't support setting of T variables. + * So until the next release (ver 15) of TDC is available, this fix is needed + * for running GMM406X test cases. + */ +#ifdef _SIMULATION_ /* TCS 4.0 */ + gmm_data->cell_notification = gmm_data->config.cell_notification; /* TCS 4.0 */ +#endif /*_SIMULATION_*/ /* TCS 4.0 */ +#endif /* REL99 */ + + /* + * remove PLMN from forbiden list + */ + kern_remove_plmn_from_forbidden_list(gmm_data->kern.sig_cell_info.env.rai.plmn); + + kern_set_rai ( routing_area_identification ); + + if (GMM_NO_RAU != gmm_data->kern.attach_cap.rau_initiated) + { + result->result_value <<= 1; + result->result_value |= 1; + + } + /* + * the following is needed when calling kern_rau_complete() from + * within kern_gmmsm_sequence_res(): + */ + gmm_data->kern.attach_cap.result_type = result->result_value; + + + /* + * Reset RAU and ATTACH attempt counter + */ + if (!IS_CAUSE_INVALID (cause)) + { + gmm_data->kern.detach_cap.error_cause = cause; + + switch ( cause ) + { + case GMMCS_MSC_TEMP_NOT_REACHABLE: /* TCS 2.1 */ + case GMMCS_NET_FAIL: /* TCS 2.1 */ + case GMMCS_CONGESTION: /* TCS 2.1 */ + if ( COMBINED_ATTACHED == result->result_value ) + { + TRACE_0_INFO("#0x10 or #0x11 or #0x16 received together with COMBINED attach. Switched to NORMAL attached"); + result->result_value = NORMAL_ATTACHED; + } + /* 04.08 44.7.3.2.3.2 */ + /* special kern_attach_reset */ + gmm_data->kern.aac++; + gmm_data->kern.ct3310 = 0; + vsi_t_stop ( GMM_handle, kern_T3310); + break; + default: + kern_attach_reset(); + break; + } + } + else + { + gmm_data->kern.detach_cap.error_cause = GMMCS_INT_NOT_PRESENT; /* TCS 2.1 */ + kern_attach_reset(); + } + + sig_kern_rdy_force_ie_req + ( force_to_standby->force_to_standby_value , + v_mobile_identity || v_gmobile_identity);/*lint !e730 (Info -- Boolean argument to function) */ + + /* + * force to standby function has to be called before handling of the ready timer, because cu + * is not allowed upon force to standby + */ + sig_kern_rdy_t3314_req + ( (v_gmobile_identity && ID_TYPE_TMSI==gmobile_identity->type_of_identity) + || (gmobile_identity && ID_TYPE_TMSI==mobile_identity->type_of_identity) + || v_receive_n_pdu_number_list, /*lint !e730 (Info -- Boolean argument to function) *//*lint !e730 (Info -- Boolean argument to function) */ + v_ready_timer, + ready_timer, + rau_timer, + v_mobile_identity || v_gmobile_identity); + + /* + * this procedure transmittes the GSIM_UPDATE_REQ message + * and starts the kern_local_attach procedure + * + * <R.GMM.PATTCNF.M.001> + */ + /* Delete old signature if no signatur is included in attach_accept + or rau_accept primitive */ + if (!v_p_tmsi_signature) + { + gmm_data->ptmsi_signature.value = INVALID_PTMSI_SIGNATURE; + gmm_data->ptmsi_signature.available = FALSE; + } + kern_tmsi_negotiated ( + v_mobile_identity, + mobile_identity, + v_gmobile_identity, + gmobile_identity, + v_p_tmsi_signature, + p_tmsi_signature); + + + if (!IS_CAUSE_INVALID (cause)) + /* + * LABEL TMSI_CAUSE + */ + /* + * it is not required that i have to go to aac if an error cause + * is received in normal attach/rau mode + */ + { + if ( GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated + && AT_GPRS == gmm_data->kern.attach_cap.attach_proc_type ) + { + SET_STATE ( MM, GMM_MM_DEREG ); + kern_aac (cause); + GMM_RETURN; + } + switch ( cause ) + { + case GMMCS_IMSI_UNKNOWN: /* TCS 2.1 */ + { + gmm_data->tmsi = GMMRR_TMSI_INVALID; + gmm_data->kern.sig_cell_info.mm_status = MMGMM_LIMITED_SERVICE; + sig_kern_sync_set_mm_state(MMGMM_LIMITED_SERVICE); + + kern_mm_attach_rej (cause); + kern_attach_complete ( + result->result_value, + v_gmobile_identity && + ID_TYPE_TMSI==gmobile_identity->type_of_identity, /*lint !e730 (Info -- Boolean argument to function) */ + v_receive_n_pdu_number_list, receive_n_pdu_number_list );/*lint !e613 (Warning -- Possible use of null pointer 'gmobile_identity' in left argument to operator '->') */ + break; + } + case GMMCS_MSC_TEMP_NOT_REACHABLE: /* TCS 2.1 */ + case GMMCS_NET_FAIL: /* TCS 2.1 */ + case GMMCS_CONGESTION: /* TCS 2.1 */ + /* + * ERRCS_NETWORK_FAILURE + */ + + TRACE_1_INFO(" aac: %d", gmm_data->kern.aac ); + + /* this is already done. + */ + + if ( gmm_data->gu == GU1_UPDATED + && !kern_rai_changed() + && gmm_data->kern.aac < MAX_AAC ) + { + TRACE_EVENT ( "Info: START: T3311" ); + vsi_t_start ( GMM_handle , kern_T3311, gmm_data->kern.t3311_val ); + kern_mm_attach_rej (cause); + gmm_data->kern.attach_cap.attempting_to_update_mm = TRUE; + kern_attach_complete ( + result->result_value, + (v_gmobile_identity + && ID_TYPE_TMSI==gmobile_identity->type_of_identity) + || + (v_mobile_identity + && ID_TYPE_TMSI == mobile_identity->type_of_identity),/*lint !e730 (Info -- Boolean argument to function) */ + v_receive_n_pdu_number_list, receive_n_pdu_number_list);/*lint !e613 (Warning -- Possible use of null pointer 'gmobile_identity' in left argument to operator '->') */ + gmm_data->kern.attach_cap.rau_initiated=GMM_RAU; + } + else + { + vsi_t_start ( GMM_handle , kern_T3302, gmm_data->kern.t3302_val ); + sig_kern_rdy_start_t3302_req(); + TRACE_EVENT ( "Info: START: T3302" ); + TRACE_1_INFO ( "ATTACH or RAU will retried %.1f minutes later", + (gmm_data->kern.t3302_val/(60000.0))); + + switch ( gmm_data->kern.attach_cap.mobile_class) + { + case GMMREG_CLASS_A: + /* + * kern_mm_set_state ( MMGMM_ENTER_IDLE_MODE ); + */ + SET_STATE ( MM, GMM_MM_DEREG ); + kern_mm_lau(); + + kern_attach_complete ( + result->result_value, + (v_gmobile_identity + && ID_TYPE_TMSI==gmobile_identity->type_of_identity) + || + (v_mobile_identity + && ID_TYPE_TMSI == mobile_identity->type_of_identity),/*lint !e730 (Info -- Boolean argument to function) */ + v_receive_n_pdu_number_list, receive_n_pdu_number_list);/*lint !e613 (Warning -- Possible use of null pointer 'gmobile_identity' in left argument to operator '->') */ + GMM_RETURN; + default: + TRACE_ERROR("unexpected MS class"); + /* NO break; */ + case GMMREG_CLASS_BG: + case GMMREG_CLASS_BC: + case GMMREG_CLASS_B: + { + /* rau_initiated will be reset in attah_complete()*/ + BOOL no_rau= (GMM_NO_RAU == gmm_data->kern.attach_cap.rau_initiated); + kern_mm_attach_rej (cause); + + gmm_data->kern.attach_cap.attempting_to_update_mm = TRUE; + + kern_attach_complete ( + result->result_value, + (v_gmobile_identity + && ID_TYPE_TMSI==gmobile_identity->type_of_identity) + || + (v_mobile_identity + && ID_TYPE_TMSI == mobile_identity->type_of_identity),/*lint !e730 (Info -- Boolean argument to function) */ + v_receive_n_pdu_number_list, receive_n_pdu_number_list);/*lint !e613 (Warning -- Possible use of null pointer 'gmobile_identity' in left argument to operator '->') */ + + if ((no_rau && AT_GPRS != gmm_data->kern.attach_cap.attach_proc_type ) + || (!no_rau && + (COMBINED_RAU == gmm_data->kern.attach_cap.update_proc_type ) + || (COMBINED_RAU_IMSI_ATTACH == gmm_data->kern.attach_cap.update_proc_type ))) + { + + if (no_rau) + { + SET_STATE ( KERN, KERN_GMM_DEREG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_DEREG_SUSPENDING ); +#endif + } + else + { + /* 04.08 ch. 4.7..2.3 The MM sublayer shall act as in network operation mode II as long as the + combined GMM procedures are not successful and no new RA is entered. The new + MM state is MM IDLE. */ + gmm_data->kern.sig_cell_info.net_mode= GMMRR_NET_MODE_II; + TRACE_0_INFO ("changed to NMOII"); + + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING ); +#endif + kern_llgmm_suspend(LLGMM_CALL); + } + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + } + break; + case GMMREG_CLASS_CG: + /* + * <R.GMM.RCSUGPRS.M.020> + */ + kern_mm_attach_rej (cause); + + gmm_data->kern.attach_cap.attempting_to_update_mm = TRUE; + kern_attach_complete ( + result->result_value, + SEND_ATTACH_COMPLETE, + v_receive_n_pdu_number_list, receive_n_pdu_number_list); + break; + } + + } + break; + default: + kern_aac (cause); + break; + } + SET_STATE( MM, GMM_MM_DEREG ); + } + else + /* + * LABEL TMSI_NO_CAUSE + */ + { + /* + * <R.GMM.RCSUBOTH.M.019> + */ + kern_mm_attach_acc ( v_mobile_identity, mobile_identity, /* TCS 2.1 */ + v_eqv_plmn_list, eqv_plmn_list ); /* TCS 2.1 */ + + if ( COMBINED_ATTACHED == result->result_value ) + { + SET_STATE( MM, GMM_MM_REG_NORMAL_SERVICE ); + /* + * mm_lau_attempt is reset. It is only set if lau has been performed + * before via MM_procedures + */ + gmm_data->kern.attach_cap.mm_lau_attempted=FALSE; + } + else + { + if (GMM_MM_REG_INITATED_VIA_GPRS == GET_STATE(MM)) + { + TRACE_ERROR ("network has sent attach_accept (GPRS) w/o error cause but (COMB) has been requested"); + kern_mm_attach_rej(GMMCS_MESSAGE_INVALID); /* TCS 2.1 */ + } + } + + kern_attach_complete ( + result->result_value, + (v_gmobile_identity + && ID_TYPE_TMSI==gmobile_identity->type_of_identity) + || + (v_mobile_identity + && ID_TYPE_TMSI == mobile_identity->type_of_identity),/*lint !e730 (Info -- Boolean argument to function) */ + v_receive_n_pdu_number_list, receive_n_pdu_number_list);/*lint !e613 (Warning -- Possible use of null pointer 'gmobile_identity' in left argument to operator '->') */ + } + + GMM_RETURN; +} /* kern_attach_accept () */ + + +/* ++------------------------------------------------------------------------------ +| Function : kern_norm_rau ++------------------------------------------------------------------------------ +| Description : The label NORM_RAU +| +| Normal RAU +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void kern_norm_rau ( void ) +{ + GMM_TRACE_FUNCTION( "kern_norm_rau" ); + if (gmm_data->kern.timeout_t3312) + /* + * 24.008: + * If the MS is in other state than GMM-REGISTERED.NORMAL-SERVICE when the timer + * expires the periodic routing area updating procedure is delayed until the MS + * returns to GMM-REGISTERED.NORMAL-SERVICE. + * In GSM, if the MS in MS operation mode B is in the state GMM-REGISTERED. + * SUSPENDED when the timer expires the periodic routing area updating procedure + * is delayed until the state is left. + */ + { + kern_periodic_rau(); + GMM_RETURN; + } + + { + /* T_ROUTING_AREA_UPDATE_REQUEST */ + MCAST (routing_area_update_request,ROUTING_AREA_UPDATE_REQUEST); + + routing_area_update_request->v_gmobile_identity = FALSE; + routing_area_update_request->v_ms_network_capability = FALSE; + routing_area_update_request->v_pdp_context_status = FALSE; + + gmm_data->kern.attach_cap.update_proc_type = RAU; + + routing_area_update_request->update_type.update_type_value + = RAU; + TRACE_EVENT("Info: Normal RAU"); + + kern_rau_init(); + } + + GMM_RETURN; +} /* kern_norm_rau () */ + + +/* ++------------------------------------------------------------------------------ +| Function : kern_comb_rau ++------------------------------------------------------------------------------ +| Description : The label COMB_RAU +| +| Combined RAU +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ + +GLOBAL void kern_comb_rau ( void ) +{ + GMM_TRACE_FUNCTION( "kern_comb_rau" ); + if (gmm_data->kern.timeout_t3312) + /* + * 24.008: + * If the MS is in other state than GMM-REGISTERED.NORMAL-SERVICE when the timer + * expires the periodic routing area updating procedure is delayed until the MS + * returns to GMM-REGISTERED.NORMAL-SERVICE. + * In GSM, if the MS in MS operation mode B is in the state GMM-REGISTERED. + * SUSPENDED when the timer expires the periodic routing area updating procedure + * is delayed until the state is left. + */ + { + kern_periodic_rau(); + GMM_RETURN; + } + + gmm_data->kern.attach_cap.update_proc_type = COMBINED_RAU; + + { + /* T_ROUTING_AREA_UPDATE_REQUEST */ + MCAST (routing_area_update_request,ROUTING_AREA_UPDATE_REQUEST); + + routing_area_update_request->v_gmobile_identity = FALSE; + routing_area_update_request->v_ms_network_capability = FALSE; + routing_area_update_request->v_pdp_context_status = FALSE; + + if ( GMMREG_AT_GPRS != gmm_data->kern.attach_cap.attach_type + && GMMRR_TMSI_INVALID == gmm_data->tmsi ) + /* + * <R.GMM.RCINIT.M.016> + * + * 24.008 9.4.1.3. TMSI Status + * + * This IE shall be included if the MS performs a + * combined GPRS attach and no valid TMSI is available + */ + { + routing_area_update_request->v_tmsi_status = TRUE; + routing_area_update_request->tmsi_status.tmsi_flag = FALSE; + } + else + { + routing_area_update_request->v_tmsi_status = FALSE; + } + + + if ( GMM_MM_DEREG == GET_STATE(MM) + || gmm_data->kern.attach_cap.mm_lau_attempted) + { + gmm_data->kern.attach_cap.update_proc_type = COMBINED_RAU_IMSI_ATTACH; + routing_area_update_request->update_type.update_type_value + = COMBINED_RAU_IMSI_ATTACH; + TRACE_EVENT("Info: Comb. RAU with IMSI attach"); + } + else + { + gmm_data->kern.attach_cap.update_proc_type = COMBINED_RAU; + routing_area_update_request->update_type.update_type_value + = COMBINED_RAU; + TRACE_EVENT("Info: Comb. RAU"); + } + } + + kern_mm_attach_started (); + kern_rau_init(); + GMM_RETURN; +} /* kern_comb_rau () */ + + +/* ++------------------------------------------------------------------------------ +| Function : kern_rau_limited ++------------------------------------------------------------------------------ +| Description : The label RAU_LIMITED +| +| Start of RAU without supention of the rest of the world +| beacause the rest is already suspended +| +| Parameters : void +| ++------------------------------------------------------------------------------ +*/ +GLOBAL void kern_rau_limited ( void ) +{ + GMM_TRACE_FUNCTION( "kern_rau_limited" ); + + switch ( gmm_data->kern.sig_cell_info.net_mode ) + { + case GMMRR_NET_MODE_I: + if (GMM_MM_DEREG != GET_STATE(MM) + || GMMREG_AT_COMB==gmm_data->kern.attach_cap.attach_type) + { + kern_comb_rau(); + } + else + { + kern_norm_rau(); + } + break; + case GMMRR_NET_MODE_II: + if (kern_lau_needed()) + /* + * if deatch procedure collision and GSM is already detached we can start + * rau + */ + { + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + kern_norm_rau(); + } + break; + case GMMRR_NET_MODE_III: + switch ( gmm_data->kern.attach_cap.mobile_class) + { + case GMMREG_CLASS_A: + TRACE_ERROR ("ClassA not supported"); + break; + case GMMREG_CLASS_BG: + if ( GMM_MM_DEREG != GET_STATE(MM) ) + { + if (kern_lau_needed()) + /* + * First update than detach!!! + */ + { + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + kern_imsi_detach_reg_susp(); + } + } + else + { + kern_norm_rau(); + } + break; + case GMMREG_CLASS_BC: + if (GMMREG_AT_GPRS == gmm_data->kern.attach_cap.attach_type) + { + kern_norm_rau(); + } + else + /* + * GSM attach_type + */ + { + if ( kern_lau_needed()) + { + SET_STATE ( KERN, KERN_GMM_REG_SUSPENDING ); +#ifdef FF_EM_MODE + EM_GMM_SET_STATE(KERN_GMM_REG_SUSPENDING ); +#endif + kern_gmmrr_suspend (GMMRR_SUSP_GPRS, GMMRR_NORMAL_RELEASE, GMM_SUSP_LAU); + } + else + { + if (kern_rai_changed()) + { + kern_norm_rau(); + } + else + { + gmm_data->kern.detach_cap.detach_type = GMMREG_DT_GPRS; + kern_detach(); + } + } + } + break; + case GMMREG_CLASS_CG: + kern_norm_rau(); + break; + default: + break; + } + + break; + default: + TRACE_ERROR ("unknown netmode"); + break; + } + GMM_RETURN; +} /* kern_rau_limited () */