view src/g23m-gsm/mm/mm_regs.c @ 639:026c98f757a6

tpudrv12.h & targets/gtm900.h: our current support is for MGC2GSMT version only As it turns out, there exist two different Huawei-made hw platforms both bearing the marketing name GTM900-B: one is MG01GSMT, the other is MGC2GSMT. The two are NOT fw-compatible: aside from flash chip differences which should be handled by autodetection, the two hw platforms are already known to have different RFFEs with different control signals, and there may be other differences not yet known. Our current gtm900 build target is for MGC2GSMT only; we do not yet have a specimen of MG01GSMT on hand, hence no support for that version will be possible until and unless someone provides one.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 30 Jan 2020 18:19:01 +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