FreeCalypso > hg > fc-magnetite
view src/g23m-gsm/mm/mm_regs.c @ 460:4d4f0bba9469
doc/D-Sample written
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 19 Mar 2018 18:45:16 +0000 |
parents | 27a4235405c6 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : GSM-PS (8410) | Modul : MM_REGS +----------------------------------------------------------------------------- | 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 registration | capability of the module Mobility Managemant. +----------------------------------------------------------------------------- */ #ifndef MM_REGS_C #define MM_REGS_C #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" #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" #endif /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ /*==== TEST =====================================================*/ /* * ------------------------------------------------------------------- * SIGNAL Processing functions * ------------------------------------------------------------------- */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_mmr_auth_ind | +--------------------------------------------------------------------+ PURPOSE : Process the signal MMR_AUTH_IND. */ GLOBAL void reg_mmr_auth_ind (T_SIM_AUTHENTICATION_REQ *sim_auth_req) { GET_INSTANCE_DATA; MCAST (auth_req, D_AUTH_REQ); TRACE_FUNCTION ("reg_mmr_auth_ind()"); if(mm_data->last_auth_req_id != NOT_PRESENT_8BIT) { mm_data->last_auth_req_id++; } else { mm_data->last_auth_req_id = 0; } sim_auth_req->source = SRC_MM; sim_auth_req->req_id = mm_data->last_auth_req_id; sim_auth_req->cksn = auth_req->ciph_key_num.key_seq; memcpy (sim_auth_req->rand, auth_req->auth_rand.rand, sizeof (sim_auth_req->rand)); PSENDX (SIM, sim_auth_req); if (mm_data->last_auth_req_id != 0) { /* problem occurred!!!! */ #ifdef WIN32 vsi_o_ttrace (VSI_CALLER TC_FUNC, "Authentication problem occurred %d", mm_data->last_auth_req_id); #endif /* WIN32 */ } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_net_list | +--------------------------------------------------------------------+ PURPOSE : Build a list of available PLMNs for the MMI. Use the information received from RR to update MM's internal PLMN list used for MM's own operation. */ #if 0 // The old code GLOBAL void reg_net_list (const T_RR_ABORT_IND *rr_abort_ind) { TRACE_FUNCTION ("reg_net_list()"); /* Create the PLMN list for the MMI and send it */ reg_create_plmn_list (rr_abort_ind, WITH_ALL_PLMNS); if (mm_data->reg.plmn_cnt EQ 0) { if ((rr_abort_ind->op.service NEQ NO_SERVICE) AND (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL)) { mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE); } else { mm_mmgmm_plmn_ind (MMCS_SUCCESS); } } else { mm_mmgmm_plmn_ind (MMCS_SUCCESS); } /* Do not consider the forbidden PLMN's for MM's internal operation */ reg_create_plmn_list (rr_abort_ind, WITH_OTHER_PLMNS); switch (rr_abort_ind->op.service) { case NO_SERVICE: mm_mmgmm_nreg_ind (NREG_NO_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case LIMITED_SERVICE: mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case FULL_SERVICE: break; default: /* All possible values caught, this is garbage */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } } #else // The new code GLOBAL void reg_net_list (const T_RR_ABORT_IND *rr_abort_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("reg_net_list()"); if (rr_abort_ind->plmn_avail EQ 0) { /* * Distinguish between "no PLMN found" and search aborted * due to eg. paging in RR. In the future, we may introduce * a proper cause in the RR_ABORT_IND to distinguish this, * this here should work but is ugly. */ if ((rr_abort_ind->op.service NEQ NO_SERVICE) AND (rr_abort_ind->cause EQ RRCS_ABORT_CEL_SEL_FAIL)) { mm_mmgmm_plmn_ind (MMCS_PLMN_NOT_IDLE_MODE, NULL); } else { mm_mmgmm_plmn_ind (MMCS_SUCCESS, rr_abort_ind); } mm_data->reg.plmn_cnt = 0; } else { mm_mmgmm_plmn_ind (MMCS_SUCCESS, rr_abort_ind); } switch (rr_abort_ind->op.service) { case NO_SERVICE: mm_mmgmm_nreg_ind (NREG_NO_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case LIMITED_SERVICE: mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case FULL_SERVICE: break; default: /* All possible values caught, this is garbage */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } } #endif /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_rr_failure | +--------------------------------------------------------------------+ PURPOSE : Indication from MM/RR about unsuccessfull cell selection. The new service and the found PLMN indications are for- warded to MM. */ GLOBAL void reg_rr_failure (T_RR_ABORT_IND *rr_abort_ind) { GET_INSTANCE_DATA; unsigned i; BOOL actual_plmn_found; TRACE_FUNCTION ("reg_rr_failure()"); #if defined (WIN32) { TRACE_EVENT_P1 ("PLMN_AVAIL = %d", rr_abort_ind->plmn_avail); for (i = 0 ;i < rr_abort_ind->plmn_avail; i++) { TRACE_EVENT_P6 ("MCC=%x%x%x MNC=%x%x%x", rr_abort_ind->plmn[i].mcc[0], rr_abort_ind->plmn[i].mcc[1], rr_abort_ind->plmn[i].mcc[2], rr_abort_ind->plmn[i].mnc[0], rr_abort_ind->plmn[i].mnc[1], rr_abort_ind->plmn[i].mnc[2]); } } #endif /* #if defined (WIN32) */ if (rr_abort_ind->plmn_avail EQ 0 OR mm_data->reg.op.sim_ins EQ SIM_NO_INSRT) { /* * No PLMN delivered by RR to build a PLMN list or no SIM present */ switch (rr_abort_ind->op.service) { case NO_SERVICE: mm_mmgmm_nreg_ind (NREG_NO_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case LIMITED_SERVICE: mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; default: /* eg. FULL_SERVICE and reg_rr_failure => nonsense */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } /* Delete the PLMN list, currently no PLMN available */ mm_data->reg.plmn_cnt = 0; /* // First make sure to understand completely the underlying problem... // Patch HM 11.06.01, clear PLMN list in ACI and MM >>> mm_mmgmm_plmn_ind (MMCS_SUCCESS, rr_abort_ind); // Patch HM 11.06.01, clear PLMN list in ACI and MM <<< */ } else { /* * At least one PLMN found and SIM present, create PLMN list. * Depending on the selected mode (automatic or manual), * either select the next available PLMN or present the * list of PLMNs possibly providing full service to the user. */ switch (mm_data->reg.op.m) { case MODE_AUTO: // Note: There are better algorithms to decide whether an update // of the PLMN list is necessary or not, but for these we need the // information from RR whether a found PLMN/location area is // forbidden. This becomes especially TRUE for an exhausted PLMN // list as we waste a lot of battery here if there is no location // area suitable for full service available, but a lot of location // areas on VPLMNs which are forbidden for roaming. In this case we // run in a loop senseless activating VPLMN which don't provide // full service at all. /* * Don't update the PLMN list if the actual PLMN is a member * of the PLMN list delivered by RR and the current list is * non-exhaused. */ actual_plmn_found = FALSE; if (mm_data->reg.plmn_cnt > mm_data->reg.plmn_index) { /* * There is a non-exhausted list present in MM. * Check whether the actual PLMN is a member. */ for (i = 0; i < rr_abort_ind->plmn_avail; i++) { if (reg_plmn_equal_sim (&rr_abort_ind->plmn[i], &mm_data->reg.actual_plmn)) { actual_plmn_found = TRUE; break; } } if (!actual_plmn_found) { /* The requested PLMN was not found. Update outdated list. */ reg_create_plmn_list (rr_abort_ind, WITH_OTHER_PLMNS); } else { TRACE_EVENT ("PLMN list ignored"); } } else { /* No non-exhaused list present in MM. Take the new list from RR */ reg_create_plmn_list (rr_abort_ind, WITH_OTHER_PLMNS); } /* * Select the next PLMN if available * else indicate LIMITED SERVICE to MMI */ reg_plmn_select (FORB_PLMN_NOT_INCLUDED); break; case MODE_MAN: reg_create_plmn_list (rr_abort_ind, WITH_ALL_PLMNS); /* * Forward the PLMN list to MMI for selection */ switch (rr_abort_ind->op.service) { case NO_SERVICE: mm_mmgmm_nreg_ind (NREG_NO_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; case LIMITED_SERVICE: mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); break; default: /* eg. FULL_SERVICE and reg_rr_failure => nonsense */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } mm_data->plmn_scan_mmi = TRUE; mm_mmgmm_plmn_ind (MMCS_SUCCESS, rr_abort_ind); break; default: /* No mode left */ TRACE_ERROR (UNEXPECTED_DEFAULT); break; } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_mm_success | +--------------------------------------------------------------------+ PURPOSE : MM indicates successfull registration. */ GLOBAL void reg_mm_success (UBYTE service) { GET_INSTANCE_DATA; TRACE_FUNCTION ("reg_mm_success()"); if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT) { /* * No SIM is inserted */ mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); } else { /* * SIM is inserted */ if (service EQ LIMITED_SERVICE) { mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE, SEARCH_NOT_RUNNING, FORB_PLMN_NOT_INCLUDED); } else { /* * Send new PLMN identification to MMI or GMM. * In case we compile for a GPRS protocol stack, * we will not indicate end of procedure (entering IDLE state) * by MMGMM_REG_CNF, but sending an intermediate result (full service) * by MMGMM_LUP_ACCEPT_IND. */ #ifdef GPRS if (mm_data->gprs.reg_cnf_on_idle_entry) { mm_mmgmm_lup_accept_ind (); } else #endif { mm_mmgmm_reg_cnf (); } /* Check HPLMN timer state */ reg_check_hplmn_tim (mm_data->reg.thplmn); } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_mm_cell_selected | +--------------------------------------------------------------------+ PURPOSE : MM indicates successfull cell selection. */ GLOBAL void reg_mm_cell_selected (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("reg_mm_cell_selected()"); if (mm_gsm_alone() AND mm_data->reg.op.sim_ins EQ SIM_INSRT) { /* * GPRS is inactive (GSM only mobile or GPRS deactivated) AND * a valid SIM is inserted. These are the prerequisites to indicate * full service to the MMI after cell selection. */ if (!mm_normal_upd_needed()) { /* * If no normal update is needed, the next service state * is "normal service" regardless of the need of an IMSI * ATTACH. Normal calls are possible, so we have to indicate * full service to the MMI. */ mm_mmgmm_reg_cnf (); } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : MM_REG | | STATE : code ROUTINE : reg_mm_failure | +--------------------------------------------------------------------+ PURPOSE : MM indicates an internal failure during location updating. */ GLOBAL void reg_mm_failure (UBYTE forb_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("reg_mm_failure()"); if (!mm_lup_allowed_by_gmm()) { /* * Call of function caused by MMGMM_ATTACH_REJ_REQ * and not by own failed LOCATION UPDATING ATTEMPT - or - * by MMGMM_NREG_REQ with (cs EQ CS_DISABLE). */ // This means, in automatic mode we wait for a // GMM decision to try a location update in automatic // mode if there are further networks present. // We have to discuss this item for network mode I! /* * Check whether the MM failure was caused by MMGMM_NREG_REQ. */ if (mm_data->nreg_request) mm_mmgmm_nreg_cnf (mm_data->nreg_cause); return; } /* * The MM failure was caused by MM's own location updating procedure, * LOCATION UPDATING REJECT message has been received. */ /* * In automatic mode with valid SIM, select the next PLMN if available */ reg_plmn_select (forb_ind); } #endif