FreeCalypso > hg > fc-tourmaline
diff src/g23m-gsm/mm/mm_gprs.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/g23m-gsm/mm/mm_gprs.c Fri Oct 16 06:25:50 2020 +0000 @@ -0,0 +1,1187 @@ +/* ++----------------------------------------------------------------------------- +| Project : GSM-PS (8410) +| Modul : MM_GPRS.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 module defines the functions which are necessary +| to process requests from GMM in MM. ++----------------------------------------------------------------------------- +*/ + +#ifndef MM_GMM_C +#define MM_GMM_C + +#define ENTITY_MM + +/*==== INCLUDES ===================================================*/ + +#include <string.h> +#include "typedefs.h" +#include "pconst.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" + +#ifdef GPRS + +/*==== EXPORT ==============================================================*/ + +/*==== TEST ================================================================*/ + +/*==== PRIVAT ==============================================================*/ + +/*==== VARIABLES ===========================================================*/ + +/*==== FUNCTIONS ===========================================================*/ + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_gprs_update_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function performs an remote controlled, by GMM initiatiated + location update + +*/ + +GLOBAL void mm_gprs_update_req (void) +{ + GET_INSTANCE_DATA; +restart_function: + + TRACE_FUNCTION ("mm_gprs_update_req()"); + + mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; + + switch (GET_STATE (STATE_MM)) + { + case MM_WAIT_FOR_OUTG_MM_CONN: + case MM_WAIT_FOR_RR_CONN_MM: + case MM_WAIT_FOR_RR_ACTIVE: + mm_data->attempt_cnt = 0; /* Just to be safe */ + /* Save the event as outstanding periodic update */ + mm_data->t3212_timeout = TRUE; + break; + + case MM_IDLE_NORMAL_SERVICE: /* 19.1 */ + case MM_LOCATION_UPDATING_PENDING: + case MM_IMSI_DETACH_PENDING: + /* + * As MM had no knowledge that a LOCATION UPDATING is necessary, + * it can only be a periodic location updating or an unnecessary + * trigger for an IMSI attach location updating. + */ + if (mm_data->first_attach) + { + assert (mm_data->mm.mm_info.att EQ ATT_NOT_ALLOW); + + /* + * Start BCCH with broadcasted value. It could be discussed + * it the better time would have been after RR_ACTIVATE_IND. + */ + mm_start_t3212_bcch(); + + mm_data->first_attach_mem = mm_data->first_attach; + mm_data->first_attach = FALSE; + + mm_mmgmm_reg_cnf (); + } + else + { + /* + * GMM should not trigger a periodic location updating + * if this is not announced by the cell, but anyway, it does not + * do any harm to check this condition here. + */ + if (mm_data->mm.mm_info.t3212 NEQ T3212_NO_PRD_UPDAT) + { + mm_data->attempt_cnt = 0; /* Just to be safe */ + mm_periodic_loc_upd (); + } + else + { + mm_mmgmm_reg_cnf (); + } + } + break; + + case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */ + mm_data->attempt_cnt = 0; // Patch HM 14-Feb-02, GSM 11.10 44.2.1.2.8 + mm_normal_loc_upd (); + break; + + case MM_IDLE_LIMITED_SERVICE: /* 19.3 */ + if (mm_data->reg.op.m EQ M_MAN) + { + mm_data->attempt_cnt = 0; + mm_normal_loc_upd (); + } + else + { + TRACE_EVENT ("GMM triggered invalid update, not done."); + mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, + SEARCH_NOT_RUNNING, + FORB_PLMN_NOT_INCLUDED); + } + break; + + case MM_IDLE_NO_IMSI: /* 19.4 */ + mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, + SEARCH_NOT_RUNNING, + FORB_PLMN_NOT_INCLUDED); + break; + + case MM_IDLE_NO_CELL_AVAILABLE: /* 19.5 */ + mm_mmgmm_nreg_ind (NREG_NO_SERVICE, + SEARCH_NOT_RUNNING, + FORB_PLMN_NOT_INCLUDED); + break; + + case MM_IDLE_LUP_NEEDED: /* 19.6 */ + /* + * Start location update procedure in remote controlled form, + * the type of location update may be NORMAL_LUP or IMSI_ATTACH_LUP. + * MM already knows from the state that it needs a remote controlled + * location updating. + */ + if (!mm_normal_upd_needed ()) + { + /* Send fake MMGMM_LUP_ACCEPT_IND to indicate the full service + * condition already (which is a fact if only IMSI ATTACH needed). */ + mm_mmgmm_lup_accept_ind (); + + mm_data->attempt_cnt = 0; /* Power on, SIM inserted */ + mm_attach_loc_upd (); + } + else + { + mm_data->attempt_cnt = 0; /* Change of LA detected */ + mm_normal_loc_upd (); + } + break; + + case MM_IDLE_PLMN_SEARCH: /* 19.7 */ + if (mm_data->idle_substate EQ MM_IDLE_NO_CELL_AVAILABLE) + { + mm_mmgmm_nreg_ind (NREG_NO_SERVICE, + SEARCH_NOT_RUNNING, + FORB_PLMN_NOT_INCLUDED); + break; + } + /*FALLTHROUGH*/ + //lint -fallthrough + case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */ + /* Scan aborted, notify MMI */ + mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); + + /* Back to previous, non-searching IDLE substate */ + SET_STATE (STATE_MM, mm_data->idle_substate); + + /* Restart the function in new state, avoid recursion, stack usage */ + goto restart_function; + + default: + TRACE_EVENT (UNEXPECTED_IN_STATE); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_auth_rej_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_AUTH_REJ_REQ primitive. + MMGMM_AUTH_REJ_REQ indicates MM that the authentication procedure + performed by GMM is rejected by the network. For further details, + see GSM 04.08 subclause 4.3.2.5. + +*/ + +GLOBAL void mm_func_mmgmm_auth_rej_req (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_auth_rej_req()"); + + switch (GET_STATE (STATE_MM)) + { + case MM_IDLE_NORMAL_SERVICE: + case MM_IDLE_ATTEMPT_TO_UPDATE: + case MM_IDLE_LIMITED_SERVICE: + case MM_IDLE_NO_IMSI: + case MM_IDLE_NO_CELL_AVAILABLE: + case MM_IDLE_LUP_NEEDED: + case MM_IDLE_PLMN_SEARCH: + case MM_PLMN_SEARCH_NORMAL_SERVICE: + case MM_LOCATION_UPDATING_PENDING: + case MM_IMSI_DETACH_PENDING: + /* Release all calls, can only be stored calls */ + mm_mmxx_rel_ind (MMCS_NO_REGISTRATION, CM_NOT_IDLE); + + /* + * Upon receipt of an AUTHENTICATION REJECT message, the mobile station + * shall set the update status in the SIM to U2 ROAMING NOT ALLOWED, + * delete from the SIM the stored TMSI, LAI and ciphering key sequence + * number. [GSM 04.08 subclause 4.3.2.5] + */ +#ifdef REL99 + reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE); +#else + reg_invalidate_upd_state (MS_LA_NOT_ALLOWED); +#endif + + /* Delete IMSI - consider SIM as invalid */ + mm_clear_mob_ident (&mm_data->reg.imsi_struct); + mm_clear_reg_data (); + + /* Inform RR about invalidation */ + mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG); + + /* Set new MM main state */ + SET_STATE (STATE_MM, MM_IDLE_NO_IMSI); + break; + + default: /* No IDLE state */ + /* + * This means: Either this is an internal protocol error or we are + * performing circuit switched and packed switched operations in + * parallel. MM does not handle this. As it seems so that + * the networks will never support this it makes no sense to handle it. + */ + TRACE_ERROR (UNEXPECTED_IN_STATE); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_cm_establish_res | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_CM_ESTABLISH_RES primitive. + MMGMM_CM_ESTABLISH_RES confirms the establish request. + +*/ + +GLOBAL void mm_func_mmgmm_cm_establish_res (UBYTE cm_establish_res) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_cm_establish_res()"); + + switch (GET_STATE (STATE_GPRS_CM_EST)) + { + case CM_GPRS_EST_PEND: /* Normal case */ + break; + + case CM_GPRS_EST_OK: /* Clash MO/MT, special case */ + TRACE_EVENT ("MO/MT clash"); + return; + + default: + TRACE_ERROR ("Unexpected STATE_GPRS_CM_EST"); + break; + } + + if (cm_establish_res EQ MMGMM_ESTABLISH_OK) + { + mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; + + SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK); + + if (mm_count_connections (CM_NOT_IDLE) EQ 0) + { + /* + * In the meantime, all the stored connections have been cleared + * Worst case assumption: MMGMM_RESUMPTION_FAILURE. + */ + mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); + } + else + { + /* + * Now all the stored establish requests may be performed + */ + USE_STORED_ENTRIES(); + } + } + else /* cm_establish_res EQ MMGMM_ESTABLISH_REJECT */ + { + /* Clear outstanding MMGMM_CM_ESTABLISH_IND */ + SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_IDLE); + + /* Release all connections, there can only be stored connections */ + mm_mmxx_rel_ind (MMCS_INT_NOT_PRESENT, CM_NOT_IDLE); + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_cm_emergency_res | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_CM_EMERGENCY_RES primitive. + MMGMM_CM_EMERGENCY_RES confirms the establish request. + +*/ + +GLOBAL void mm_func_mmgmm_cm_emergency_res (UBYTE cm_establish_res) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_cm_emergency_res()"); + + switch (GET_STATE (STATE_GPRS_CM_EST)) + { + case CM_GPRS_EST_PEND: /* Normal case */ + case CM_GPRS_EMERGE_PEND: + break; + + case CM_GPRS_EST_OK: /* Clash MO/MT, special case */ + TRACE_EVENT ("MO/MT clash"); + return; + + default: + TRACE_ERROR ("Unexpected STATE_GPRS_CM_EST"); + break; + } + + if (cm_establish_res EQ MMGMM_ESTABLISH_OK) + { + mm_data->gprs.resumption = MMGMM_RESUMPTION_FAILURE; + + SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK); + + if (mm_count_connections (CM_NOT_IDLE) EQ 0) + { + /* + * In the meantime, all the stored connections have been cleared + * Worst case assumption: MMGMM_RESUMPTION_FAILURE. + */ + mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); + } + else + { + /* + * Now all the stored establish requests can be performed + */ + USE_STORED_ENTRIES(); + } + } + else /* cm_establish_res EQ MMGMM_EMERGENCY_REJECT */ + { + /* Clear outstanding MMGMM_CM_ESTABLISH_IND */ + SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_IDLE); + + /* Release all connections, there can only be stored connections */ + mm_mmxx_rel_ind (MMCS_INT_NOT_PRESENT, CM_NOT_IDLE); + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_attach_started_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_ATTACH_STARTED_REQ primitive. + GMM indicates MM that GMM starts the combined attach procedure. + This implies also network mode I. + +*/ + +GLOBAL void mm_func_mmgmm_attach_started_req (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_attach_started_req()"); + + switch (GET_STATE (STATE_MM)) + { + case MM_IDLE_LUP_NEEDED: + assert (GET_STATE (STATE_REG_TYPE) EQ REG_CELL_SEARCH_ONLY); + /*FALLTHROUGH*/ + //lint -fallthrough + case MM_IDLE_NORMAL_SERVICE: + case MM_IDLE_ATTEMPT_TO_UPDATE: + case MM_IDLE_LIMITED_SERVICE: + case MM_PLMN_SEARCH_NORMAL_SERVICE: + case MM_LOCATION_UPDATING_PENDING: + case MM_IMSI_DETACH_PENDING: + + /* IMSI present physically */ + assert (mm_data->reg.imsi_struct.v_mid EQ V_MID_PRES AND + !mm_data->gprs.sim_physically_removed); + + /* Revalidate SIM data */ + mm_data->reg.op.sim_ins = SIM_INSRT; + + /* Prevent MM specific procedures (location updating/detach) */ + SET_STATE (STATE_REG_TYPE, REG_CELL_SEARCH_ONLY); + + /* + * A GPRS MS operating in mode A or B in a network that operates in + * mode I should not use any MM timers relating to MM specific + * procedures, (e.g T3210, T3211, T3212, T3213) except in some error + * and abnormal cases. If the MM timers are already running, the MS + * should not react on the expiration of the timers. + * + * NOTE 2: Whenever GMM performs a combined GMM procedure, + * a GPRS MS enters the MM state MM LOCATION UPDATING PENDING in order + * to prevent the MM to perform a location update procedure. + * + * [GSM 04.08 subclause 4.1.1.2.1, + * GPRS MS operating in mode A or B in a network that operates in mode I] + */ + + /* + * As GMM sends the primitive MMGMM_ATTACH_STARTED_REQ if it begins a combined + * attach procedure, MM is cautious not to stop any timer here already. + * This is left up to the reception of MMGMM_ATTACH_ACC_REQ. + */ + + /* + * LOCATION UPDATING PENDING + * + * A location updating has been started using the combined + * GPRS routing area updating procedure. + * + * [GSM 04.08 subclause 4.1.2.1.1, Main states] + */ + + /* Remember service state */ + mm_data->idle_substate = mm_get_service_state (); + + // + // MM_LOCATION_UPDATING_PENDING is a superflous state. + // Don't enter it. + // + //SET_STATE (STATE_MM, MM_LOCATION_UPDATING_PENDING); + break; + + default: + TRACE_ERROR (UNEXPECTED_IN_STATE); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_attach_acc | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_ATTACH_ACC_REQ primitive. + GMM informs MM about the successfull combined attach procedure + and sends the new TMSI, if available, to MM. + This implies also network mode I. + +*/ + +LOCAL void mm_attach_acc (const T_plmn *plmn, + USHORT lac, + UBYTE v_mobile_identity, + ULONG mobile_identity, + UBYTE v_equ_plmn_list, + const T_equ_plmn_list *equ_plmn_list) +{ + GET_INSTANCE_DATA; + BOOL eplmn_changed; + + TRACE_FUNCTION ("mm_attach_acc()"); + + /* All other conditions are an internal protocol failure here */ + assert (GET_STATE (STATE_REG_TYPE) EQ REG_CELL_SEARCH_ONLY); + + /* It is not specified that MM has to confirm a MMGMM_ATTACH_ACC_REQ, + * GMM is informed about full service condition */ + mm_data->reg.full_service_indicated = TRUE; + + /* Remember IMSI ATTACH has been done. */ + if (mm_data->first_attach) + { + mm_data->first_attach_mem = mm_data->first_attach; + mm_data->first_attach = FALSE; + } + + /* Remember MM was attached by combined attach/detach procedures */ + mm_data->gprs.combined_procedures = TRUE; + mm_data->reg.update_stat = MS_UPDATED; + mm_data->rej_cause = 0; + mm_data->attempt_cnt = 0; + mm_data->loc_upd_type.lut = NOT_RUNNING; + + if (memcmp(mm_data->reg.lai.mnc, plmn->mnc, SIZE_MNC) OR memcmp (mm_data->reg.lai.mcc, plmn->mcc, SIZE_MCC) OR (mm_data->reg.lai.lac NEQ lac)) + { + /* EF LOCI value has changed, hence write it on SIM */ + /* EF Indicator for EF LOCI - bit 1 - changed value from Attach Accept msg*/ + mm_data->ef_indicator|=0x01; + } + /* Copy PLMN and LAC into registration data */ + memcpy (mm_data->reg.lai.mnc, plmn->mnc, SIZE_MNC); + memcpy (mm_data->reg.lai.mcc, plmn->mcc, SIZE_MCC); + mm_data->reg.lai.lac = lac; + + if (v_mobile_identity EQ MMGMM_TMSI_USED) + { + /* Remember GMM's TMSI to avoid unnecessary synchronization */ + mm_data->reg.indicated_tmsi = mobile_identity; + + if (mobile_identity NEQ mm_data->reg.tmsi) + { + /* EF LOCI value has changed, hence write it on SIM */ + /* EF Indicator for EF LOCI - bit 1 - changed value from Attach Accept msg*/ + mm_data->ef_indicator|=0x01; + } + if (mobile_identity NEQ MMGMM_TMSI_INVALID) + { + mm_data->reg.tmsi = mobile_identity; + + /* Inform RR about changed TMSI */ + mm_build_rr_sync_req_tmsi (); + } + else + { + mm_data->reg.tmsi = TMSI_INVALID_VALUE; + + /* Inform RR about invalidation of TMSI */ + mm_build_rr_sync_req_cause (SYNCCS_TMSI_INVAL); + } + } + + /* Remove the PLMN from the "forbidden PLMN" list */ + reg_plmn_bad_del (mm_data->reg.forb_plmn, MAX_FORB_PLMN_ID, plmn); + + /* Remove the PLMN from the "forbidden PLMNs for GPRS service" list */ + reg_plmn_bad_del (mm_data->reg.gprs_forb_plmn, MAX_GPRS_FORB_PLMN_ID, plmn); + + /* Send RR_SYNC_REQ (Location Area allowed) */ + mm_build_rr_sync_req_cause (SYNCCS_LAI_ALLOW); + + /* This is a nasty hack to process 'equ_plmn_list'. The function 'reg_store_eqv_plmns' + * can only take a 'T_eqv_plmn_list' Currently 'T_equ_plmn_list' is identical to 'T_eqv_plmn_list' + * in all but name hence making the casting OK, **for now**. This problem needs to be adressed + * in the air interface document. + */ + if (v_equ_plmn_list) + eplmn_changed = reg_store_eqv_plmns((T_eqv_plmn_list *)equ_plmn_list, (T_plmn *)plmn); + else + eplmn_changed = reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE); + + /* Send RR_SYNC_REQ (equivalent plmn list changed) */ + if(eplmn_changed) + mm_build_rr_sync_req_cause (SYNCCS_EPLMN_LIST); + + /* Inform SIM */ + reg_build_sim_update (); + + /* + * We assume the network has updated us for the currently selected cell, + * otherwise we will run into trouble. + */ + assert (mm_check_lai (&mm_data->reg.lai, &mm_data->mm.lai)); + + /* Stop all timers used for MM specific procedures */ + TIMERSTOP (T3210); + TIMERSTOP (T3211); + TIMERSTOP (T3212); + mm_data->t3212_timeout = FALSE; + + TIMERSTOP (T3213); + mm_data->t3213_restart = 0; +} + + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_attach_acc_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_ATTACH_ACC_REQ primitive. + GMM informs MM about the successfull combined attach procedure + and sends the new TMSI, if available, to MM. + This implies also network mode I. + +*/ + +GLOBAL void mm_func_mmgmm_attach_acc_req (const T_plmn *plmn, + USHORT lac, + UBYTE v_mobile_identity, + ULONG mobile_identity, + UBYTE v_equ_plmn_list, + const T_equ_plmn_list *equ_plmn_list) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_attach_acc_req()"); + + switch (GET_STATE (STATE_MM)) + { + 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_LUP_NEEDED: /* 19.6 */ + case MM_LOCATION_UPDATING_PENDING: + case MM_IMSI_DETACH_PENDING: + mm_attach_acc (plmn, lac, v_mobile_identity, mobile_identity, v_equ_plmn_list, equ_plmn_list); + + SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE); + USE_STORED_ENTRIES(); + break; + + case MM_IDLE_PLMN_SEARCH: /* 19.7 */ + mm_attach_acc (plmn, lac, v_mobile_identity, mobile_identity, v_equ_plmn_list, equ_plmn_list); + + SET_STATE (STATE_MM, MM_PLMN_SEARCH_NORMAL_SERVICE); + USE_STORED_ENTRIES(); + break; + + case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */ + mm_attach_acc (plmn, lac, v_mobile_identity, mobile_identity, v_equ_plmn_list, equ_plmn_list); + break; + + default: + TRACE_ERROR (UNEXPECTED_IN_STATE); + break; + } + + /* Check HPLMN timer state */ + reg_check_hplmn_tim (mm_data->reg.thplmn); + +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_allowed_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_ALLOWED_REQ primitive. + GMM informs MM that the attach procedure was accepted by the + network, but for GPRS services only. MM doesn't perform a state + change (especially GSM does not become idle updated on the cell + by receiving this event), but the location area is removed from + all forbidden lists. + +*/ + +GLOBAL void mm_func_mmgmm_allowed_req (UBYTE v_equ_plmn_list, const T_equ_plmn_list *equ_plmn_list) +{ + GET_INSTANCE_DATA; + T_plmn plmn; + BOOL eplmn_changed; + + TRACE_FUNCTION ("mm_mmgmm_allowed_req()"); + + /* Fill up the PLMN structure from the camped cell data */ + plmn.v_plmn = V_PLMN_PRES; + memcpy (plmn.mcc, mm_data->mm.lai.mcc, SIZE_MCC); + memcpy (plmn.mnc, mm_data->mm.lai.mnc, SIZE_MNC); + + /* Remove the PLMN from the "forbidden PLMN" list */ + reg_plmn_bad_del (mm_data->reg.forb_plmn, MAX_FORB_PLMN_ID, &plmn); + + /* Remove the PLMN from the "forbidden PLMNs for GPRS service" list */ + reg_plmn_bad_del (mm_data->reg.gprs_forb_plmn, MAX_GPRS_FORB_PLMN_ID, &plmn); + + /* Send RR_SYNC_REQ (Location Area allowed) */ + mm_build_rr_sync_req_cause (SYNCCS_LAI_ALLOW); + + /* This is a nasty hack to process 'equ_plmn_list'. The function 'reg_store_eqv_plmns' + * can only take a 'T_eqv_plmn_list' Currently 'T_equ_plmn_list' is identical to 'T_eqv_plmn_list' + * in all but name hence making the casting OK, for now. This problem needs to be adressed + * in the air interface document. + */ + if (v_equ_plmn_list) + eplmn_changed = reg_store_eqv_plmns((T_eqv_plmn_list *)equ_plmn_list, (T_plmn *)&plmn); + else + eplmn_changed = reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE); + + /* Send RR_SYNC_REQ (equivalent plmn list changed) */ + if(eplmn_changed) + mm_build_rr_sync_req_cause (SYNCCS_EPLMN_LIST); + + /* Update SIM */ + reg_build_sim_update (); + + /* Check HPLMN timer state */ + reg_check_hplmn_tim (mm_data->reg.thplmn); +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_attach_rej_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_ATTACH_REJ_REQ primitive. + GMM informs MM that the attach procedure was rejected by the + network with the given reject cause. According to the given + cause action in MM is taken. For further details, see + GSM 04.08 subclause 4.7.3.1.4 + + See also the GSM functions mm_lup_rej() and mm_loc_upd_rej(). + + This does *not* imply network mode I here, also other network + modes are possible here. MM need not have received the + MMGMM_ATTACH_STARTED_REQ message. + +*/ + +GLOBAL void mm_func_mmgmm_attach_rej_req (USHORT cs) /* T_MMGMM_ATTACH_REJ_REQ */ +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_attach_rej_req()"); + + TRACE_EVENT_P1 (" cs = %d", cs); + + /* All other conditions is an internal protocol failure here */ + assert (GET_STATE (STATE_REG_TYPE) EQ REG_CELL_SEARCH_ONLY); + + /* Check for correct originating entity */ + assert (GET_CAUSE_ORIGIN_ENTITY (cs) EQ + GMM_ORIGINATING_ENTITY); + + if (cs EQ GMMCS_GPRS_NOT_ALLOWED) + { + /* List of forbidden PLMNs for GPRS services has no meaning anymore */ + reg_clear_plmn_list (mm_data->reg.gprs_forb_plmn, MAX_GPRS_FORB_PLMN_ID); + + return; /* No further impact on GSM side */ + } + + switch (GET_STATE (STATE_MM)) + { + case MM_NULL: /* MM is off, do nothing */ + break; + + case MM_LUP_INITIATED: + case MM_WAIT_FOR_OUTG_MM_CONN: + case MM_CONN_ACTIVE: + case MM_IMSI_DETACH_INIT: + case MM_PROCESS_PROMPT: + case MM_WAIT_FOR_NW_CMD: +#ifdef REL99 + case MM_RR_CONN_RELEASE_NOT_ALLOWED: +#endif + case MM_LUP_REJECTED: + case MM_WAIT_FOR_RR_CONN_LUP: + case MM_WAIT_FOR_RR_CONN_MM: + case MM_WAIT_FOR_RR_CONN_DETACH: + case MM_WAIT_FOR_REESTABLISH: + /* Abort to RR */ + mm_abort_connection (ABCS_NORM); + /*FALLTHROUGH*/ + //lint -fallthrough + default: /* These states have no existing or requested RR connection */ + /* Release all connections to CM */ + mm_mmxx_rel_ind (cs, CM_NOT_IDLE); + + /* CM control back to GMM */ + mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_OK); + + mm_data->rej_cause = cs; + + /* + * Set the attempt counter to the maximal possible value. This will + * ensure no own location updating attempt will be scheduled and MM + * will enter the state MM_IDLE_ATTEMPT_TO_UPDATE if an unspecified + * cause has been received by the network. + * An exception is GMMCS_GPRS_NOT_ALLOWED_IN_PLMN which shall + * not have any influence for GSM (except that the PLMN in question + * has to be added to the forbidden list for GPRS services). + */ + if (mm_data->rej_cause NEQ GMMCS_GPRS_NOT_ALLOWED_IN_PLMN) + mm_data->attempt_cnt = 4; + + mm_loc_upd_rej (); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_detach_started_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_DETACH_STARTED_REQ primitive. + GMM indicates MM that GMM starts the detach procedure for GSM. + MM has to enter state MM_IMSI_DETACH_PENDING. + See GSM 04.08 subclause 4.7.4.1. + The reception of this primitive is only possible if network mode I, + this means, combined procedures are performed. + +*/ + +GLOBAL void mm_func_mmgmm_detach_started_req (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_func_mmgmm_detach_started_req()"); + + /* Reception of this primitive is a protocol failure if GSM is alone. */ + assert (!mm_gsm_alone()); + + /* Remember combinded detach */ + mm_data->gprs.combined_procedures = TRUE; + + switch (GET_STATE (STATE_MM)) + { + case MM_NULL: /* MM is off, do nothing */ + case MM_IMSI_DETACH_PENDING: /* State already entered, do nothing */ + break; + + case MM_LUP_INITIATED: + case MM_WAIT_FOR_OUTG_MM_CONN: + case MM_CONN_ACTIVE: + case MM_IMSI_DETACH_INIT: + case MM_PROCESS_PROMPT: + case MM_WAIT_FOR_NW_CMD: +#ifdef REL99 + case MM_RR_CONN_RELEASE_NOT_ALLOWED: +#endif + case MM_LUP_REJECTED: + case MM_WAIT_FOR_RR_CONN_LUP: + case MM_WAIT_FOR_RR_CONN_MM: + case MM_WAIT_FOR_RR_CONN_DETACH: + case MM_WAIT_FOR_REESTABLISH: + /* Abort to RR */ + mm_abort_connection (ABCS_NORM); + /*FALLTHROUGH*/ + //lint -fallthrough + default: /* These states have no existing or requested RR connection */ + /* Release all connections to CM */ + mm_mmxx_rel_ind (MMCS_NO_REGISTRATION, CM_NOT_IDLE); + + /* Prevent MM specific procedures (location updating/detach) */ + SET_STATE (STATE_REG_TYPE, REG_CELL_SEARCH_ONLY); + + /* Stop all possibly running MM timers */ + TIMERSTOP (T3210); + TIMERSTOP (T3211); + TIMERSTOP (T3212); + mm_data->t3212_timeout = FALSE; + TIMERSTOP (T3213); + mm_data->t3213_restart = 0; + TIMERSTOP (T3220); + TIMERSTOP (T3230); + TIMERSTOP (T3240); + + /* Remember service state */ + mm_data->idle_substate = mm_get_service_state (); + + /* Enter state MM_IMSI_DETACH_PENDING */ + // + // MM_IMSI_DETACH_PENDING is a superflous state. Don't enter it. + // + //SET_STATE (STATE_MM, MM_IMSI_DETACH_PENDING); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_start_t3212_req | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the MMGMM_START_T3212_REQ primitive. + MMGMM_START_T3212_REQ indicates that GPRS is now detached after + combined attach state in network mode I. + MM has to start its own timer T3212 with the broadcasted value. + +*/ + +GLOBAL void mm_func_mmgmm_start_t3212_req (void) +{ + GET_INSTANCE_DATA; + T_TIME t3212_time; + + TRACE_FUNCTION ("mm_func_mmgmm_start_t3212_req()"); + + /* Reception of this primitive is a protocol failure if GSM is alone. */ + assert (!mm_gsm_alone()); + + /* + * If the detach type information element value indicates "GPRS detach + * without switching off" and the MS is attached for GPRS and non-GPRS + * services and the network operates in network operation mode I, then + * if in the MS the timer T3212 is not already running, the timer T3212 + * shall be set to its initial value and restarted after the + * DETACH REQUEST message has been sent. + * [GSM 04.08 subclause 4.7.4.1.1, + * MS initiated detach procedure initiation] + */ + + /* + * If the detach type information element value indicates "re-attach + * required" or "re-attach not required" and the MS is attached for GPRS + * and non-GPRS services and the network operates in network operation + * mode I, then if in the MS the timer T3212 is not already running, + * the timer T3212 shall be set to its initial value and restarted. + * [GSM 04.08 subclause 4.7.4.2.2, + * Network initiated GPRS detach procedure completion by the MS] + */ + + /* + * One thing is for sure: MM is not (anymore) attached by combined + * procedures if its own T3212 is running. On the other hand, GSM + * is not alone, but still performs its operation with GMM. + */ + mm_data->gprs.combined_procedures = FALSE; + + /* + * Start timer T3212 with broadcasted value. + */ + if (mm_data->t3212_cfg_counter NEQ 0 AND + mm_data->mm.mm_info.t3212 NEQ 0) + t3212_time = mm_data->t3212_cfg_counter; + else + t3212_time = mm_data->mm.mm_info.t3212 * 36; + + if (t3212_time NEQ 0) + { + TIMERSTART (T3212, t3212_time * T_T3212_TIC_VALUE); + } + else + { + TIMERSTOP (T3212); /* No periodic update timer */ + } +} + +#if 0 +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_func_mmgmm_trigger_req | ++----------------------------------------------------------------------------+ + + PURPOSE : Goal of this function is to ensure that the remaining + time before expiracy of the T_HPLMN timer is long enough. + Used to prevent from aborting a data transfer because of + a PLMN reselection. + +*/ + +GLOBAL void mm_func_mmgmm_trigger_req (void) +{ + TRACE_FUNCTION ("mm_func_mmgmm_trigger_req()"); + + /* Check if running first */ + if (TIMERACTIVE(T_HPLMN)) + { + T_TIME remaining_time; + + vsi_t_status (VSI_CALLER T_HPLMN, &remaining_time); + + /* Check if THPLMN is close from expiracy */ + if (remaining_time <= TICS_PER_DECIHOURS) + { + TRACE_EVENT("Kick HPLMN timer"); + reg_stop_hplmn_tim(); /* Not restarted if already running */ +/* if (mm_full_service_pplmn_scan()) +*/ + reg_check_hplmn_tim (1); /* Expiry not before 6 minutes */ + } + } +} +#endif + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_network_initiated_detach | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the network initiated detach received + by GMM and signalled to MM by using the MMGMM_NREG_REQ primitive + with cs EQ CS_DISABLE. + +*/ + +void mm_network_initiated_detach (USHORT cs) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_network_initiated_detach()"); + + switch (GET_STATE (STATE_MM)) + { + case MM_NULL: + /* No further action required */ + mm_mmgmm_nreg_cnf (mm_data->nreg_cause); + break; + + case MM_LUP_INITIATED: + case MM_CONN_ACTIVE: + case MM_IMSI_DETACH_INIT: + case MM_PROCESS_PROMPT: + case MM_WAIT_FOR_NW_CMD: +#ifdef REL99 + case MM_RR_CONN_RELEASE_NOT_ALLOWED: +#endif + case MM_LUP_REJECTED: + /* + * States where the mobile has a layer 2 connection + */ + + /* + * The problem with that all is the following: + * If we read GSM 04.08, subclause 4.7.4.2, it is not described + * what to do with a dedicated layer 2 connection. + * Entering state MM_WAIT_FOR_NW_CMD and wait for either CHANNEL RELEASE + * message in RR or for T3240 expiry in MM is not possible as it violates + * the standard, entering MM_IDLE state is requested. + * So the only way to get rid of an MM connection is a local release + * before entering MM_IDLE state. + * This is not described in GSM 04.08, subclause 4.7.4.2. + * Also is not described what to do with (pending) CM connections, compare + * this with the stardadization of the abort procedure (GSM 04.08, 4.3.5). + * The conclusion of this all is: It is either not foreseen or + * not yet standardized. So it still cannot be implemented in a + * standard conformant way. Class A is for further study in MM, really. + */ + + /*FALLTHROUGH*/ + case MM_WAIT_FOR_OUTG_MM_CONN: + case MM_WAIT_FOR_RR_CONN_LUP: + case MM_WAIT_FOR_RR_CONN_MM: + case MM_WAIT_FOR_RR_CONN_DETACH: + case MM_WAIT_FOR_REESTABLISH: + case MM_WAIT_FOR_RR_ACTIVE: + /* + * States where the mobile has a layer 2 connection requested + */ + TRACE_ERROR (UNEXPECTED_IN_STATE); + break; + + case MM_IDLE_NORMAL_SERVICE: + case MM_LOCATION_UPDATING_PENDING: + case MM_IMSI_DETACH_PENDING: + case MM_IDLE_ATTEMPT_TO_UPDATE: + case MM_IDLE_LIMITED_SERVICE: + case MM_IDLE_NO_IMSI: + case MM_IDLE_NO_CELL_AVAILABLE: + case MM_IDLE_LUP_NEEDED: + case MM_IDLE_PLMN_SEARCH: + case MM_PLMN_SEARCH_NORMAL_SERVICE: + /* Release all connections with appropriate cause to CM */ + mm_mmxx_rel_ind (cs, CM_NOT_IDLE); + + /* Inform GMM */ + mm_mmgmm_cm_release_ind (MMGMM_RESUMPTION_FAILURE); + + /* Handle the request of GMM like an location updating reject */ + mm_data->rej_cause = cs; + mm_loc_upd_rej (); + break; + + default: + /* All states caught, this means trouble */ + TRACE_ERROR (UNEXPECTED_DEFAULT); + break; + } +} + + +/* ++----------------------------------------------------------------------------+ +| PROJECT : GSM-PS (6147) MODULE : MM_MM | +| STATE : code ROUTINE : mm_sim_removed_gprs_active | ++----------------------------------------------------------------------------+ + + PURPOSE : This function handles the case that the SIM is removed when GPRS + is active. An IMSI DETACH cannot be done immediately as MM has no + knowledge about the network mode in the current design (which is + regarded as a disadvantage for this case). All calls are thrown + out and all update activities are to be stopped. + +*/ + +GLOBAL void mm_sim_removed_gprs_active (void) +{ + GET_INSTANCE_DATA; + TRACE_FUNCTION ("mm_sim_removed_gprs_active()"); + + /* Remember the cause for limited service */ + mm_data->limited_cause = MMCS_SIM_REMOVED; + + /* Release all CM connections to upper layers */ + mm_mmxx_rel_ind (MMCS_NO_REGISTRATION, CM_NOT_IDLE); + + /* Stop all running update timers and running attempts */ + TIMERSTOP (T_REGISTRATION); + TIMERSTOP (T3210); + TIMERSTOP (T3211); + TIMERSTOP (T3212); + TIMERSTOP (T3213); + mm_data->t3213_restart = 0; + mm_data->loc_upd_type.lut = NOT_RUNNING; + mm_data->idle_entry = RRCS_INT_NOT_PRESENT; + + switch (GET_STATE (STATE_MM)) + { + /* Dedicated or dedicated requested states */ + case MM_LUP_INITIATED: + case MM_WAIT_FOR_OUTG_MM_CONN: + case MM_CONN_ACTIVE: + case MM_IMSI_DETACH_INIT: + case MM_PROCESS_PROMPT: + case MM_WAIT_FOR_NW_CMD: +#ifdef REL99 + case MM_RR_CONN_RELEASE_NOT_ALLOWED: +#endif + case MM_LUP_REJECTED: + case MM_WAIT_FOR_RR_CONN_LUP: + case MM_WAIT_FOR_RR_CONN_MM: + case MM_WAIT_FOR_RR_CONN_DETACH: + /* Abort RR connection */ + mm_abort_connection (ABCS_NORM); + + /* No state change, wait for RR_RELEASE_IND in old state */ + break; + + default: /* All other states, especially IDLE states */ + if (GET_STATE (STATE_REG_TYPE) EQ REG_REMOTE_CONTROLLED) + { + /* Indicate end of RC update to GMM */ + mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, + SEARCH_NOT_RUNNING, + FORB_PLMN_NOT_INCLUDED); + } + break; + } +} + +#endif /* GPRS */ + +#endif /* MM_GPRS_C */