FreeCalypso > hg > freecalypso-sw
view gsm-fw/g23m-gsm/mm/mm_mmp.c @ 876:c9f353b5d70c
rvinterf/asyncshell/rxctl.c: buglet in the implementation of dis/enable commands
author | Space Falcon <falcon@ivan.Harhan.ORG> |
---|---|
date | Sat, 30 May 2015 07:50:05 +0000 |
parents | 1f78e5fda218 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS (8410) | Modul : MM_MMP +----------------------------------------------------------------------------- | 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 defines the functions for the mob. management | capability of the module Mobility Management. +----------------------------------------------------------------------------- */ #ifndef MM_MMP_C #define MM_MMP_C #include "config.h" #include "fixedconf.h" #include "condat-features.h" #define ENTITY_MM /*==== INCLUDES ===================================================*/ #if defined (NEW_FRAME) #include <string.h> #include <stdlib.h> #include <stddef.h> #include "typedefs.h" #include "pcm.h" #include "pconst.cdg" #include "mconst.cdg" #include "message.h" #include "ccdapi.h" #include "vsi.h" #include "custom.h" #include "gsm.h" #include "prim.h" #include "cnf_mm.h" #include "mon_mm.h" #include "pei.h" #include "tok.h" #include "mm.h" #include "mm_em.h" #else #include <string.h> #include <stdlib.h> #include <stddef.h> #include "stddefs.h" #include "pcm.h" #include "pconst.cdg" #include "mconst.cdg" #include "message.h" #include "ccdapi.h" #include "custom.h" #include "gsm.h" #include "prim.h" #include "cnf_mm.h" #include "mon_mm.h" #include "vsi.h" #include "pei.h" #include "tok.h" #include "mm.h" #include "mm_em.h" #endif /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ /*==== TEST =====================================================*/ /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ LOCAL void mm_rr_abort_cell_sel_fail (T_RR_ABORT_IND *rr_abort_ind); LOCAL void mm_mmcm_ss_sms_data_req (T_VOID_STRUCT *mm_data_req); LOCAL void mm_sim_insert_state (void); /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_est_rr_for_cm | +--------------------------------------------------------------------+ PURPOSE : Establish a RR connection for any CM entity. If this is possible, e.g. GPRS is not active/delivered or CM establishment is allowed by GPRS, the RR_ESTABLISH_REQ is sent and state MM_WAIT_FOR_RR_CONN_MM is entered. Otherwise GMM is informed about the CM connection request and the primitive is saved for later usage, but no state change is done. */ LOCAL void mm_est_rr_for_cm (UBYTE comp, UBYTE ti, USHORT estcs) { GET_INSTANCE_DATA; UBYTE service; TRACE_FUNCTION ("mm_est_rr_for_cm()"); #ifdef WIN32 TRACE_EVENT_P3 (" comp = %d, ti = %d, estcs = %x", comp, ti, estcs); #endif /* #ifdef WIN32 */ switch (comp) { case CC_COMP: if (estcs EQ MMCM_ESTCS_EMERGE) service = EMERGENCY_SERVICE; else service = CALL_SERVICE; break; case SS_COMP: estcs = ESTCS_MOB_ORIG_CAL_BY_SS_SMS; /* Override estcs */ service = SS_SERVICE; break; case SMS_COMP: estcs = ESTCS_MOB_ORIG_CAL_BY_SS_SMS; /* Override estcs */ service = SMS_SERVICE; break; default: TRACE_ERROR (UNEXPECTED_PARAMETER); return; } mm_data->act_retrans = INTERNAL_REDIAL; if (estcs EQ MMCM_ESTCS_EMERGE) { /* * Establish RR connection for emergency call */ #ifdef GPRS if (mm_cm_est_allowed()) { #endif mm_data->idle_substate = GET_STATE (STATE_MM); mm_rr_est_req (estcs, service, ti); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_MM); #ifdef GPRS } else { mm_mmgmm_cm_emergency_ind (); mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); } #endif } else { /* * Establish RR connection for normal call, SS or SMS */ #ifdef GPRS if (mm_cm_est_allowed()) { #endif mm_data->idle_substate = GET_STATE (STATE_MM); mm_rr_est_req (estcs, service, ti); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_MM); #ifdef GPRS } else { mm_mmgmm_cm_establish_ind (); mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); } #endif } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmxx_release_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitives MMCM_RELEASE_REQ, MMSS_RELEASE_REQ and MMSMS_RELEASE_REQ. */ LOCAL void mm_mmxx_release_req (UBYTE comp, UBYTE ti) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_mmxx_release_req()"); switch (GET_STATE (STATE_MM)) { case MM_LUP_INITIATED: case MM_IMSI_DETACH_INIT: case MM_WAIT_FOR_NW_CMD: case MM_LUP_REJECTED: case MM_WAIT_FOR_RR_CONN_LUP: case MM_WAIT_FOR_RR_CONN_DETACH: /* * RR connection requested/established. Only delete the request from CM, * but do not inform GMM now until connection released. */ mm_delete_entry (comp, ti); break; case MM_WAIT_FOR_RR_ACTIVE: case MM_IDLE_NORMAL_SERVICE: /* 19.1 */ case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */ case MM_IDLE_LIMITED_SERVICE: /* 19.3 */ case MM_IDLE_NO_IMSI: /* 19.4 */ case MM_IDLE_NO_CELL_AVAILABLE: /* 19.5 */ case MM_IDLE_PLMN_SEARCH: /* 19.7 */ case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */ #ifdef GPRS case MM_IDLE_LUP_NEEDED: /* 19.6 */ case MM_LOCATION_UPDATING_PENDING: case MM_IMSI_DETACH_PENDING: #endif /* GPRS */ mm_delete_entry (comp, ti); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_OK); break; case MM_WAIT_FOR_OUTG_MM_CONN: if ((mm_data->pend_conn.comp EQ comp) AND (mm_data->pend_conn.ti EQ ti)) { MCAST (cm_serv_abort, U_CM_SERV_ABORT); CM_SET_STATE (comp, mm_data->pend_conn.ti, CM_IDLE); cm_serv_abort->msg_type = U_CM_SERV_ABORT; for_data_req (BSIZE_U_CM_SERV_ABORT); EM_SERVICE_ABORTED; TIMERSTOP (T3230); #if defined (FF_EOTD) AND defined (REL99) /* * check the flag rrlp_lcs_started value. True if rrlp is running, False * if no rrlp is runnig. */ if(mm_data->rrlp_lcs_started EQ TRUE) { /* * Enter state MM_RR_CONN_RELEASE_NOT_ALLOWED only if the last * active MM connection has been released by the CM layer * and there is rrlp service on going. */ TIMERSTART (T3241, T_3241_VALUE); SET_STATE (STATE_MM, MM_RR_CONN_RELEASE_NOT_ALLOWED); } else #endif /* (FF_EOTD) AND defined (REL99) */ { TIMERSTART (T3240, T_3240_VALUE); mm_data->wait_for_accept = FALSE; SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); } } else { mm_delete_entry (comp, ti); } break; case MM_CONN_ACTIVE: switch (CM_GET_STATE (comp, ti)) { case CM_STORE: mm_delete_entry (comp, ti); break; case CM_PENDING: mm_data->wait_for_accept = FALSE; CM_SET_STATE (comp, ti, CM_IDLE); break; case CM_ACTIVE: CM_SET_STATE (comp, ti, CM_IDLE); if ((mm_count_connections (CM_ACTIVE) EQ 0) AND !TIMERACTIVE (T3230)) { #if defined (FF_EOTD) AND defined (REL99) /*check the flag rrlp_lcs_started value. True if rrlp is running, False if no rrlp is runnig.*/ if(mm_data->rrlp_lcs_started EQ TRUE) { /* * Enter state MM_RR_CONN_RELEASE_NOT_ALLOWED only if the last * active MM connection has been released by the CM layer * and there is rrlp service on going. */ TIMERSTART (T3241, T_3241_VALUE); SET_STATE (STATE_MM, MM_RR_CONN_RELEASE_NOT_ALLOWED); } else #endif /* (FF_EOTD) AND defined (REL99) */ { /* * Enter state MM_WAIT_FOR_NW_CMD only if the last * active MM connection has been released by the CM layer * and there is no pending connection. Otherwise keep state. */ TIMERSTART (T3240, T_3240_VALUE); SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); } } break; default: break; } break; case MM_PROCESS_PROMPT: switch (CM_GET_STATE (comp, ti)) { case CM_STORE: mm_delete_entry (comp, ti); break; case CM_PENDING: /* * In state MM_PROCESS_PROMPT there are never pending connections, * so these need not be handled here */ TRACE_ERROR ("CM_PENDING?"); break; case CM_ACTIVE: CM_SET_STATE (comp, ti, CM_IDLE); if (mm_count_connections (CM_ACTIVE) EQ 0) { /* * Last active connection released, but * PROMPT remains present. Only START T3240 */ TIMERSTART (T3240, T_3240_VALUE); } break; default: break; } break; case MM_WAIT_FOR_RR_CONN_MM: if (mm_data->pend_conn.comp EQ comp AND mm_data->pend_conn.ti EQ ti) { CM_SET_STATE (comp, mm_data->pend_conn.ti, CM_IDLE); mm_abort_connection (ABCS_NORM); TIMERSTOP (T3230); /* After RR_ABORT_REQ here, RR_RELEASE_IND is guaranteed by RR */ } else { mm_delete_entry (comp, ti); } break; case MM_WAIT_FOR_REESTABLISH: switch (CM_GET_STATE (comp, ti)) { case CM_IDLE: case CM_PENDING: break; case CM_STORE: mm_delete_entry (comp, ti); break; case CM_ACTIVE: /* CC will not start call reestablishment, * then clear connection status */ CM_SET_STATE (comp, ti, CM_IDLE); /* this was the last answer from MM */ if (mm_count_connections (CM_ACTIVE) EQ 0) { /* there was no connection requesting call reestablishment */ if ( mm_count_connections (CM_REEST_PENDING) EQ 0) { /* Find IDLE state after MM connection */ mm_release_rr_connection (MMGMM_RESUMPTION_FAILURE); } else { /* * RR has already signalled a cell which is * suitable for call reestablishment * This could be explained to me. Why is in the release * routine reestablishment performed. I never understood * the problem which was solved here. Implementation problem? ... */ if (mm_data->reest_cell_avail) mm_reest (mm_data->reest_ti); } } break; } break; default: break; } } /*==== VARIABLES ==================================================*/ GLOBAL UBYTE _decodedMsg [MAX_MSTRUCT_LEN_MM]; /*==== FUNCTIONS ==================================================*/ /* * ------------------------------------------------------------------- * PRIMITIVE Processing functions * ------------------------------------------------------------------- */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_init_mm_data | +--------------------------------------------------------------------+ PURPOSE : Initialize the MM data for the module mob. management. */ GLOBAL void mm_init_mm_data (void) { GET_INSTANCE_DATA; USHORT i; TRACE_FUNCTION ("mm_init_mm_data()"); #if defined (NEW_FRAME) for (i = 0; i < NUM_OF_MM_TIMERS; i++) mm_data->t_running[i] = FALSE; #else for (i = 0; i < NUM_OF_MM_TIMERS; i++) mm_data->t_handle[i] = VSI_ERROR; #endif mm_init (); reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE); mm_data->state[STATE_MM] = MM_NULL; #ifdef GPRS mm_data->state[STATE_REG_TYPE] = REG_GPRS_INACTIVE; mm_data->state[STATE_GPRS_CM_EST] = CM_GPRS_EST_OK; #endif /* GPRS */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mdl_error_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MDL_ERROR_IND. */ GLOBAL void mm_mdl_error_ind (T_MDL_ERROR_IND *mdl_error_ind) { TRACE_FUNCTION ("mm_mdl_error_ind()"); #if 0 /* * No MDL_RELEASE_REQ is needed in DL for fatal reasons, * as DL already automatically releases the DL connection if such * a fatal reason occurs. The opposite is true: This function * will disturb DL operation if it sends a MDL_RELEASE_REQ * after receiving MDL_ERROR_IND with cause CS_T200_EXP in case * of a switch back to the old channel on handover failure. * * The communication path between DL and MM may have been a * general misdecision in design, this has still to be discussed. */ switch (GET_STATE (STATE_MM)) { case MM_NULL: case MM_IDLE_NO_CELL_AVAILABLE: /* * no DL is active */ break; default: /* * Handling depending on the error cause */ switch (mdl_error_ind->cs) { case CS_T200_EXP: case CS_UNSOL_DM_RESP: case CS_UNSOL_DM_RESP_MULT_FRM: case CS_NR_SEQ_ERR: switch (mdl_error_ind->sapi) { case SAPI_0: mm_mdl_rel_req (); break; case SAPI_3: mm_mdl_rel_req_sapi_3 (); break; } break; } break; } #endif PFREE (mdl_error_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_data_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_DATA_REQ. */ GLOBAL void mm_mmcm_data_req (T_MMCM_DATA_REQ *mmcm_data_req) { TRACE_FUNCTION ("mm_mmcm_data_req()"); mm_mmcm_ss_sms_data_req ( (T_VOID_STRUCT*)mmcm_data_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmxx_establish_req | +--------------------------------------------------------------------+ PURPOSE : Process MMCM_ESTABLISH_REQ, MMSS_ESTABLISH_REQ and MMSMS_ESTABLISH_REQ finally. This is a generic function which handles the establishment for all CM entities. */ GLOBAL void mm_mmxx_establish_req (UBYTE comp, UBYTE ti, USHORT estcs, U8 info) { GET_INSTANCE_DATA; UBYTE service; restart_function: TRACE_FUNCTION ("mm_mmxx_establish_req()"); switch (comp) { case CC_COMP: if (estcs EQ MMCM_ESTCS_EMERGE) service = EMERGENCY_SERVICE; else service = CALL_SERVICE; break; case SS_COMP: service = SS_SERVICE; break; case SMS_COMP: service = SMS_SERVICE; break; default: TRACE_ERROR (UNEXPECTED_DEFAULT); /* Cannot happen */ return; /* No action which makes sense possible here */ } #ifdef GPRS if ((mm_data->gprs.mobile_class EQ MMGMM_CLASS_CG) OR (mm_data->gprs.sim_physically_removed AND (service NEQ EMERGENCY_SERVICE))) { /* * 1.) No CS services with a PS only mobile, * for MMGMM_CLASS_BG MM has to ask * 2.) SIM removal, GMM detaching and call request requiring SIM * => release the call */ mm_mmxx_release_ind (comp, ti, MMCS_NO_REGISTRATION); return; } #endif /* #ifdef GPRS */ switch (GET_STATE (STATE_MM)) { case MM_NULL: case MM_IDLE_NO_CELL_AVAILABLE: /* * without coverage no calls ! */ mm_mmxx_release_ind (comp, ti, MMCS_NO_REGISTRATION); break; case MM_LUP_INITIATED: case MM_WAIT_FOR_OUTG_MM_CONN: case MM_PROCESS_PROMPT: case MM_WAIT_FOR_NW_CMD: case MM_LUP_REJECTED: case MM_WAIT_FOR_RR_CONN_LUP: case MM_WAIT_FOR_RR_CONN_MM: case MM_WAIT_FOR_REESTABLISH: case MM_WAIT_FOR_RR_ACTIVE: #ifdef GPRS case MM_LOCATION_UPDATING_PENDING: #endif /* GPRS */ mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); break; #ifdef REL99 case MM_RR_CONN_RELEASE_NOT_ALLOWED: /*Upon reception of CM establishment request, MM will stop the timer 3241 & *shall send mm_rr_data_request. Upon reception of cm service accept from *network MM enter in MM_CONN_ACTIVE state. */ TIMERSTOP (T3241); mm_rr_data_req (estcs, service, ti); TIMERSTART (T3230, T_3230_VALUE); SET_STATE (STATE_MM, MM_WAIT_FOR_OUTG_MM_CONN); break; #endif case MM_CONN_ACTIVE: if (mm_data->wait_for_accept) { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); } else { /* * There is a rare, unhandled case: * MM_CONN_ACTIVE and the service state is not full service, * we have an ongoing emergency call. In this case MM should * reject the establish request, but this is not critical here. */ mm_rr_data_req (estcs, service, ti); TIMERSTART (T3230, T_3230_VALUE); } break; case MM_IMSI_DETACH_INIT: case MM_WAIT_FOR_RR_CONN_DETACH: #ifdef GPRS case MM_IMSI_DETACH_PENDING: #endif /* GPRS */ if (mm_data->nreg_cause EQ CS_SIM_REM AND estcs EQ MMCM_ESTCS_EMERGE) { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); } else { mm_mmxx_release_ind (comp, ti, MMCS_NO_REGISTRATION); } break; case MM_IDLE_NORMAL_SERVICE: mm_est_rr_for_cm (comp, ti, estcs); break; #ifdef GPRS case MM_IDLE_LUP_NEEDED: /* * Inform GMM about the wish to establish a RR connection * for CM. Either GMM will accept this and bring MM into * IDLE updated state or GMM will refuse this. * The final decision is left to GMM here. */ if (estcs EQ MMCM_ESTCS_EMERGE) { /* * Emergency call */ mm_mmxx_rel_ind (MMCS_INT_PREEM, CM_NOT_IDLE); mm_est_rr_for_cm (comp, ti, estcs); } else { /* * Normal call */ if (mm_cm_est_allowed()) { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, CM_LUP_TRIGGER); if (info EQ UNSPEC) { SET_STATE (STATE_REG_TYPE, REG_REMOTE_CONTROLLED); mm_normal_loc_upd (); } } else { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); mm_mmgmm_cm_establish_ind (); } } break; #endif /* GPRS */ case MM_IDLE_ATTEMPT_TO_UPDATE: if (info NEQ CM_LUP_TRIGGER) mm_data->attempt_cnt = 0; if (estcs EQ MMCM_ESTCS_EMERGE) { /* * Emergency call */ mm_mmxx_rel_ind (MMCS_INT_PREEM, CM_NOT_IDLE); mm_est_rr_for_cm (comp, ti, estcs); } else { /* * 'info' is used to check to see where this function was called. * If this function was called from 'mm_mmcm_establish_req()' then * this is the first pass for this function and 'mm_normal_loc_upd()' * must be called according to the Recs. * If the function was called from 'mm_use_entry()', then it means * an existing CM request is stored in the MM local stack and the current * MM procedure is running for that entry. Subsequent calls of 'mm_use_entry()' * must be ignored i.e. mm_normal_loc_upd()' must *not* be called. */ /* * Normal call */ if (mm_cm_est_allowed()) { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, CM_LUP_TRIGGER); if (info EQ UNSPEC) { #ifdef GPRS if (!mm_lup_allowed_by_gmm()) { SET_STATE (STATE_REG_TYPE, REG_REMOTE_CONTROLLED); } #endif mm_normal_loc_upd (); } } else { mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); mm_mmgmm_cm_establish_ind (); } } break; case MM_IDLE_LIMITED_SERVICE: case MM_IDLE_NO_IMSI: if (estcs EQ MMCM_ESTCS_EMERGE) { mm_est_rr_for_cm (comp, ti, estcs); } else { mm_mmxx_release_ind (comp, ti, MMCS_NO_REGISTRATION); } break; case MM_IDLE_PLMN_SEARCH: mm_write_entry (comp, ti, estcs, EVENT_ENTRY, NULL, UNSPEC); if (estcs EQ MMCM_ESTCS_EMERGE) { mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); mm_rr_act_req (); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_ACTIVE); } break; case MM_PLMN_SEARCH_NORMAL_SERVICE: /* Indicate stop of search to the MMI */ mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); /* Back to IDLE state before network search was started, * as establishment will stop network search in RR */ SET_STATE (STATE_MM, mm_data->idle_substate); /* Repeat the establish attempt in new MM state */ /* -- mm_mmxx_establish_req (comp, ti, estcs,info); -- */ /* -- return; -- */ /* avoid recursion, stack usage, therefore the goto. */ goto restart_function; /*lint !e801 goto*/ default: TRACE_ERROR (UNEXPECTED_DEFAULT); /* All states caught */ break; } } /* mm_mmxx_establish_req() */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_establish_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_ESTABLISH_REQ. */ GLOBAL void mm_mmcm_establish_req (T_MMCM_ESTABLISH_REQ *mmcm_establish_req) { TRACE_FUNCTION ("mm_mmcm_establish_req()"); /* * And from this point MM is not interested in prio anymore. * To distinguish emergency calls from normal calls estcs is used. */ switch (mmcm_establish_req->org_entity) { case MMCM_ORG_ENTITY_CC: mm_mmxx_establish_req (CC_COMP, mmcm_establish_req->ti, mmcm_establish_req->estcs, UNSPEC); break; case MMCM_ORG_ENTITY_SS: mm_mmxx_establish_req (SS_COMP, mmcm_establish_req->ti, 0,UNSPEC); break; case MMCM_ORG_ENTITY_SMS: mm_mmxx_establish_req (SMS_COMP, mmcm_establish_req->ti, 0,UNSPEC); break; default: TRACE_ERROR ("org_entity trashed"); break; } PFREE (mmcm_establish_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mmcm_reestablish_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_REESTABLISH_REQ. */ GLOBAL void mm_mmcm_reestablish_req (T_MMCM_REESTABLISH_REQ *mmcm_reestablish_req) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_mmcm_reestablish_req()"); switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_REESTABLISH: /* set re-establishment transaction identifier if not already set */ if (mm_data->reest_ti EQ NOT_PRESENT_8BIT) mm_data->reest_ti = mmcm_reestablish_req->ti; /* set connection type to reestablishment pending */ CM_SET_STATE (CC_COMP, mmcm_reestablish_req->ti, CM_REEST_PENDING); /* all CM connection have answered and * RR has signalled a suitable cell for call reestablishment */ if (mm_count_connections (CM_ACTIVE) EQ 0 AND mm_data->reest_cell_avail) mm_reest (mm_data->reest_ti); break; default: break; } PFREE (mmcm_reestablish_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_release_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_RELEASE_REQ. */ GLOBAL void mm_mmcm_release_req (T_MMCM_RELEASE_REQ *mmcm_release_req) { TRACE_FUNCTION ("mm_mmcm_release_req()"); mm_mmxx_release_req (CC_COMP, mmcm_release_req->ti); PFREE (mmcm_release_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmss_data_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSS_DATA_REQ. */ GLOBAL void mm_mmss_data_req (T_MMSS_DATA_REQ *mmss_data_req) { TRACE_FUNCTION ("mm_mmss_data_req()"); mm_mmcm_ss_sms_data_req ( (T_VOID_STRUCT*)mmss_data_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmss_establish_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSS_ESTABLISH_REQ. */ GLOBAL void mm_mmss_establish_req (T_MMSS_ESTABLISH_REQ *mmss_establish_req) { TRACE_FUNCTION ("mm_mmss_establish_req()"); mm_mmxx_establish_req (SS_COMP, mmss_establish_req->ti, 0, UNSPEC); PFREE (mmss_establish_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmss_release_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSS_RELEASE_REQ. */ GLOBAL void mm_mmss_release_req (T_MMSS_RELEASE_REQ *mmss_release_req) { TRACE_FUNCTION ("mm_mmss_release_req()"); mm_mmxx_release_req (SS_COMP, mmss_release_req->ti); PFREE (mmss_release_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmsms_data_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSMS_DATA_REQ. */ GLOBAL void mm_mmsms_data_req (T_MMSMS_DATA_REQ *mmsms_data_req) { TRACE_FUNCTION ("mm_mmsms_data_req()"); mm_mmcm_ss_sms_data_req ( (T_VOID_STRUCT*)mmsms_data_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmsms_establish_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSMS_ESTABLISH_REQ. */ GLOBAL void mm_mmsms_establish_req (T_MMSMS_ESTABLISH_REQ *mmsms_establish_req) { TRACE_FUNCTION ("mm_mmsms_establish_req()"); mm_mmxx_establish_req (SMS_COMP, mmsms_establish_req->ti, 0, UNSPEC); PFREE (mmsms_establish_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmsms_release_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMSMS_RELEASE_REQ. */ GLOBAL void mm_mmsms_release_req (T_MMSMS_RELEASE_REQ *mmsms_release_req) { TRACE_FUNCTION ("mm_mmsms_release_req()"); mm_mmxx_release_req (SMS_COMP, mmsms_release_req->ti); PFREE (mmsms_release_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_abort_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ABORT_IND. */ GLOBAL void mm_rr_abort_ind (T_RR_ABORT_IND *rr_abort_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_abort_ind()"); mm_data->t3213_restart = MAX_REST_T3213; /* * If MM is reading sim and waiting for the SIM_READ_CNF for the EF PLMNsel * /EF EFPLMNwAcT/EFOPLMNwAcT which are used to prepare pref_plmn list. * rr_abort_ind will be stored if plmn_avail is indicated and will be used * once sim_read_cnf is received. */ if (mm_data->reg.sim_read_in_progress AND rr_abort_ind->plmn_avail >0) { mm_write_entry(NO_ENTRY,NO_ENTRY,NO_ENTRY,PRIMITIVE_ENTRY,rr_abort_ind, UNSPEC); return; } #ifdef WIN32 /* Check for correct cause value */ switch (rr_abort_ind->cause) { case RRCS_ABORT_CEL_SEL_FAIL: case RRCS_ABORT_RAD_LNK_FAIL: case RRCS_DATA_LINK_FAIL: case RRCS_ABORT_PTM: break; default: TRACE_ERROR("Unexpected cause value"); assert (0); /* Stop the simulation */ break; } #endif /* #ifdef WIN32 */ EM_RESULT_PLMN_LIST; TRACE_EVENT_P1 ("SERVICE = %d", rr_abort_ind->op.service); /* This switch statement is used to catch the case where the RR_ABORT_IND sent in state */ /* MM_LUP_INITIATED triggers a second RR_ABORT_IND received in state MM_IDLE_NORMAL_SERVICE */ /* caused by a TABORT timeout. The second RR_ABORT_IND (containing zero plmns) is subsequently */ /* ignored. This situation occurs when running TC 26.7.4.3.4 */ switch(GET_STATE (STATE_MM)) { case MM_LUP_INITIATED: mm_data->rr_abort_prior_to_tabort = TRUE; break; case MM_IDLE_NORMAL_SERVICE: break; default: mm_data->rr_abort_prior_to_tabort = FALSE; break; } if (rr_abort_ind->op.service EQ LIMITED_SERVICE) mm_data->rf_power = rr_abort_ind->power; switch (GET_STATE (STATE_MM)) { case MM_NULL: break; case MM_LUP_INITIATED: TIMERSTOP (T3210); mm_mdl_rel_req (); mm_lup_restart (); break; case MM_WAIT_FOR_OUTG_MM_CONN: case MM_CONN_ACTIVE: case MM_PROCESS_PROMPT: case MM_WAIT_FOR_NW_CMD: #ifdef REL99 case MM_RR_CONN_RELEASE_NOT_ALLOWED: #endif mm_mdl_rel_req (); TIMERSTOP (T3230); TIMERSTOP (T3240); #ifdef REL99 TIMERSTOP (T3241); #endif mm_mmxx_rel_ind (rr_abort_ind->cause, CM_PENDING); if (mm_mmxx_err_ind (rr_abort_ind->cause) NEQ 0) { /* * Active connections exist (CM_ACTIVE), remember that * CC has not yet signalled a valid ti for call re-establishment and * RR has not yet indicated a cell which is able to process call * re-establishment. Enter MM state MM_WAIT_FOR_REESTABLISH. */ mm_data->reest_ti = NOT_PRESENT_8BIT; mm_data->reest_cell_avail = FALSE; SET_STATE (STATE_MM, MM_WAIT_FOR_REESTABLISH); } else { /* No active CM connection. Find IDLE state after MM connection. */ mm_release_rr_connection (MMGMM_RESUMPTION_FAILURE); } break; case MM_IMSI_DETACH_INIT: case MM_WAIT_FOR_RR_CONN_DETACH: mm_mdl_rel_req (); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); mm_end_of_detach (); break; case MM_LUP_REJECTED: mm_mdl_rel_req (); TIMERSTOP (T3240); mm_loc_upd_rej (); break; case MM_WAIT_FOR_RR_CONN_LUP: if (rr_abort_ind->op.func EQ FUNC_NET_SRCH_BY_MMI) { /* * A running parallel search has been interrupted by a * location updating procedure. The sequence is * RR_ACTIVATE_REQ (MMI SEARCH) / RR_ACTIVATE_IND (new LA) * RR_ESTABLISH_REQ (LUP request) / RR_ABORT_IND (MMI SEARCH) * In this case we abort the pending search to the upper layers * and continue with our location updating procedure. */ mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); } else { /* * The RR_ABORT_IND is not indicating the end of a search for * available networks. */ TIMERSTOP (T3210); mm_mdl_rel_req (); if (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL) { TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); switch (rr_abort_ind->op.service) { case NO_SERVICE: SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); break; case LIMITED_SERVICE: SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); break; default: /* eg. FULL_SERVICE and reg_rr_failure => nonsense */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } reg_rr_failure (rr_abort_ind); } else { mm_lup_restart (); } } break; case MM_WAIT_FOR_RR_CONN_MM: if (rr_abort_ind->op.func EQ FUNC_NET_SRCH_BY_MMI) { /* * Handle MMXXX_NET_REQ followed by MMGXXX_PLMN_RES during network * running search. MMXXX_NET_REQ is leading to establishment for MM's * location updating, this aborts the network search in RR. * Don't send probably partial or empty list to the MMI and avoid * MMXXX_NREG_IND in this situation, as this could be interpreted * by GMM as end of the procedure (which it is not). * Instead, send simply MMXXX_PLMN_IND (MMCS_PLMN_NOT_IDLE_MODE). */ mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); } else { mm_mdl_rel_req (); if (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL) { TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; if (rr_abort_ind->op.service EQ NO_SERVICE) { mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); reg_rr_failure (rr_abort_ind); } else { if (mm_data->pend_conn.cause EQ MMCM_ESTCS_EMERGE) { /* * Clash RR_ESTABLISH_REQ (emergency call) / * RR_ABORT_IND (limited service). * RR dropped the RR_ESTABLISH_REQ. * Repeat the emergency call attempt. */ mm_rr_est_req (mm_data->pend_conn.cause, mm_data->pend_conn.service, mm_data->pend_conn.ti); /* Remain in state MM_WAIT_FOR_RR_CONN_MM */ } else { mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); reg_rr_failure (rr_abort_ind); } } } else { /* * Is data link failure possible here? Release pending connection. */ mm_mmxx_rel_ind (rr_abort_ind->cause, CM_PENDING); mm_release_rr_connection (MMGMM_RESUMPTION_FAILURE); } } break; case MM_WAIT_FOR_REESTABLISH: case MM_IDLE_ATTEMPT_TO_UPDATE: case MM_IDLE_LIMITED_SERVICE: mm_mdl_rel_req (); mm_rr_abort_cell_sel_fail( rr_abort_ind); break; case MM_IDLE_NO_IMSI: /* * During limited service without SIM card * the no service condition is signalled by RR. */ mm_mdl_rel_req (); if (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL AND rr_abort_ind->op.service EQ NO_SERVICE) { TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); reg_rr_failure (rr_abort_ind); } break; case MM_IDLE_NORMAL_SERVICE: TIMERSTOP (T3213); mm_data->t3213_restart = 0; /*Check to see if this RR_ABORT_IND is caused by a RR TABORT timeout...*/ if((mm_data->rr_abort_prior_to_tabort EQ TRUE) && (rr_abort_ind->plmn_avail EQ 0)) { mm_data->rr_abort_prior_to_tabort = FALSE; PFREE (rr_abort_ind); return; } /*lint -fallthrough */ #ifdef GPRS case MM_IDLE_LUP_NEEDED: #endif /* GPRS */ mm_mdl_rel_req (); mm_rr_abort_cell_sel_fail( rr_abort_ind); break; case MM_IDLE_NO_CELL_AVAILABLE: if (rr_abort_ind->op.service NEQ NO_SERVICE) { mm_data->reg.bcch_encode = FALSE; SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); reg_rr_failure (rr_abort_ind); } break; case MM_WAIT_FOR_RR_ACTIVE: if (mm_data->reg.op.func EQ rr_abort_ind->op.func) { /* * answer to the request of MM */ mm_mdl_rel_req (); mm_data->reg.bcch_encode = FALSE; if (rr_abort_ind->op.service EQ NO_SERVICE) { SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); } else { SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } reg_rr_failure (rr_abort_ind); USE_STORED_ENTRIES(); } #ifndef NTRACE else { /* This RR_ABORT_IND is to be ignored here, trace the func */ switch (rr_abort_ind->op.func) { case FUNC_LIM_SERV_ST_SRCH: TRACE_EVENT ("RR_ABORT_IND (FUNC_LIM_SERV_ST_SRCH)"); break; case FUNC_PLMN_SRCH: TRACE_EVENT ("RR_ABORT_IND (FUNC_PLMN_SRCH)"); break; case FUNC_NET_SRCH_BY_MMI: TRACE_EVENT ("RR_ABORT_IND (FUNC_NET_SRCH_BY_MMI)"); break; default: TRACE_ERROR (UNEXPECTED_PARAMETER); break; } } #endif /* of #ifndef NTRACE */ break; case MM_IDLE_PLMN_SEARCH: /* Find new MM IDLE state, not searching */ switch (rr_abort_ind->op.service) { case NO_SERVICE: SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); break; case LIMITED_SERVICE: mm_sim_insert_state(); break; case FULL_SERVICE: /* MM has to wait with full service in MM state machine * until it is known which cell was selected by RR. */ mm_sim_insert_state(); break; default: TRACE_ERROR (UNEXPECTED_DEFAULT); /* Something has been garbled */ break; } /* Build and send the list */ reg_net_list (rr_abort_ind); /* State change has occurred => use stored primitives */ USE_STORED_ENTRIES(); break; case MM_PLMN_SEARCH_NORMAL_SERVICE: /* This state implies that a SIM is present */ /* Find new MM IDLE state, not searching */ switch (rr_abort_ind->op.service) { case NO_SERVICE: SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); reg_net_list (rr_abort_ind); /* Build and send the list */ USE_STORED_ENTRIES(); break; case LIMITED_SERVICE: SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); reg_net_list (rr_abort_ind); /* Build and send the list */ USE_STORED_ENTRIES(); break; case FULL_SERVICE: /* * Back to old full service IDLE state, maybe either * MM_IDLE_NORMAL_SERVICE, MM_IDLE_ATTEMPT_TO_UPDATE, * or MM_IDLE_LUP_NEEDED. */ SET_STATE(STATE_MM,mm_data->idle_substate); if (rr_abort_ind->cause EQ RRCS_ABORT_PTM) { if(mm_data->net_search_count < 2) { /* * Since GPRS is in PTM there seems to be no need to inform * ACI of the Network list * Also,MM should start with 10 secs timer and on the expiry of * this timer should initiate the plmn scan search again */ TIMERSTART(T_HPLMN,10000); mm_data->net_search_count++; } else { /* * The user initiated network search should be repeated only twice * and empty PLMN list should be returned. But if the search was * other than user initiated network scan allow repetions till * PLMN search is a success. This should be tried every 2 mins. */ if ( mm_data->plmn_scan_mmi ) reg_net_list (rr_abort_ind); else TIMERSTART(T_HPLMN,120000); } } else { mm_data->net_search_count = 0;/*Network Scan successful,reset couter*/ reg_net_list (rr_abort_ind); /* Build and send the list */ } if (GET_STATE (STATE_MM) NEQ MM_WAIT_FOR_RR_ACTIVE) { /* * reg_net_list () didn't select a different PLMN. * Check whether MM needs a location update procedure. */ if (mm_data->t3212_timeout AND mm_data->loc_upd_type.lut EQ NOT_RUNNING) { /* * T3212 expired during MM_PLMN_SEARCH_NORMAL_SERVICE. * Repeat the timeout event now as we are back to IDLE. */ mm_data->t3212_timeout = FALSE; tim_t3212 (); } else { /* * Check whether T3211 and T3213 are inactive, if so, * continue an already running update now (if any). */ if (!TIMERACTIVE (T3211) AND !TIMERACTIVE (T3213)) { mm_continue_running_update (); } } } break; default: TRACE_ERROR (UNEXPECTED_DEFAULT); /* Something has been garbled */ break; } break; #ifdef GPRS case MM_LOCATION_UPDATING_PENDING: case MM_IMSI_DETACH_PENDING: /* * This state transitions here should be discussed with ANS, * maybe MM is doing the wrong thing here. */ if (rr_abort_ind->op.func NEQ FUNC_NET_SRCH_BY_MMI) { mm_mdl_rel_req (); /* Throw out all pending connections */ mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); TRACE_EVENT ("State transition may be subject of discussion"); /* Enter the appropriate IDLE state for the offered service */ if (rr_abort_ind->op.service EQ NO_SERVICE) { SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); } else { mm_sim_insert_state(); } reg_rr_failure (rr_abort_ind); } break; #endif /* GPRS */ default: /* All states caught by case statements, this is impossible */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } PFREE (rr_abort_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_limited_from_rr | +--------------------------------------------------------------------+ PURPOSE : This function takes the appropriate actions if a limited service cell is offered by RR. */ LOCAL void mm_limited_from_rr (T_RR_ACTIVATE_CNF *rr_activate_cnf) { TRACE_FUNCTION ("mm_limited_from_rr()"); mm_copy_rr_act_cnf_data (rr_activate_cnf); reg_mm_success (LIMITED_SERVICE); /* Inform GPRS about selected cell */ mm_mmgmm_activate_ind (MMGMM_LIMITED_SERVICE); mm_sim_insert_state(); } /* +----------------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_activate_cnf | +----------------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ACTIVATE_CNF. */ GLOBAL void mm_rr_activate_cnf (T_RR_ACTIVATE_CNF *rr_activate_cnf) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_activate_cnf()"); #ifdef WIN32 vsi_o_ttrace (VSI_CALLER TC_FUNC, " MCC=%x%x%x MNC=%x%x%x LAC=%04X CID=%04X POW=%d", rr_activate_cnf->plmn.mcc[0], rr_activate_cnf->plmn.mcc[1], rr_activate_cnf->plmn.mcc[2], rr_activate_cnf->plmn.mnc[0], rr_activate_cnf->plmn.mnc[1], rr_activate_cnf->plmn.mnc[2], rr_activate_cnf->lac, rr_activate_cnf->cid, rr_activate_cnf->power); #endif /* #ifdef WIN32 */ /* Changes for Boot Time Speedup. MM will get RR_ACTIVATE_CNF with op.func = FUNC_ST_PWR_SCAN. * No need to process it as this is response to dummy request. * MM need to send REG_CNF indicating PWR_SCAN_START */ if (mm_data->reg.op.func EQ FUNC_ST_PWR_SCAN) { if (rr_activate_cnf->op.func EQ FUNC_ST_PWR_SCAN) { mm_send_mmgmm_reg_cnf (PWR_SCAN_START); } else { TRACE_EVENT_P1 ("Expected function FUNC_ST_PWR_SCAN but received %x", rr_activate_cnf->op.func); } return ; } mm_data->rf_power = rr_activate_cnf->power; mm_data->reg.new_cell_ind = TRUE; if (reg_plmn_equal_eqv (&rr_activate_cnf->plmn, &mm_data->reg.actual_plmn)) { mm_data->reg.actual_plmn = rr_activate_cnf->plmn; /* Struct copy */ } switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_RR_ACTIVE: if (mm_data->reg.op.func EQ rr_activate_cnf->op.func) { /* * this is the answer to the request of MM */ switch (rr_activate_cnf->op.service) { case LIMITED_SERVICE: mm_limited_from_rr (rr_activate_cnf); USE_STORED_ENTRIES(); break; case FULL_SERVICE: /* * full service is indicated by RR. */ mm_copy_rr_act_cnf_data (rr_activate_cnf); if (!mm_normal_upd_needed() AND !mm_attach_upd_needed() AND !mm_periodic_upd_needed()) { /* * No location updating needed */ TIMERSTOP (T3213); mm_data->t3213_restart = 0; /* Track possible change of T3212 */ mm_change_t3212 (); reg_mm_success (FULL_SERVICE); reg_build_sim_update (); /* Update cell id */ mm_mmgmm_activate_ind (MMGMM_FULL_SERVICE); /* Back to MM_IDLE_NORMAL_SERVICE */ mm_data->idle_entry = RRCS_INT_NOT_PRESENT; /* Remember MM doesn't need any IMSI ATTACH anymore */ if (mm_lup_allowed_by_gmm() AND mm_data->first_attach ) { mm_data->first_attach_mem = mm_data->first_attach; mm_data->first_attach = FALSE; } mm_data->t3212_timeout = FALSE; mm_data->loc_upd_type.lut = NOT_RUNNING; SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); /* Check HPLMN timer state */ reg_check_hplmn_tim (mm_data->reg.thplmn); USE_STORED_ENTRIES(); } else { /* * Location updating needed */ reg_mm_cell_selected (); mm_data->attempt_cnt = 0; if (mm_normal_upd_needed()) { /* * If updating is allowed by GMM, start procedure, * otherwise enter state MM_IDLE_LUP_NEEDED. */ mm_normal_loc_upd (); } else if (mm_attach_upd_needed()) { /* * If updating is allowed by GMM, start procedure, * otherwise enter state MM_IDLE_LUP_NEEDED. */ mm_attach_loc_upd (); } else { /* * It must be a periodic location updating procedure. * If updating is allowed, start procedure, * otherwise enter state MM_IDLE_NORMAL_SERVICE. * Compare this with GSM 04.08 subclause 4.2.3 */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_periodic_loc_upd (); } else { SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } } /* * If GPRS is active, GMM will be informed about the * cell selection. In this case, MM has not tried * to establish a RR connection for location updating * and the state MM_IDLE_LUP_NEEDED has already been entered. */ mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); } break; /* case FULL_SERVICE */ default: /* NO_SERVICE or other garbage */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } /* switch() */ } break; default: /* * Normally MM should not receive an unsolicited RR_ACTIVATE_CNF, * but if it happens, we keep MM up to date using considering the * RR_ACTIVATE_CNF as RR_ACTIVATE_IND. * It is theoretically possible that a clash * RR_ACTIVATE_REQ -> RR_ABORT_IND -> RR_ACTIVATE_CNF * happens, but in most of the cases the reception of RR_ACTIVATE_CNF * in another state than MM_WAIT_FOR_RR_ACTIVE is a strong hint that * something went wrong in RR which should be observed carefully. */ TRACE_ERROR ("RR_ACTIVATE_CNF => RR_ACTIVATE_IND"); mm_rr_activate_ind ((T_RR_ACTIVATE_IND*)rr_activate_cnf); return; /* Don't free primitive twice */ } PFREE (rr_activate_cnf); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_handled_forb_plmn_cell | +--------------------------------------------------------------------+ PURPOSE : This function checks whether RR selected a full service cell which is part of the forbidden PLMN list. If the cell is a member of a forbidden list, the appropriate actions are taken, but no change of the MM main state is performed. */ LOCAL BOOL mm_handled_forb_plmn_cell (T_RR_ACTIVATE_IND *rr_activate_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_handled_forb_plmn_cell()"); if (reg_plmn_in_list (mm_data->reg.forb_plmn, MAX_FORB_PLMN_ID, &rr_activate_ind->plmn)) { TRACE_EVENT ("RR selected forbidden PLMN"); mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF *)rr_activate_ind); reg_mm_success (LIMITED_SERVICE); mm_build_rr_sync_req_cause (SYNCCS_LIMITED_SERVICE); /* * GSM 04.08 subclause 4.4.4.7 doesn't say that a forbidden PLMN * for GSM shall also be considered as a forbidden PLMN for GPRS. * This means, we could have the situation that GSM has limited * service only, but GPRS has full network access. */ mm_mmgmm_activate_ind (MMGMM_LIMITED_SERVICE); return TRUE; /* Cell is in forbidden list */ } if (rr_activate_ind->mm_info.la EQ LA_IN_FRBD_LST_INCL) { mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF *)rr_activate_ind); reg_mm_success (LIMITED_SERVICE); mm_mmgmm_activate_ind (MMGMM_LIMITED_SERVICE); return TRUE; /* Cell is in forbidden list */ } return FALSE; /* Cell is not in forbidden list */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_full_from_rr | +--------------------------------------------------------------------+ PURPOSE : This function takes the appropriate actions if a full service cell is offered by RR in some MM states. */ LOCAL void mm_full_from_rr (T_RR_ACTIVATE_IND *rr_activate_ind) { GET_INSTANCE_DATA; BOOL rr_changed_lai; TRACE_FUNCTION ("mm_full_from_rr()"); rr_changed_lai = !mm_check_lai_from_RR (&mm_data->mm.lai, &rr_activate_ind->plmn, rr_activate_ind->lac); mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF *)rr_activate_ind); mm_data->idle_entry = RRCS_INT_NOT_PRESENT; if (mm_normal_upd_needed()) mm_data->loc_upd_type.lut = NORMAL_LUP; else if (mm_attach_upd_needed()) mm_data->loc_upd_type.lut = IMSI_ATTACH_LUP; else if (mm_periodic_upd_needed()) mm_data->loc_upd_type.lut = PERIODIC_LUP; else { if (memcmp(mm_data->reg.lai.mcc, mm_data->mm.lai.mcc, SIZE_MCC) OR memcmp(mm_data->reg.lai.mnc, mm_data->mm.lai.mnc, SIZE_MNC) OR (mm_data->reg.lai.lac NEQ mm_data->mm.lai.lac)) { /* EF LOCI value has changed, hence write it on SIM */ /* EF Indicator for EF LOCI - bit 1*/ mm_data->ef_indicator|=0x01; } mm_data->loc_upd_type.lut = NOT_RUNNING; } #ifdef GPRS if (rr_changed_lai AND (mm_data->loc_upd_type.lut NEQ NOT_RUNNING) AND (GET_STATE (STATE_REG_TYPE) EQ REG_REMOTE_CONTROLLED)) { /* * MM is in remote controlled operation with GPRS present and * the location area identifier has changed, MM has to set * its reg_type auxiliary state variable. The network mode * may have changed to network mode I. * Beware not to suppress an outstanding MMGMM_REG_CNF if * no update needed anymore for whatever reason. */ SET_STATE (STATE_REG_TYPE, REG_CELL_SEARCH_ONLY); } #endif /* GPRS */ switch (mm_data->loc_upd_type.lut) { case NOT_RUNNING: /* * No location updating needed */ /* Track possible change of T3212 */ mm_change_t3212 (); TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; mm_mmgmm_activate_ind (MMGMM_FULL_SERVICE); reg_mm_success (FULL_SERVICE); reg_build_sim_update (); /* Remember MM doesn't need any IMSI ATTACH anymore */ if (mm_lup_allowed_by_gmm() AND mm_data->first_attach) { mm_data->first_attach_mem = mm_data->first_attach; mm_data->first_attach = FALSE; } mm_data->t3212_timeout = FALSE; SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); USE_STORED_ENTRIES(); break; case NORMAL_LUP: /* * If updating is allowed by GMM, start procedure, * otherwise enter appropriate IDLE state. */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); if (rr_changed_lai OR (!TIMERACTIVE (T3211) AND !TIMERACTIVE (T3213))) { mm_normal_loc_upd (); } else { /* Await timer expiry in appropriate IDLE state */ if (mm_data->reg.update_stat EQ MS_UPDATED) { SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } else { SET_STATE (STATE_MM, MM_IDLE_ATTEMPT_TO_UPDATE); } } } else { mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED); } break; case IMSI_ATTACH_LUP: /* * If updating is allowed, start procedure, * otherwise enter state MM_IDLE_LUP_NEEDED. */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); if (mm_gsm_alone ()) { mm_mmgmm_reg_cnf (); /* Early indication of full service */ } if (!TIMERACTIVE (T3211) AND !TIMERACTIVE (T3213)) { mm_attach_loc_upd (); } else { SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } } else { mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED); } break; case PERIODIC_LUP: /* * It is a periodic location updating procedure. * If updating is allowed, start procedure, * otherwise enter state MM_IDLE_NORMAL_SERVICE. * Compare this with GSM 04.08 subclause 4.2.3 */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); if (mm_gsm_alone ()) { mm_mmgmm_reg_cnf (); /* Early indication of full service */ } if (!TIMERACTIVE (T3211) AND !TIMERACTIVE (T3213)) { mm_periodic_loc_upd (); } else { SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } } else { mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } break; default: /* Cannot happen */ break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_activate_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ACTIVATE_IND. MM is informed by RR about a cell selection without prior request by RR_ACTIVATE_REQ. */ GLOBAL void mm_rr_activate_ind (T_RR_ACTIVATE_IND *rr_activate_ind) { GET_INSTANCE_DATA; mm_data->t3213_restart = MAX_REST_T3213; restart_function: TRACE_FUNCTION ("mm_rr_activate_ind()"); #ifdef WIN32 vsi_o_ttrace (VSI_CALLER TC_FUNC, " MCC=%x%x%x MNC=%x%x%x LAC=%04X CID=%04X POW=%d", rr_activate_ind->plmn.mcc[0], rr_activate_ind->plmn.mcc[1], rr_activate_ind->plmn.mcc[2], rr_activate_ind->plmn.mnc[0], rr_activate_ind->plmn.mnc[1], rr_activate_ind->plmn.mnc[2], rr_activate_ind->lac, rr_activate_ind->cid, rr_activate_ind->power); #endif /* #ifdef WIN32 */ mm_data->rf_power = rr_activate_ind->power; mm_data->reg.new_cell_ind = TRUE; if(reg_plmn_equal_eqv (&rr_activate_ind->plmn, &mm_data->reg.actual_plmn)) { mm_data->reg.actual_plmn = rr_activate_ind->plmn; /* Struct copy */ } switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_RR_CONN_MM: /* * If the unexpected incoming RR_ACTIVATE_IND in this state indicates * a new location area the rr_activation_indication is stored and a * rr_abort_req is sent. This should be answered by RR with a * RR_RELEASE_IND message triggering the MM to change the state to * MM_IDLE and to handle the outstanding RR_ACTIVATE_IND there. */ { T_loc_area_ident local_lai; memcpy (local_lai.mcc, rr_activate_ind->plmn.mcc, SIZE_MCC); memcpy (local_lai.mnc, rr_activate_ind->plmn.mnc, SIZE_MNC); local_lai.lac = rr_activate_ind->lac; if (!mm_check_lai (&mm_data->mm.lai, &local_lai)) { mm_write_entry(NO_ENTRY, NO_ENTRY, NO_ENTRY, PRIMITIVE_ENTRY, rr_activate_ind, UNSPEC); if (mm_data->pend_conn.cause NEQ ESTCS_EMRG_CAL) { TRACE_EVENT_P1 ("pend_conn.cause= %x", mm_data->pend_conn.cause); mm_abort_connection(ABCS_NORM); } return; } } /* FALLTHROUGH */ /*lint -fallthrough */ case MM_WAIT_FOR_RR_CONN_LUP: /* * case MM_WAIT_FOR_RR_CONN_MM: */ case MM_WAIT_FOR_RR_CONN_DETACH: /* * A dedicated connection to the network * has been requested, but has not yet been established. * As we are storing the cell data here only, * it may become necessary to perform a location * updating procedure if coming back to IDLE. */ mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF*) rr_activate_ind); /* Inform GPRS about selected cell */ mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); if (mm_check_lai (&mm_data->mm.lai, &mm_data->reg.lai)) reg_build_sim_update (); /* Update cell id */ break; case MM_WAIT_FOR_REESTABLISH: /* RR indicates a suitable cell for call reestablishment */ if (rr_activate_ind->mm_info.re EQ 0) { /* What if call reestablishment and after call release of reestablished call in other LA LUP is necessary? The following line was obviously missing here (HM, 01.02.01) mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF *) rr_activate_ind); Inform GPRS about selected cell mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); */ mm_data->reest_cell_avail = TRUE; /*at least one connection has requested call reestablishment */ if (mm_data->reest_ti NEQ NOT_PRESENT_8BIT) mm_reest (mm_data->reest_ti); /*if (mm_normal_upd_needed()) { */ mm_write_entry(NO_ENTRY, NO_ENTRY, NO_ENTRY, PRIMITIVE_ENTRY, rr_activate_ind, UNSPEC); return; /*} */ } else { /* * No support of call reestablishment */ mm_mmxx_rel_ind (MMCS_NO_REESTABLISH, CM_NOT_IDLE); /* Find IDLE state after MM connection */ mm_release_rr_connection (MMGMM_RESUMPTION_FAILURE); /* Restart the function in new state to perform location updating * if needed, avoid recursion for stack usage, therefore the goto */ goto restart_function; /*lint !e801 goto*/ } /* break is removed ,as case is returning before break so it is not needed */ case MM_WAIT_FOR_RR_ACTIVE: /* * Clash case. While MM required to perform a network selection in RR, * RR performed a cell selection. This maybe ignored, as RR stored the * RR_ACTIVATE_REQ primitive in this case and a RR_ACTIVATE_CNF or * RR_ABORT_IND primitive will follow within short time. */ break; #ifdef GPRS case MM_LOCATION_UPDATING_PENDING: case MM_IMSI_DETACH_PENDING: /* * What to do here?... */ assert (GET_STATE (STATE_REG_TYPE) EQ REG_CELL_SEARCH_ONLY); TRACE_EVENT ("This needs still discussion"); /*FALLTHROUGH*/ /* lint -fallthrough */ #endif /* GPRS */ case MM_IDLE_NORMAL_SERVICE: /* 19.1 */ switch (rr_activate_ind->op.service) { case LIMITED_SERVICE: mm_limited_from_rr ((T_RR_ACTIVATE_CNF*)rr_activate_ind); break; case FULL_SERVICE: if (mm_handled_forb_plmn_cell (rr_activate_ind)) { /* * The cell is a member of a forbidden list. */ SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); USE_STORED_ENTRIES(); } else { mm_full_from_rr (rr_activate_ind); } break; default: /* Either NO_SERVICE or other garbage */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } break; case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */ if (mm_handled_forb_plmn_cell (rr_activate_ind)) { SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } else { /* * RR selected a cell which may serve for full service. Behaviour * here is described in GSM 04.08 subclause 4.2.2.2, "Service State, * ATTEMPTING TO UPDATE". The idea behind this subclause for the * case "cell in old location area selected" seems to be very simple: * If the location updating problem has been caused by the BSS or the * cell itself, perform an updating attempt as soon as a new cell * has been selected by RR and don't consider the timers T3211 and * T3213. In case the location updating problem has been caused by the * NSS (core network), e.g. there was a "network failure", updating * if a new cell is entered makes no sense as the problem was under * no circumstances related to the previously selected cell. */ if (mm_check_lai_from_RR (&mm_data->mm.lai, &rr_activate_ind->plmn, rr_activate_ind->lac)) { /* * RR selected a cell which belongs to a location * area identical with the previously selected cell. * Don't reset the attempt counter. * Compare this with GSM 04.08 subclause 4.4.4.5. */ BOOL perform_lup; mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF*) rr_activate_ind); /* Track possible change of T3212 */ mm_change_t3212 (); /* * Check reject cause category according to GSM 04.08 s * subclause 4.2.2.2 and decide whether a location updating * procedure shall be performed. */ switch (mm_data->rej_cause) { case RRCS_MM_ABORTED: /* GSM 04.08 4.4.4.9 e), T3210 */ case RRCS_ABNORM_UNSPEC: /* GSM 04.08 4.4.4.9 f), ABNORM */ /* * don't start normal location updating if the state * has been entered after T3210 timeout or the network * released the RR connection with RR cause RRCS_ABNORM_UNSPEC. */ perform_lup = FALSE; break; case MMCS_RETRY_IN_NEW_CELL: /* GSM 04.08 4.4.4.8 g), RETRY */ perform_lup = TRUE; break; case RRCS_RND_ACC_FAIL: /* GSM 04.08 4.4.4.9 c) */ case RRCS_DL_EST_FAIL: /* GSM 04.08 4.4.4.9 d) */ perform_lup = (mm_data->attempt_cnt < 4); break; default: /* * Treated here: GSM 04.08 4.4.4.9 f) with causes different * from "abnormal release, unspecified and g) with causes * different from "retry upon entry into a new cell". */ perform_lup = GET_CAUSE_ORIGIN_ENTITY (mm_data->rej_cause) EQ RR_ORIGINATING_ENTITY; break; } /* switch (mm_data->rej_cause) */ if (perform_lup) { /* * Normal location update is necessary */ mm_normal_loc_upd (); /* Inform GPRS about selected cell */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); } else { mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); } } else { /* * RR performed a cell selection which doesn't lead to a * location updating procedure in this state */ mm_mmgmm_activate_ind (MMGMM_CELL_SELECTED); } } else { /* * RR selected a cell which belongs to a location * area not identical with the previously selected cell. * See GSM 04.08, subclause 4.2.2.2, "Service State, * ATTEMPTING TO UPDATE". */ mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF*) rr_activate_ind); /* Track possible change of T3212 */ mm_change_t3212 (); mm_data->attempt_cnt = 0; /* GSM 04.08 subclause 4.4.4.5 */ #ifdef GPRS TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; if (GET_STATE (STATE_REG_TYPE) EQ REG_REMOTE_CONTROLLED) { SET_STATE (STATE_REG_TYPE, REG_CELL_SEARCH_ONLY); } #endif /* GPRS */ mm_normal_loc_upd (); mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); } } /* cell which may offer full service */ break; case MM_IDLE_LIMITED_SERVICE: /* 19.3 */ case MM_IDLE_NO_CELL_AVAILABLE: /* 19.5 */ switch (rr_activate_ind->op.service) { case LIMITED_SERVICE: mm_limited_from_rr ((T_RR_ACTIVATE_CNF*)rr_activate_ind); break; case FULL_SERVICE: if (mm_handled_forb_plmn_cell (rr_activate_ind)) { /* * The cell is a member of a forbidden list. */ SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); mm_use_entry (); } else { mm_full_from_rr (rr_activate_ind); } break; default: /* Either NO_SERVICE or other garbage */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } break; case MM_IDLE_PLMN_SEARCH: /* 19.7 */ if (!mm_handled_forb_plmn_cell (rr_activate_ind)) { /* * Cell is not in forbidden list, offering full service. */ mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF*) rr_activate_ind); // Is it really for sure that an ACTIVATE IND in this state // cannot serve for more than limited service? Why?... /* Inform GPRS about selected cell */ mm_mmgmm_activate_ind (MMGMM_LIMITED_SERVICE); if (mm_check_lai (&mm_data->mm.lai, &mm_data->reg.lai)) reg_build_sim_update (); switch (mm_data->reg.op.func) { case FUNC_LIM_SERV_ST_SRCH: reg_mm_success (LIMITED_SERVICE); mm_sim_set_imsi_marker( MSG_RR_ACT); break; } } break; #ifdef GPRS case MM_IDLE_LUP_NEEDED: /* 19.6 */ if (mm_handled_forb_plmn_cell (rr_activate_ind)) { SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } else { mm_copy_rr_act_cnf_data ((T_RR_ACTIVATE_CNF*) rr_activate_ind); /* * Cell maybe ok for full service, not forbidden PLMN */ if (!mm_normal_upd_needed() AND !mm_attach_upd_needed()) { /* * Back to old updated area, no IMSI ATTACH needed */ mm_mmgmm_activate_ind (MMGMM_FULL_SERVICE); SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); } else { /* * Location updating procedure needed */ mm_mmgmm_activate_ind (MMGMM_WAIT_FOR_UPDATE); /* Remain in MM state MM_IDLE_LUP_NEEDED */ } } break; #endif /* GPRS */ case MM_IDLE_NO_IMSI: /* 19.4 */ /* * The mobile has no SIM and a cell change is indicated. * Service cannot be better than LIMITED_SERVICE without IMSI (SIM). */ mm_limited_from_rr ((T_RR_ACTIVATE_CNF*)rr_activate_ind); break; case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */ /* * RR_ACTIVATE_REQ -> RR_ACTIVATE_IND -> RR_ABORT_IND (search result) * Best thing (which is not perfect anyway) here is to abort the * search requested by the MMI and to handle this in the previous state. * The user may get an empty list, but the RR_ACTIVATE_IND maybe * more important. */ /* Abort the search for the MMI */ mm_data->reg.plmn_cnt = 0; mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); /* Back to previous IDLE state */ SET_STATE (STATE_MM, mm_data->idle_substate); /* Restart the function in new state, avoid recursion, stack usage, * therefore the goto. */ goto restart_function; /*lint !e801 goto*/ /* * Rare case: rr_activate_ind was received during call establishment for * emergency call and stored. * Stored rr_activate_ind shall remain stored until end of emergency call. */ case MM_CONN_ACTIVE: /* * Rare case: 16868 rr_activate indication follows to RR_ABORT during a call. * Reestablishment was rejected because of unknown TI. * Should trigger an LUP after RR connection release if a new LAI is contained. * Stored rr_activate_ind shall remain stored. */ case MM_WAIT_FOR_NW_CMD: mm_write_entry(NO_ENTRY, NO_ENTRY, NO_ENTRY, PRIMITIVE_ENTRY, rr_activate_ind, UNSPEC); return; default: /* * MM_LUP_INITIATED, MM_WAIT_FOR_OUTG_MM_CONN, * MM_IMSI_DETACH_INIT, MM_PROCESS_PROMPT, * MM_LUP_REJECTED => Not expected cell selection in dedicated mode */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } PFREE (rr_activate_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_establish_cnf | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ESTABLISH_CNF. */ GLOBAL void mm_rr_establish_cnf (T_RR_ESTABLISH_CNF *rr_establish_cnf) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mmrr_establish_cnf()"); switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_RR_CONN_LUP: TIMERSTART (T3210, T_3210_VALUE); mm_data->ciphering_on = FALSE; SET_STATE (STATE_MM, MM_LUP_INITIATED); break; case MM_WAIT_FOR_RR_CONN_MM: mm_data->ciphering_on = FALSE; mm_data->wait_for_accept = TRUE; SET_STATE (STATE_MM, MM_WAIT_FOR_OUTG_MM_CONN); TIMERSTART (T3230, T_3230_VALUE); break; case MM_WAIT_FOR_REESTABLISH: mm_data->ciphering_on = FALSE; mm_data->wait_for_accept = TRUE; TIMERSTART (T3230, T_3230_VALUE); break; case MM_WAIT_FOR_RR_CONN_DETACH: /* * RR connection for IMSI Detach has been established */ TIMERSTART (T3220, T_3220_VALUE); /* * Wait for release by the infrastructure or timeout T3220 * if the SIM card is removed. */ SET_STATE (STATE_MM, MM_IMSI_DETACH_INIT); break; default: /* * A RR_ESTABLISH_CNF is somewhat unexpected here, but we can try to * handle it by aborting the RR connection. But it is at least also * worth a TRACE. */ mm_abort_connection (ABCS_NORM); TRACE_EVENT (UNEXPECTED_IN_STATE); break; } EM_RR_CONECTION_ESTABLISHED; PFREE (rr_establish_cnf); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_establish_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ESTABLISH_IND. */ GLOBAL void mm_rr_establish_ind (T_RR_ESTABLISH_IND *rr_establish_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_establish_ind()"); TIMERSTOP (T3240); switch (GET_STATE (STATE_MM)) { case MM_IDLE_PLMN_SEARCH: case MM_PLMN_SEARCH_NORMAL_SERVICE: mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); /*FALLTHROUGH*/ //lint -fallthrough case MM_WAIT_FOR_RR_CONN_LUP: case MM_IDLE_NORMAL_SERVICE: case MM_IDLE_ATTEMPT_TO_UPDATE: case MM_IDLE_LIMITED_SERVICE: #ifdef GPRS case MM_IDLE_LUP_NEEDED: case MM_LOCATION_UPDATING_PENDING: mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK); #endif /* GPRS */ mm_data->idle_substate = mm_get_service_state (); mm_data->ciphering_on = FALSE; mm_data->rej_cause = 0; SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); break; case MM_WAIT_FOR_RR_CONN_MM: /* * Clash. RR_ESTABLISH_IND was underway, in the * same moment RR_ESTABLISH_REQ was sent. * The RR_ESTABLISH_REQ is cancelled, the MT * establishment has the right of way. */ #ifdef GPRS mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK); #endif /* GPRS */ if (mm_data->pend_conn.comp EQ SMS_COMP) { /* * In the clash a pending MO SMS is involved. Do not release the SMS * but store it until it can established again. * Note: This special treatment makes only sense for SMS. */ TRACE_EVENT ("MO SMS clashed with MT"); mm_write_entry (mm_data->pend_conn.comp, mm_data->pend_conn.ti, mm_data->pend_conn.cause, EVENT_ENTRY, NULL, UNSPEC); } else { /* Release all pending connections */ mm_mmxx_rel_ind (MMCS_INT_PREEM, CM_PENDING); } mm_data->idle_substate = mm_get_service_state (); mm_data->ciphering_on = FALSE; mm_data->rej_cause = 0; SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); break; /* case MM_WAIT_FOR_RR_CONN_MM: mm_abort_connection (ABCS_NORM); switch (mm_data->pend_conn.comp) { case CC_COMP: if (mm_data->pend_conn.prio EQ PRIO_NORM_CALL) { switch (mm_data->pend_conn.cause) { case ESTCS_MOB_ORIG_SPCH: case ESTCS_MOB_ORIG_DATA: case ESTCS_MOB_ORIG_DATA_HR_SUFF: mm_rr_est_req (mm_data->pend_conn.cause, CALL_SERVICE, mm_data->pend_conn.ti); break; } } else mm_rr_est_req (ESTCS_EMERGE, CALL_SERVICE, mm_data->pend_conn.ti); break; case SS_COMP: mm_rr_est_req (ESTCS_MOB_ORIG_CAL_BY_SS_SMS, SS_SERVICE, mm_data->pend_conn.ti); break; case SMS_COMP: mm_rr_est_req (ESTCS_MOB_ORIG_CAL_BY_SS_SMS, SMS_SERVICE, mm_data->pend_conn.ti); break; } break; */ case MM_WAIT_FOR_REESTABLISH: /* * Lost RR connection by a radio link failure and next thing which * happens is MT call establishment, just before the internal * communication after the radio link failure was completed. * This is not expected to happen, but if so, the MT call * has to be aborted. Maybe the incoming call ti is identical to a ti * for a call which has to be reestablished, this would lead to failure. */ mm_abort_connection (ABCS_NORM); break; default: break; } EM_RR_CONECTION_ESTABLISHED; PFREE (rr_establish_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_release_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_RELEASE_IND. */ GLOBAL void mm_rr_release_ind (T_RR_RELEASE_IND *rr_release_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_release_ind()"); /* Check for correct cause value */ assert (GET_CAUSE_ORIGIN_ENTITY (rr_release_ind->cause) EQ RR_ORIGINATING_ENTITY); #ifdef GPRS mm_data->gprs.resumption = rr_release_ind->gprs_resumption; #endif /* #ifdef GPRS */ switch (GET_STATE (STATE_MM)) { case MM_LUP_INITIATED: if (mm_data->rej_cause EQ 0) mm_data->rej_cause = rr_release_ind->cause; TIMERSTOP (T3210); mm_mdl_rel_req (); mm_lup_restart (); break; case MM_WAIT_FOR_OUTG_MM_CONN: case MM_WAIT_FOR_NW_CMD: #ifdef REL99 case MM_RR_CONN_RELEASE_NOT_ALLOWED: #endif case MM_WAIT_FOR_RR_CONN_MM: EM_RR_CONNECTION_ESTABLISHED_2; /*FALLTHROUGH*/ //lint -fallthrough case MM_WAIT_FOR_REESTABLISH: if (rr_release_ind->cause NEQ RRCS_MO_MT_COLL) mm_mdl_rel_req (); TIMERSTOP (T3230); TIMERSTOP (T3240); #ifdef REL99 /*Stop timer t3241 if it is ruuning. *As per the spec 24.008, Timer T3241 is stopped and reset (but not started) *when the MM state RR CONNECTION RELEASE NOT ALLOWED is left. */ TIMERSTOP(T3241); #endif if (rr_release_ind->cause EQ RRCS_RND_ACC_FAIL AND mm_data->reg.op.sim_ins EQ SIM_INSRT AND mm_data->reg.op.ts EQ TS_NO_AVAIL AND mm_data->act_retrans NEQ 0 AND (mm_count_connections (CM_PENDING) NEQ 0 OR mm_count_connections (CM_REEST_PENDING) NEQ 0)) { /* * start internal redial, if * - no TEST SIM * - SIM * - Cause <> random access failure * - retransmission counter <> 0 * - at least one CM connection is pending */ mm_data->act_retrans--; mm_rr_est_req (mm_data->pend_conn.cause, mm_data->pend_conn.service, mm_data->pend_conn.ti); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_MM); } else { /* * other cases: no internal redial */ if (rr_release_ind->cause EQ RRCS_MO_MT_COLL) { if (mm_data->pend_conn.comp EQ SMS_COMP) { /* * Clash MO/MT, a pending MO SMS is involved. Do not release * the SMS but store it until it can be established again. * Note: This special treatment makes only sense for SMS. */ TRACE_EVENT ("MO SMS clashed with MT"); mm_write_entry (mm_data->pend_conn.comp, mm_data->pend_conn.ti, mm_data->pend_conn.cause, EVENT_ENTRY, NULL, UNSPEC); } else { /* * Clash MO/MT, no pending MO SMS is involved. Inform CM * about the release of the pending connection */ mm_mmxx_rel_ind (rr_release_ind->cause, CM_PENDING); mm_mmxx_rel_ind (rr_release_ind->cause, CM_REEST_PENDING); } /* Back to old Idle state without informing GMM about CM release */ SET_STATE (STATE_MM, mm_data->idle_substate); } else /* if release_ind->cause */ { /* Commenting the OMAPS00048777 changes as it was a incomplete workaround. Refer the analysis section of the defect 71208 for details */ /*#ifdef GPRS if (mm_data->gprs.sim_physically_removed) { mm_data->nreg_cause = CS_SIM_REM; mm_create_imsi_detach_message (); for_est_req (ESTCS_MOB_ORIG_CAL_BY_SS_SMS, BSIZE_U_IMSI_DETACH_IND); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_DETACH); } else #endif {*/ /* * No MO/MT clash. Inform CM and also GMM about release. * Release all connections except the stored connections. */ mm_mmxx_rel_ind (rr_release_ind->cause, CM_PENDING); mm_mmxx_rel_ind (rr_release_ind->cause, CM_ACTIVE); mm_mmxx_rel_ind (rr_release_ind->cause, CM_REEST_PENDING); /* Find IDLE state */ mm_release_rr_connection (rr_release_ind->gprs_resumption); /* }*/ } /* release cause <> collision */ } break; case MM_CONN_ACTIVE: case MM_PROCESS_PROMPT: { if (rr_release_ind->sapi NEQ SAPI_3) { /* * Release of main signalling link, release all. */ /* Manager DL release, kill layer 2 */ mm_mdl_rel_req (); TIMERSTOP (T3230); TIMERSTOP (T3240); if ((rr_release_ind->cause EQ RRCS_NORM) AND (mm_count_connections (CM_PENDING) NEQ 0)) { /* * This is state MM WAIT FOR ADD OUTG MM CONN. * MM_PROCESS_PROMPT is incompatible with the requestion of a new * MM connection, so we are not in this state here. * The RR connection was released by the network normally. * Assume a clash case and repeat the CM_SERVICE_REQUEST message * for the pending connection. */ mm_mmxx_rel_ind (rr_release_ind->cause, CM_ACTIVE); mm_mmxx_rel_ind (rr_release_ind->cause, CM_REEST_PENDING); mm_rr_est_req (mm_data->pend_conn.cause, mm_data->pend_conn.service, mm_data->pend_conn.ti); SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_MM); } else { /* * Inform CM about release. */ mm_mmxx_rel_ind (rr_release_ind->cause, CM_PENDING); mm_mmxx_rel_ind (rr_release_ind->cause, CM_ACTIVE); mm_mmxx_rel_ind (rr_release_ind->cause, CM_REEST_PENDING); /* Find IDLE state after MM connection */ mm_release_rr_connection (rr_release_ind->gprs_resumption); } } else { /* * Only release of RR connection for SAPI = 3, * main signalling link not released. */ /* * Inform CM entity SMS about release. All SAPI 3 connections * are to be released to SMS (except the stored ones). */ mm_mmsms_rel_ind (rr_release_ind->cause, CM_PENDING); mm_mmsms_rel_ind (rr_release_ind->cause, CM_ACTIVE); mm_mmsms_rel_ind (rr_release_ind->cause, CM_REEST_PENDING); if (mm_count_connections (CM_ACTIVE) NEQ 0 OR mm_count_connections (CM_PENDING) NEQ 0) { /* * Some active or pending connections remaining for * SAPI NEQ 3, kill layer 2 only for SAPI = 3 */ mm_mdl_rel_req_sapi_3 (); } else { /* * No active or pending connections * remaining, manager release of layer 2. */ mm_mdl_rel_req (); TIMERSTOP (T3230); TIMERSTOP (T3240); /* Find IDLE state after MM connection */ mm_release_rr_connection (rr_release_ind->gprs_resumption); } } break; } case MM_IMSI_DETACH_INIT: case MM_WAIT_FOR_RR_CONN_DETACH: mm_mdl_rel_req (); mm_mmgmm_cm_release_ind (rr_release_ind->gprs_resumption); mm_end_of_detach (); break; case MM_LUP_REJECTED: mm_mdl_rel_req (); TIMERSTOP (T3240); mm_loc_upd_rej (); break; case MM_WAIT_FOR_RR_CONN_LUP: mm_data->rej_cause = rr_release_ind->cause; mm_mdl_rel_req (); TIMERSTOP (T3210); switch (rr_release_ind->cause) { case RRCS_DL_EST_FAIL: /* * GSM 04.08 subclause 4.4.4.9 case d) * RR connection failure. */ mm_data->rej_cause = RRCS_DL_EST_FAIL; mm_lup_restart (); break; case RRCS_RND_ACC_FAIL: /* * GSM 04.08 subclause 4.4.4.9 case c) * Random access failure. */ mm_data->rej_cause = RRCS_RND_ACC_FAIL; mm_data->idle_entry = RRCS_INT_NOT_PRESENT; #ifdef WIN32 TRACE_EVENT_P1 ("Last Rej Cause = %x", mm_data->last_rej_cause); #endif /* #ifdef WIN32 */ if (mm_data->last_rej_cause EQ RRCS_RND_ACC_FAIL) { mm_lup_restart (); } else { mm_data->last_rej_cause = RRCS_RND_ACC_FAIL; TIMERSTART (T3213, T_3213_VALUE); mm_data->t3213_restart = 0; /* * It can be safely assumed that idle_substate here is either * MM_IDLE_NORMAL_SERVICE or MM_IDLE_ATTEMPT_TO_UPDATE */ SET_STATE (STATE_MM, mm_data->idle_substate); } break; case RRCS_ACCESS_BARRED: case RRCS_RND_ACC_DELAY: /* * GSM 04.08 subclause 4.4.4.9 case a) * Access barred because of access class control. * GSM 04.08 subclause 4.4.4.9 case b) * The answer to random access is an * IMMEDIATE ASSIGNMENT REJECT message. */ mm_data->idle_entry = rr_release_ind->cause; /* * It can be safely assumed that idle_substate here is either * MM_IDLE_NORMAL_SERVICE or MM_IDLE_ATTEMPT_TO_UPDATE */ SET_STATE (STATE_MM, mm_data->idle_substate); break; default: /* eg. RRCS_ABNORM_UNSPEC, RRCS_INT_NOT_PRESENT */ mm_lup_restart (); break; } break; default: /* * 19.x, MM_LOCATION_UPDATING_PENDING, MM_IMSI_DETACH_PENDING, * and all remaining MM states. */ /* Local end release of layer 2 */ mm_mdl_rel_req (); #ifdef GPRS /* Assume GMM sent GMMRR_CS_PAGE_RES (GMMRR_CS_PAGE_CNF). * This means CS services are (were) allowed. */ SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK); /* Give CM control back to GMM */ mm_mmgmm_cm_release_ind (rr_release_ind->gprs_resumption); #endif /* #ifdef GPRS */ USE_STORED_ENTRIES(); break; } #ifdef GPRS mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; #endif /* #ifdef GPRS */ PFREE (rr_release_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_sync_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_SYNC_IND. */ GLOBAL void mm_rr_sync_ind (T_RR_SYNC_IND *rr_sync_ind) { GET_INSTANCE_DATA; BOOL t3212_changed; TRACE_FUNCTION ("mm_rr_sync_ind()"); /* prevent the T3213 from restarting when it runs first time, but don't forget, that it is restarted if so */ if (mm_data->t3213_restart EQ 0) { mm_data->t3213_restart = MAX_REST_T3213; } /* Remember wheter a change in broadcasted value for T3212 was detected */ t3212_changed = (rr_sync_ind->mm_info.valid EQ MM_INFO_PRES AND mm_data->mm.mm_info.t3212 NEQ rr_sync_ind->mm_info.t3212); /* * Forward new BCCH information to the SIM application */ if (rr_sync_ind->bcch_info.v_bcch EQ V_BCCH_PRES) { // Patch HM 14.03.01 >>> // memcpy (&mm_data->mm.bcch, &rr_sync_ind->bcch_info, SIZE_BCCH); memcpy (mm_data->mm.bcch, rr_sync_ind->bcch_info.bcch, SIZE_BCCH); // Patch HM 14.03.01 <<< if (memcmp(rr_sync_ind->bcch_info.bcch,mm_data->reg.bcch,SIZE_BCCH)) { /* Set bit 2 in ef_indicator to indicate bcch_info change to SIM */ mm_data->ef_indicator|=(0x01 << 1); } reg_build_sim_update (); PFREE (rr_sync_ind); // return; // } /* * forwarding of ciphering indicator */ if (rr_sync_ind->ciph NEQ CIPH_NOT_PRES) { if (rr_sync_ind->ciph NEQ mm_data->ciphering_on) { #ifdef GPRS /* GPRS supported, forward ciphering info for indicator to GMM */ PALLOC (ciphering_ind,MMGMM_CIPHERING_IND); ciphering_ind->ciph = rr_sync_ind->ciph; PSENDX (GMM, ciphering_ind); #else /* GSM only case, forward ciphering info for indicator to ACI directly */ PALLOC (ciphering_ind,MMR_CIPHERING_IND); ciphering_ind->ciph = rr_sync_ind->ciph; PSENDX (MMI, ciphering_ind); #endif /* GPRS */ } } switch (GET_STATE (STATE_MM)) { case MM_LUP_INITIATED: if (rr_sync_ind->ciph NEQ CIPH_NOT_PRES) { mm_data->ciphering_on = rr_sync_ind->ciph; } break; case MM_WAIT_FOR_OUTG_MM_CONN: if (rr_sync_ind->ciph NEQ CIPH_NOT_PRES) { mm_data->ciphering_on = rr_sync_ind->ciph; mm_data->error = FALSE; mm_cm_serv_accept (); } if (rr_sync_ind->chm.ch_mode NEQ NOT_PRESENT_8BIT) { PALLOC (mmcm_sync_ind, MMCM_SYNC_IND); /* T_MMCM_SYNC_IND */ mmcm_sync_ind->ti = 0; mmcm_sync_ind->sync_info.ch_info.ch_type = rr_sync_ind->chm.ch_type; mmcm_sync_ind->sync_info.ch_info.ch_mode = rr_sync_ind->chm.ch_mode; PSENDX (CC, mmcm_sync_ind); } break; case MM_CONN_ACTIVE: if (rr_sync_ind->chm.ch_mode NEQ NOT_PRESENT_8BIT) { PALLOC (mmcm_sync_ind, MMCM_SYNC_IND); /* T_MMCM_SYNC_IND */ mmcm_sync_ind->ti = 0; mmcm_sync_ind->sync_info.ch_info.ch_type = rr_sync_ind->chm.ch_type; mmcm_sync_ind->sync_info.ch_info.ch_mode = rr_sync_ind->chm.ch_mode; PSENDX (CC, mmcm_sync_ind); } if (rr_sync_ind->ciph NEQ NOT_PRESENT_8BIT) { mm_data->ciphering_on = rr_sync_ind->ciph; if (mm_data->wait_for_accept) { mm_mmxx_est_cnf (); TIMERSTOP (T3230); mm_data->wait_for_accept = FALSE; EM_CM_SERVICE_ACCEPTED(EM_COMMAND); USE_STORED_ENTRIES(); } } break; case MM_PROCESS_PROMPT: if (rr_sync_ind->chm.ch_mode NEQ NOT_PRESENT_8BIT) { /* Channel mode modification, MMCM_SYNC_IND to CC */ PALLOC (mmcm_sync_ind, MMCM_SYNC_IND); /* T_MMCM_SYNC_IND */ mmcm_sync_ind->ti = 0; mmcm_sync_ind->sync_info.ch_info.ch_type = rr_sync_ind->chm.ch_type; mmcm_sync_ind->sync_info.ch_info.ch_mode = rr_sync_ind->chm.ch_mode; PSENDX (CC, mmcm_sync_ind); } if (rr_sync_ind->ciph NEQ NOT_PRESENT_8BIT) { /* Ciphering changed, remember this is MM data */ mm_data->ciphering_on = rr_sync_ind->ciph; if (mm_count_connections (CM_ACTIVE) NEQ 0) { /* * In state MM_PROCESS PROMPT we cannot have * pending connections which are waiting * for CM SERVICE ACCEPT. This means, do nothing here. */ } else { /* * No connection exists, behaviour like in state * of MM_WAIT_FOR_NW_CMD, restart T3240 */ TIMERSTART (T3240, T_3240_VALUE); } } break; case MM_WAIT_FOR_NW_CMD: #ifdef REL99 case MM_RR_CONN_RELEASE_NOT_ALLOWED: #endif if (rr_sync_ind->chm.ch_mode NEQ NOT_PRESENT_8BIT) { PALLOC (mmcm_sync_ind, MMCM_SYNC_IND); /* T_MMCM_SYNC_IND */ mmcm_sync_ind->ti = 0; mmcm_sync_ind->sync_info.ch_info.ch_type = rr_sync_ind->chm.ch_type; mmcm_sync_ind->sync_info.ch_info.ch_mode = rr_sync_ind->chm.ch_mode; PSENDX (CC, mmcm_sync_ind); } if (rr_sync_ind->ciph NEQ NOT_PRESENT_8BIT) { mm_data->ciphering_on = rr_sync_ind->ciph; if (mm_get_service_state () NEQ MM_IDLE_LIMITED_SERVICE) { /* * T3212 is stopped if the first MM message is received, or * ciphering mode setting is completed in the case of MM * connection establishment, except when the most recent service * state is LIMITED SERVICE. [GSM 04.08 subclause 4.4.2] */ TIMERSTOP (T3212); mm_data->t3212_timeout = FALSE; } #ifdef REL99 if(TIMERACTIVE(T3241)) { /*Do nothing*/ } else #endif { /*restart timer T3240*/ TIMERSTART (T3240, T_3240_VALUE); } } break; case MM_IDLE_NO_IMSI: /* * Add traces to see last reject cause for location updating reject and * the place where MM entered the MM_IDLE_NO_IMSI state. */ TRACE_EVENT_P1 ("Last lup rej cause: %04x", mm_data->debug_last_rej_cause); TRACE_EVENT_P1 ("Entered state at %d", mm_data->mm_idle_no_imsi_marker); /*FALLTHROUGH*/ //lint -fallthrough case MM_WAIT_FOR_RR_CONN_LUP: case MM_WAIT_FOR_RR_CONN_MM: case MM_WAIT_FOR_RR_CONN_DETACH: case MM_IDLE_LIMITED_SERVICE: if ((rr_sync_ind->mm_info.valid EQ MM_INFO_PRES) AND (mm_data->reg.lai.lac NEQ LAC_INVALID_VALUE)) { mm_data->mm.mm_info = rr_sync_ind->mm_info; /* Structure copy */ if (t3212_changed) { // Maybe GMM is not interested either in T3212 if service state // is LIMITED SERVICE only, this should be checked... mm_mmgmm_t3212_val_ind (); } } break; case MM_IDLE_NORMAL_SERVICE: /* 19.1 */ if (rr_sync_ind->mm_info.valid EQ MM_INFO_PRES) { mm_data->mm.mm_info = rr_sync_ind->mm_info; /* Structure copy */ if (t3212_changed) { mm_mmgmm_t3212_val_ind (); mm_change_t3212 (); } } if ((rr_sync_ind->synccs EQ SYNCCS_ACC_CLS_CHA AND mm_data->idle_entry EQ RRCS_ACCESS_BARRED) OR (rr_sync_ind->synccs EQ SYNCCS_T3122_TIM_OUT AND mm_data->idle_entry EQ RRCS_RND_ACC_DELAY) OR (mm_data->t3213_restart > 0 AND mm_data->rej_cause EQ RRCS_RND_ACC_FAIL)) { mm_continue_running_update (); } break; case MM_IDLE_ATTEMPT_TO_UPDATE: if (rr_sync_ind->mm_info.valid EQ MM_INFO_PRES) { mm_data->mm.mm_info = rr_sync_ind->mm_info; /* Structure copy */ if (t3212_changed) { mm_mmgmm_t3212_val_ind (); mm_change_t3212 (); } } if ((rr_sync_ind->synccs EQ SYNCCS_ACC_CLS_CHA AND mm_data->idle_entry EQ RRCS_ACCESS_BARRED) OR (rr_sync_ind->synccs EQ SYNCCS_T3122_TIM_OUT AND mm_data->idle_entry EQ RRCS_RND_ACC_DELAY) OR (mm_data->t3213_restart > 0 AND mm_data->rej_cause EQ RRCS_RND_ACC_FAIL)) { mm_continue_running_update (); break; } #if 0 /* This code causes failure on ALCATEL test cases */ /* This registration attempt does not check the attempt counter*/ /* and so can cause the MS to attempt more than 4 LUs to the network */ if (rr_sync_ind->synccs EQ SYNCCS_LUP_RETRY) { if (mm_data->reg.op.sim_ins EQ SIM_INSRT AND mm_data->reg.op.ts EQ TS_NO_AVAIL) { /* * A SIM is inserted and it is no test SIM */ if (mm_lup_allowed_by_gmm()) /*lint !e774*/ { mm_normal_loc_upd (); } else { mm_mmgmm_lup_needed_ind (MMGMM_RXLEV_JUMP); /* No state change, MM remains in MM_IDLE_ATTEMPT_TO_UPDATE */ } } } #endif break; case MM_WAIT_FOR_REESTABLISH: if (rr_sync_ind->mm_info.re EQ RE_ALLOW) { /* * RR indicates a suitable cell for call reestablishment */ mm_data->reest_cell_avail = TRUE; // at least one connection has requested call reestablishment if (mm_data->reest_ti NEQ NOT_PRESENT_8BIT) mm_reest (mm_data->reest_ti); } else { /* * No support of call reestablishment */ mm_mmxx_rel_ind (MMCS_NO_REESTABLISH, CM_NOT_IDLE); /* Find IDLE state after MM connection */ mm_release_rr_connection(MMGMM_RESUMPTION_FAILURE); } break; #ifdef GPRS case MM_IDLE_LUP_NEEDED: /* 19.6 */ case MM_LOCATION_UPDATING_PENDING: /* 23 */ case MM_IMSI_DETACH_PENDING: /* 24 */ if (rr_sync_ind->mm_info.valid EQ MM_INFO_PRES) { mm_data->mm.mm_info = rr_sync_ind->mm_info; /* Structure copy */ if (t3212_changed) { mm_mmgmm_t3212_val_ind (); if (mm_get_service_state () NEQ MM_IDLE_LIMITED_SERVICE) mm_change_t3212 (); } } break; #endif /* GPRS */ default: TRACE_EVENT (PRIMITIVE_IGNORED); break; } PFREE (rr_sync_ind); } #if defined (FF_EOTD) AND defined (REL99) /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_rrlp_start_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive mm_rr_rrlp_start_ind. */ GLOBAL void mm_rr_rrlp_start_ind (T_RR_RRLP_START_IND *rr_rrlp_start_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_rrlp_start_ind()"); /* *set rrlp_lcs_started flag to true */ mm_data->rrlp_lcs_started = TRUE; switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_NW_CMD: TIMERSTOP(T3240); TIMERSTART(T3241, T_3241_VALUE); SET_STATE (STATE_MM, MM_RR_CONN_RELEASE_NOT_ALLOWED); break; case MM_RR_CONN_RELEASE_NOT_ALLOWED: TIMERSTOP(T3241); TIMERSTART(T3241, T_3241_VALUE); break; default : break; } PFREE (rr_rrlp_start_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_rrlp_stop_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive mm_rr_rrlp_stop_ind. */ GLOBAL void mm_rr_rrlp_stop_ind (T_RR_RRLP_STOP_IND *rr_rrlp_stop_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_rrlp_stop_ind()"); /* *set rrlp_lcs_started flag to false */ mm_data->rrlp_lcs_started = FALSE; switch (GET_STATE (STATE_MM)) { case MM_RR_CONN_RELEASE_NOT_ALLOWED: TIMERSTOP(T3241); TIMERSTART(T3240, T_3240_VALUE); SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); break; default : break; } PFREE (rr_rrlp_stop_ind); } #endif /* (FF_EOTD) AND defined (REL99) */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_prompt_rej | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_PROMPT_REJ. */ GLOBAL void mm_mmcm_prompt_rej (T_MMCM_PROMPT_REJ *prompt_rej) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_mmcm_prompt_rej()"); switch (GET_STATE (STATE_MM)) { case MM_PROCESS_PROMPT: /* Send MM STATUS with cause #34 */ { /* Implements Measure 29 and streamline encoding */ mm_send_status(RC_SERVICE_ORDER); } if ((mm_count_connections (CM_ACTIVE) NEQ 0) OR (mm_count_connections (CM_PENDING) NEQ 0)) { /* This is not standardized in GSM 4.08, but without returning to state MM_CONN_ACTIVE some MSCs in GSM 04.93 don't make sense. */ SET_STATE (STATE_MM, MM_CONN_ACTIVE); } else { #if defined (FF_EOTD) AND defined (REL99) if(mm_data->rrlp_lcs_started EQ TRUE) { TIMERSTART(T3241,T_3241_VALUE); SET_STATE(STATE_MM, MM_RR_CONN_RELEASE_NOT_ALLOWED); } else #endif /* (FF_EOTD) AND defined (REL99) */ { TIMERSTART (T3240, T_3240_VALUE); SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD); } } break; default: break; } PFREE (prompt_rej); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_prompt_res | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MMCM_PROMPT_RES. */ GLOBAL void mm_mmcm_prompt_res (T_MMCM_PROMPT_RES *prompt_res) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_mmcm_prompt_res()"); switch (GET_STATE (STATE_MM)) { case MM_PROCESS_PROMPT: TIMERSTOP (T3240); CM_SET_STATE (CC_COMP, prompt_res->ti, CM_ACTIVE); SET_STATE (STATE_MM, MM_CONN_ACTIVE); break; default: /* MM cannot do anything (anymore) with the ti, send MMCM_RELEASE_IND */ mm_mmxx_release_ind (CC_COMP, prompt_res->ti, MMCS_INT_NOT_PRESENT); break; } PFREE (prompt_res); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_mmcm_ss_sms_data_req | +--------------------------------------------------------------------+ PURPOSE : This function unifies mm_mmcm_data_req(), mm_mmss_data_req() and mm_mmsms_data_req(). */ LOCAL void mm_mmcm_ss_sms_data_req (T_VOID_STRUCT *mm_data_req) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_mmcm_ss_sms_data_req()"); switch (GET_STATE (STATE_MM)) { case MM_WAIT_FOR_OUTG_MM_CONN: case MM_CONN_ACTIVE: case MM_PROCESS_PROMPT: case MM_WAIT_FOR_NW_CMD: { PPASS (mm_data_req, rr_data_req, RR_DATA_REQ); for_cm_message (rr_data_req); break; } default: PFREE (mm_data_req); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_sim_insrt_state | +--------------------------------------------------------------------+ PURPOSE : This function sets the parameter mm_idle_no_imsi_marker depending on the selector imsi_marker. */ GLOBAL void mm_sim_set_imsi_marker (T_MSG_TYPE imsi_marker) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_sim_set_imsi_marker()"); if (mm_data->reg.op.sim_ins EQ SIM_INSRT) { /* Valid SIM inserted */ SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } else { /* Find original place where MM entered MM_IDLE_NO_IMSI state >>> */ if (mm_data->mm_idle_no_imsi_marker EQ 0) { if ( imsi_marker EQ MSG_RR_ACT) mm_data->mm_idle_no_imsi_marker = 13; else mm_data->mm_idle_no_imsi_marker = 3; } /* End of debugging patch <<< */ /* Invalid SIM inserted */ SET_STATE (STATE_MM, MM_IDLE_NO_IMSI); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_sim_insrt_state | +--------------------------------------------------------------------+ PURPOSE : This function sets the MM state depending on the SIM INSERT status. */ LOCAL void mm_sim_insert_state (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_sim_insert_state()"); if (mm_data->reg.op.sim_ins EQ SIM_INSRT) { /* SIM present */ SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } else { /* SIM not present */ SET_STATE (STATE_MM, MM_IDLE_NO_IMSI); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_MM | | STATE : code ROUTINE : mm_rr_abort_cell_sel_fail | +--------------------------------------------------------------------+ PURPOSE : This function processes RR_ABORT_IND */ LOCAL void mm_rr_abort_cell_sel_fail (T_RR_ABORT_IND *rr_abort_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("mm_rr_abort_cell_sel_fail()"); if (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL) { TIMERSTOP (T3211); TIMERSTOP (T3213); mm_data->t3213_restart = 0; mm_mmxx_rel_ind (rr_abort_ind->cause, CM_NOT_IDLE); mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); if (rr_abort_ind->op.service EQ NO_SERVICE) { SET_STATE (STATE_MM, MM_IDLE_NO_CELL_AVAILABLE); } else { SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE); } reg_rr_failure (rr_abort_ind); } } #endif