diff src/g23m-gsm/mm/mm_regs.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_regs.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,566 @@
+/* 
++----------------------------------------------------------------------------- 
+|  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