diff src/g23m-gsm/rr/rr_tim.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/rr/rr_tim.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,1259 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :
+|  Modul   :
++-----------------------------------------------------------------------------
+|  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 timer handling functions
+|             for the component DL of the mobile station
++-----------------------------------------------------------------------------
+*/
+
+#ifndef RR_TIM_C
+#define RR_TIM_C
+
+#define ENTITY_RR
+
+/*==== INCLUDES ===================================================*/
+
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>     /* offsetof */
+#include <stdio.h>      /* sprintf */
+#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_rr.h"
+#include "tok.h"
+#include "rr.h"
+#ifdef TI_PS_FF_AT_P_CMD_CTREG
+#include "cl_shrd.h"
+#endif /* TI_PS_FF_AT_P_CMD_CTREG */
+
+/*==== EXPORT =====================================================*/
+/*==== PRIVAT =====================================================*/
+#if !defined(ELEMENTS)
+#define ELEMENTS(array) (sizeof(array)/sizeof(array[0]))
+#endif  /* !ELEMENTS */
+
+/*==== VARIABLES ==================================================*/
+EXTERN UBYTE test_house;
+#ifdef TI_PS_FF_AT_P_CMD_CTREG
+EXTERN T_TIME cast2T_Time(UBYTE tab_val);
+#else
+EXTERN T_TIME lim_service_mode_time[25];
+#endif /* TI_PS_FF_AT_P_CMD_CTREG */
+/*
+ * In the old frame variant most of the timer handling is done
+ * in RR. RR has a timer pool and holds the dependency between
+ * logical timer and timer handle.
+ *
+ * With the new frame variant this is simplified. RR uses a constant
+ * for the timer and gets back the this constant after timeout.
+ *
+ * This is the reason why most of the functions are only needed for
+ * the old frame variant.
+ */
+
+/*==== FUNCTIONS ==================================================*/
+
+#if defined(TIMER_TRACE)
+static void  trace_timer (USHORT index, long value)
+{
+  GET_INSTANCE_DATA;
+/* Implements Measure#32: Row */
+  static T_S2I_STRING const tim_names[] =
+  {
+    S2I_STRING("T3110"),
+    S2I_STRING("T3122"),
+    S2I_STRING("T3126"),
+    S2I_STRING("T_RESELECT"),
+    S2I_STRING("TREG"),
+    S2I_STRING("TABORT"),
+    S2I_STRING("T_NO_RESELECT"),
+    S2I_STRING("TIM_EXT_MEAS"),
+    #if defined FF_EOTD
+    S2I_STRING("TAPDU"),
+    #endif /* FF_EOTD */
+    S2I_STRING("TNNN"),
+    S2I_STRING("TCSVALID"),
+    S2I_STRING("T_DEDICATED_MODE"),
+    S2I_STRING("T_PLMN_SEARCH"),
+    S2I_STRING("T_FAST_CS"),
+    S2I_STRING("T_NORMAL_CS")
+  };
+  switch(value)
+  {
+/* Implements Measure#32: Row 431, 432, 433 and 435 */
+    default:/* >0: start */
+      TRACE_TIMER_P2 ("T-Start:%s=%lu", S2I_STRING(tim_names[index]), value);
+      break;
+    case 0:/* EQ 0: stop */
+      TRACE_TIMER_P1 ("T-Stop:%s", S2I_STRING(tim_names[index]));
+      break;
+    case -1:/* -1: expire */
+      TRACE_TIMER_P1 ("T-Expired:%s ", S2I_STRING(tim_names[index]));
+      break;
+    case -2:/* -2: check */
+      if(rr_data->t_running[index])
+      { 
+        TRACE_TIMER_P1 ("T-Check:%s active", S2I_STRING(tim_names[index]));
+      }
+      else
+      { 
+        TRACE_TIMER_P1 ("T-Check:%s inactive", S2I_STRING(tim_names[index]));
+      }
+      break;
+  }
+}
+#else
+#define trace_timer(index,value)
+#endif  /* TIMER_TRACE */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_t3110                  |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer T3110. Timer is started after reception
+            of channel release message and controls layer 2 disconnection.
+            It starts the configuration of idle mode, if layer 2 has
+            not signalled in time the disconnection of the layer 2 link.
+
+*/
+
+GLOBAL void tim_t3110 (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_t3110()");
+
+  if (GET_STATE (STATE_DAT) EQ DAT_CHAN_REL)
+  {
+    /*
+     * Send STOP_DEDICATED_REQUEST to L1 and wait for confirmation 
+     */
+    att_stop_dedicated();
+  }
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_t3122                  |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer T3122. Started after reception of an
+            immediate assignment reject message. MM does not start
+            any new establishment during the timer is running.
+            After timeout MM is informed. New attempts from MM can
+            be started.
+
+*/
+
+GLOBAL void tim_t3122 (void)
+{
+  GET_INSTANCE_DATA;
+  PALLOC (sync, RR_SYNC_IND);
+
+  TRACE_FUNCTION ("tim_t3122()");
+
+  switch (GET_STATE (STATE_DAT))
+  {
+    case DAT_NULL:
+    case DAT_CELL_RESELECT:
+    case DAT_IDLE:
+    case DAT_IMM_ASS:
+    case DAT_IMM_ASS_1:
+      /*
+       * send the indication to MM that T3122 has
+       * timed-out.
+       */
+      sync->ciph              = NOT_PRESENT_8BIT;
+      sync->chm.ch_mode       = NOT_PRESENT_8BIT;
+      sync->synccs            = SYNCCS_T3122_TIM_OUT;
+      memset(&sync->mm_info, 0, sizeof(T_mm_info));
+      sync->mm_info.valid     = FALSE;
+      memset(&sync->bcch_info, 0, sizeof(T_bcch_info));
+      sync->bcch_info.v_bcch  = FALSE;
+
+      PSENDX (MM, sync);
+      srv_use_stored_prim ();
+      break;
+
+    default:
+      PFREE (sync);
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_t3126                  |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer T3126. This timer is used for two cases.
+            1. It controls that all random bursts are send during a
+               certain time. If (why ever) layer 1 does not confirm
+               all outgoing random bursts, this timer prevents RR
+               from stucking. This functionality is not described in
+               GSM and is introduced for security reasons.
+            2. It controls the reception of an immediate assignment
+               message. This is the normal GSM functionality.
+
+*/
+
+GLOBAL void tim_t3126 (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_t3126()");
+
+  if (GET_STATE (STATE_DAT) EQ DAT_IMM_ASS)
+  {
+    if (rr_data->ms_data.all_conf_received)
+    {
+      /*
+       * Normal GSM functionality. Control of the
+       * reception of immediate assignment messages.
+       */
+      TRACE_EVENT ("Immediate Assignment failed");
+
+      dat_send_release_ind ( RRCS_RND_ACC_FAIL );
+
+      /*
+       * Check if we have to do a cell reselection
+       * or if we can return directly to idle mode in the current
+       * cell
+       */
+      TRACE_EVENT("check rej_rec");
+      if (rr_data->imm_ass_rej_rec NEQ TRUE)
+      {
+        /*
+         * search for idle mode cell
+         * (exclude current serving cell, because
+         *  the random access was unsuccessfull)
+         */
+#ifdef GPRS
+        if(att_gprs_cell_has_pbcch())
+        {
+/*XY: inform GRR, and don't wait for CR_RSP we will get a CR_REQ in this case */
+          att_rrgrr_cr_ind(CR_REQ_CANDIDATE);
+          rr_data->gprs_data.start_proc = START_PROC_NOTHING;
+        }
+        else
+        {
+#endif
+
+          TRACE_EVENT_P1("rr_data->c_ncell_bcch: %x",rr_data->c_ncell_bcch);
+
+          /*There are three scenarios to be considered */
+          /*
+           * i   - The first MPH_MEASUREMENT_IND has not yet arrived
+           * ii  - The first MPH_MEASUREMENT_IND has arrived but not all 
+           *       the SIs have been received
+           * (These are managed below)
+           *
+           * iii - The first MPH_MEASUREMENT_IND has arrived and all the 
+           *       SIs have been received AND a reselection is pending
+           * This is managed in 'att_bcch_status_to_decoded()'
+           */
+
+         if(((rr_data->first_meas_received EQ TRUE) AND (rr_data->c_ncell_bcch EQ 0)) OR
+/* Implements RR Clone findings #8 */
+              att_cell_barred_status_cr_no_cr (SC_INDEX)
+              OR 
+             (rr_data->nc_data[SC_INDEX].c1 <= 0))
+          {
+/*XY:n inform GRR, and        wait for CR_RSP */
+#ifdef GPRS
+            att_start_cell_reselection_gprs (CELL_RESELECTION_RACH);
+#else
+            att_start_cell_reselection (CELL_RESELECTION_RACH);
+#endif
+          }
+          else
+          {
+            /*
+             * continue camping on current SC until indication of ncell BCCH info
+             * after first measurement indication
+             */
+             rr_data->resel_pending = TRUE;
+             att_return_to_idle();
+          }
+#ifdef GPRS
+        }
+#endif
+      }
+      else
+      {
+        /*
+         * we have received an IMMEDIATE ASSIGNMENT REJECT
+         * (the random access procedure was successfull, meaning
+         *  that an answer was received from the network, even
+         *  if the answer was negative)
+         * In this case we go directly back to the current
+         * serving cell
+         */
+#ifdef GPRS
+        if(att_gprs_cell_has_pbcch())
+        {
+/*XY: inform GRR, and don't wait for CR_RSP */
+          att_rrgrr_cr_ind(CR_SUSPENDED_IDLE);
+          rr_data->gprs_data.start_proc = START_PROC_NOTHING;
+        }
+#endif
+        att_return_to_idle();
+      }
+    }
+    else
+    {
+      /*
+       * Layer 1 has not confirmed all outgoing random bursts
+       * in time. Simulate that all confirmations have received
+       * and start second part of connection establishment
+       * with waiting for the immediate assignment.
+       */
+      TRACE_TIMER ("missing random acc cnf");
+
+      TIMERSTART (T3126, T3126_VALUE);
+      rr_data->ms_data.all_conf_received = TRUE;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_treselect              |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer T_RESELECT. The timer controls reception
+            of the whole BCCH during cell selection and cell reselection.
+
+*/
+
+GLOBAL void tim_treselect (void)
+{ 
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_treselect()");
+
+  switch (GET_STATE (STATE_ATT))
+  {
+    case ATT_CS2:
+#ifdef GPRS
+      if((rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_SI13) AND test_house)
+      {
+        if(rr_data->ms_data.rr_service EQ LIMITED_SERVICE)
+        {
+          /*
+           * We have found a 'potential' cell for limited service 
+           */
+          rr_data->nc_data[CR_INDEX].si13_loc_ind = SI13_NOT_PRESENT;
+          SET_STATE(STATE_GPRS, GPRS_ACTIVATED);
+          att_check_bcch_carrier ();
+          return;
+        }
+        else
+        {
+          /*
+           * There is a problem with some R&S tests where SI13 is indicated
+           * in SI3/4 but there is no SI13 transmitted by the tester. RR continues
+           * to wait to for SI13 having successfully received all other SI's from L1
+           *
+           * The timeout of T_RESELECT would cause this cell to be ignored and 
+           * RR would have instructed L1 to check the next BSIC.
+           * Thus, it can happen that after a failed scan of all subsequent frequencies, 
+           * MM is indicated with "no cell available" i.e. we lose a GSM-only healthy cell
+           *
+           * Mark the current arfcn as being eligible for LIM service, which RR can camp 
+           * onto on the next pass when looking for emergency cells.
+           */
+          if(dat_forb_lai_check (CR_INDEX))
+          {
+          att_store_plmn_in_found_list (&rr_data->nc_data[CR_INDEX].lai);
+          }
+          else
+          {
+            TRACE_EVENT ("Do not store Forbidden LAI PLMN in the found PLMN list");
+          }
+          cs_set_attributes (EMERGENCY_CELL,  rr_data->nc_data[CR_INDEX].arfcn);
+          TRACE_EVENT_P1("Setting %x as EMERG", rr_data->nc_data[CR_INDEX].arfcn);
+        }
+     }
+#endif
+
+      /*
+       * Sometimes SI 2Ter is indicated, but it is never sent
+       * With this patch the inconsistent BCCH is taken.
+       * Fix for defect OMAPS00069058: SI13 is indicated on EBCCH, but never
+       * received. The fix avoids ignoring this cell on TRESELECT timeout.
+       */
+      if ( (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_2TER)
+#ifdef GPRS
+          OR
+           (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_SI13)
+#endif
+         )
+      {
+        /*
+         * if at least the rest is available, check the
+         * BCCH carrier to camp on a cell.
+         */
+#ifdef GPRS
+        if ( (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_SI13) AND
+             (GET_STATE (STATE_GPRS) EQ GPRS_PIM_BCCH ) 
+           )
+        {
+          rr_data->nc_data[CR_INDEX].si13_loc_ind = SI13_NOT_PRESENT;
+          SET_STATE(STATE_GPRS, GPRS_ACTIVATED); 
+        }
+#endif
+        att_check_bcch_carrier ();
+      }
+      else
+      {
+        /*
+         * initialise the internal data for the next candidate,
+         * because the BCCH is not completely available.
+         */
+        srv_clear_list (&rr_data->cr_data.cd.ncell_list);
+        if (cs_sync_next ())
+        {
+          /*
+           * start FB/SB reading for the next channel.
+           */
+          SET_STATE (STATE_ATT, ATT_CS1);
+#ifdef GPRS
+          if (GET_STATE (STATE_GPRS) EQ GPRS_PIM_BCCH )
+          {
+            SET_STATE(STATE_GPRS, GPRS_ACTIVATED);
+          }
+#endif
+          rr_data->old_serving_cell = NOT_PRESENT_8BIT;
+        }
+      }
+      break;
+
+    case ATT_CS3:
+
+      if (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_2TER)
+      {
+        /*
+         * if all sys infos except SI 2Ter is available, check the
+         * BCCH carrier to camp on a cell.
+         * When GPRS is activate, ATT_STATE is changed from ATT_CS3 to
+         * ATT_IDLE following reception of rrgrr_cr_req from GRR. Hence
+         * it not approprite to check for ATT_STATE for cell reselection
+         * completion. A new flag has been introduced for this purpose.
+         * This is s temporary solution, untill CQ 24632 is submitted
+         * where the SI2TER functionality will be cleaned up.
+         */
+
+        rr_data->cr_treselect_exp = FALSE;
+
+        att_check_bcch_carrier ();
+
+        if(rr_data->cr_treselect_exp)
+        {
+          TRACE_EVENT("Cell Reselection Success");
+          /* cell reselection completed */
+          return;
+        }
+      }
+
+      TRACE_EVENT ("cell reselection failed");
+
+      /*
+       * reset the paging received flag.
+       */
+      rr_data->pag_rec = FALSE;
+      srv_clear_stored_prim (MPH_PAGING_IND);
+
+      /*
+       * Indicate failed reestablishment earlier
+       */
+      if (rr_data->sc_data.selection_type EQ BACK_FROM_DEDICATED_RLF)
+        dat_code_reestablishment_fail ();
+
+      /*
+       * start a cell selection after timeout.
+       */
+      rr_data->old_serving_cell = NOT_PRESENT_8BIT;
+
+    /*XY:n don't inform GRR , but call start_cs anyway */
+    
+    /* Cell Selection Improvements-LLD section:4.1.3.9
+     * Cell reselection fails due to T_RESELECT timer expiry
+     * Start Fast search
+     */
+#ifdef GPRS
+       att_start_cell_selection_gprs (RR_ORIGINATED,FAST_SEARCH_MODE);
+#else
+       att_start_cell_selection (RR_ORIGINATED, CS_NOT_PARALLEL ,FAST_SEARCH_MODE);
+#endif
+
+      break;
+
+    case ATT_IDLE:
+    case ATT_CON_EST:
+      /*
+       * Parallel scanning for a channel in idle mode has failed.
+       * Initialize the data for the next channel and start
+       * FB/SB reading for this channel.
+       */
+       #ifdef GPRS
+      if( rr_data->sc_data.selection_type EQ CELL_RESELECTION_ON_GPRS_ACT)
+      {
+       /* Cell Selection Improvements-LLD section:4.1.3.9           
+        * GPRS activation on current cell fails due to T_RESELECT timer
+        * expiry   
+        * Start Fast search
+        */
+        att_start_cell_selection_gprs(MM_ORIGINATED,FAST_SEARCH_MODE);
+      }
+      else
+      {
+      #endif
+      srv_clear_list (&rr_data->cr_data.cd.ncell_list);
+      cs_sync_next ();
+      #ifdef GPRS
+      }
+      #endif
+      break;
+    case ATT_CS_INIT:
+       /* Boot Time Performance Enhancement:           
+        * RR has not received the normal RR_ACTIVATE_REQ yet 
+        * Free the stored power_cnf and move back to ATT_NULL
+        */
+      if( srv_check_stored_prim(MPH_POWER_CNF))
+      {
+        srv_clear_stored_prim(MPH_POWER_CNF);
+      }
+      SET_STATE(STATE_CELL_SEL, CS_NULL);
+      SET_STATE(STATE_ATT, ATT_NULL);
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)     MODULE  : RR_TIM                       |
+| STATE   : code              ROUTINE : tim_plmn_search_expiry |
++--------------------------------------------------------------------+
+
+  PURPOSE : This timer expires to signal end on Manual cell selection.
+  
+*/
+GLOBAL void tim_plmn_search_expiry (void)
+{
+  GET_INSTANCE_DATA;
+  if(rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI)
+  {
+    /*
+    * Mark all ARFCN's as Checked !
+    * After the next MPH_BSIC_CNF & MPH_UNITDATA_IND,
+    * cs_sync_next_bsic() will return FALSE.
+    */
+    UBYTE i;
+    for ( i=0; i < rr_data->cs_data.max_arfcn; i++ )
+    {
+      rr_data->cs_data.attributes[i] |= CS_CHECK_FLAG;
+    }   
+  }  
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)     MODULE  : RR_TIM                       |
+| STATE   : code              ROUTINE : tim_tfast_cs                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : This timer expires to signal end on Fast Search. Currently
+            this function just traces the Black Listed channels
+            CSI-LLD section:4.1.3.4.1.9
+*/
+
+GLOBAL void tim_tfast_cs(void)
+{
+  TRACE_FUNCTION("tim_tfast_cs()");
+
+  srv_trace_black_list();
+  srv_trace_white_list();
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)     MODULE  : RR_TIM                       |
+| STATE   : code              ROUTINE : tim_tnormal_cs               |
++--------------------------------------------------------------------+
+
+  PURPOSE : This timer expires to signal end on Normal search.Currently
+            this function just traces the Black Listed channels
+            CSI-LLD section:4.1.3.4.1.10                     
+*/
+
+GLOBAL void tim_tnormal_cs(void)
+{
+  TRACE_FUNCTION("tim_tnormal_cs()");
+
+  srv_trace_black_list();
+  srv_trace_white_list();
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)     MODULE  : RR_TIM                       |
+| STATE   : code              ROUTINE : att_reset_registration_timer |
++--------------------------------------------------------------------+
+
+  PURPOSE : This function stops the registration timer early on
+            request of MMI / Keypad driver. This function can be called
+            to avoid too long periods between search attempts to come
+            back to coverage.
+
+*/
+
+GLOBAL void tim_reset_registration_timer (void)
+{
+  GET_INSTANCE_DATA;
+  T_TIME status = 0;
+
+  TRACE_FUNCTION ("tim_reset_registration_timer()");
+
+  /*
+   * depending on the current RR service
+   */
+  switch (rr_data->ms_data.rr_service)
+  {
+    case NO_SERVICE:
+    case LIMITED_SERVICE:
+      if (rr_data->ms_data.reg_counter >= 12)
+      {
+        /*
+         * Only if RR has searched already more then 12 times,
+         * that means there is a long period between search attempts
+         * from some minutes.
+         *
+         * Get the remaining time of the timer.
+         */
+        TIMER_STATUS (rr_handle, TREG, &status);
+        if (status)
+        {
+          /*
+           * if the timer is just running, stop the timer,
+           * reset the attempt counter and simulate timeout
+           * by starting the timer again for one second.
+           */
+          TIMERSTOP (TREG);
+          rr_data->ms_data.reg_counter = 0;
+          TIMERSTART (TREG, ONE_SEC);
+        }
+      }
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_treg                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer TREG. Used by RR to recover from
+            No service to limited / full service or
+            limited service to full service or
+            full service (non-HPLMN) to full service (HPLMN)
+
+*/
+
+GLOBAL void tim_treg (void)
+{
+  GET_INSTANCE_DATA;
+  U8 search_mode = 0;
+#ifdef GPRS
+  UBYTE state;
+#endif /* GPRS */
+#ifdef TI_PS_FF_AT_P_CMD_CTREG
+  BOOL ret;
+  UBYTE tab_val;
+#endif /* TI_PS_FF_AT_P_CMD_CTREG */
+  TRACE_FUNCTION ("tim_treg()");
+
+  /*
+   * clear old cell identification to
+   * signal with RR_ACTIVATE_IND to MM to force
+   * location updatings.
+   */
+  att_reset_old_lai_rac();
+  
+  /*
+   * due to : "Network not recovered after a manual registration failure"
+   * do nothing if measurement is running (RR is already in state ATT_CS1)
+   */
+  switch (GET_STATE (STATE_ATT))
+  {
+    case ATT_CS1:
+    case ATT_CS2:
+      break;
+
+    case ATT_CS3:
+    case ATT_DEDICATED:
+    case ATT_CON_EST:
+      /*
+       * handle the expiry event later after state change (by an
+       * additional expiry of TREG)
+       */
+      rr_data->treg_pending = TRUE;
+      break;
+    case ATT_IDLE:
+#ifdef GPRS
+      state = GET_STATE(STATE_GPRS);
+      switch(state)
+      {
+        case GPRS_PTM_BCCH:
+        case GPRS_PAM_BCCH:
+        case GPRS_PAM_PBCCH:
+        case GPRS_PTM_PBCCH:
+          rr_data->treg_pending = TRUE;
+          break;
+        default:
+          if(GET_STATE(STATE_CELL_SEL) EQ CS_CCO)
+            rr_data->treg_pending = TRUE;
+          break;
+      }
+      if(rr_data->treg_pending)
+      {
+        att_start_registration_timer();
+        break;
+      }
+#endif
+    /*lint -fallthrough*/
+    default:
+
+    /* Obtain the new search mode
+     * CSI-LLD : 4.1.3.4.1.5
+     */
+    search_mode = cs_get_new_search_mode();
+
+    switch (rr_data->ms_data.rr_service)
+    {
+      case NO_SERVICE:
+        /*
+         * actual there is no service. Depending on the
+         * last request from MM a limited service search
+         * or full service search is started.
+         */
+        /* XY:n inform GRR, and      wait for CR_RSP */
+#ifdef GPRS
+        att_start_cell_selection_gprs(RR_ORIGINATED,search_mode);
+#else
+        att_start_cell_selection(RR_ORIGINATED, CS_NOT_PARALLEL,search_mode);
+#endif
+        break;
+
+      case LIMITED_SERVICE:
+        /*
+         * actual there is limited service. Depending on the
+         * frequency area a limited service search or full service 
+         * search is started.
+         */    
+
+          /* Both American and European carriers are detected in 
+           * this area. Perform Non-Parallel search only when the 
+           * time gap between search attempts exceeds 2min
+           * CSI-LLD 4.3
+           */
+          if(rr_data->ms_data.reg_counter)
+          {
+#ifdef TI_PS_FF_AT_P_CMD_CTREG
+            ret = cl_shrd_get_treg(RR_MOD_LIMSERVICE_TIME,
+                                    (UBYTE)(rr_data->ms_data.reg_counter - 1),
+                                    &tab_val);
+            if (!ret)
+            {
+              /* Use default on failure */
+              tab_val = lim_service_mode_time [rr_data->ms_data.reg_counter-1];
+            }
+            rr_data->ms_data.reg_time_gap += cast2T_Time(tab_val);
+#else
+            /* Add the time gap between search attempts */
+            rr_data->ms_data.reg_time_gap += 
+              lim_service_mode_time[rr_data->ms_data.reg_counter-1];
+#endif /* TI_PS_FF_AT_P_CMD_CTREG */
+            TRACE_EVENT_P2("[%d]reg_counter, [%d]reg_time_gap", 
+              rr_data->ms_data.reg_counter,
+              rr_data->ms_data.reg_time_gap);
+          }
+
+          if((rr_data->ms_data.reg_counter < 20) AND 
+             (rr_data->ms_data.reg_time_gap < rr_data->dyn_config.lim_ser_nps_delay))
+          {
+            /* Perform parallel search if delay >= 2min. This is to allow time 
+             * for emergency calls
+             */
+            att_start_cell_selection(RR_ORIGINATED, CS_PARALLEL,search_mode); 
+          }
+          else
+          {
+
+            rr_data->ms_data.reg_time_gap = 0;
+
+            /* Perform Non-Parallel search every >= 2min */
+#ifdef GPRS
+            att_start_cell_selection_gprs(RR_ORIGINATED,search_mode);
+#else
+            att_start_cell_selection(RR_ORIGINATED, CS_NOT_PARALLEL,search_mode);
+#endif          
+        }
+        break;
+
+      case FULL_SERVICE:
+        /*
+         * actual there is full service. Nothing to do here.
+         */
+        break;
+    }
+    break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_tnnn                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer TNNN
+
+*/
+GLOBAL void tim_tnnn (void)
+{
+  GET_INSTANCE_DATA;
+  int   index;
+  BOOL  tnnn_active = FALSE;
+
+  for (index = 0; index < (int)ELEMENTS(rr_data->nc_data); index++)
+  {
+    if (rr_data->nc_data[index].tnnn)
+    {
+      rr_data->nc_data[index].tnnn--; /* decrement all active timer counts */
+      if (rr_data->nc_data[index].tnnn)
+        tnnn_active = TRUE;          /* at least one timer count active */
+      else
+      {
+/* Implements Measure#32: Row 442 */
+        switch(index)
+        {
+          case CR_INDEX:
+            TRACE_TIMER_P1 ("T-Expiry:TNNN[CR%d]", rr_data->nc_data[index].arfcn);
+            break;
+          case SC_INDEX:
+            TRACE_TIMER_P1 ("T-Expiry:TNNN[SC%d]", rr_data->nc_data[index].arfcn);
+            break;
+          default:
+            TRACE_TIMER_P1 ("T-Expiry:TNNN[%d]", rr_data->nc_data[index].arfcn);
+            break;
+        }
+      }
+    }
+  }
+
+  if (!tnnn_active)
+    TIMERSTOP (TNNN); /* no timer count active -> stop physical timer */
+}
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_tabort                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer TABORT
+
+*/
+GLOBAL void tim_tabort (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_EVENT("tim_tabort TIMEOUT");
+
+  /* Sometimes SI 2Ter is indicated but it is never sent.
+   * Wait till expiry of T_RESELECT Timer, to give more time to read SI 2Ter.
+   * Do not send RR_ABORT_IND in this special case,
+   * as this will cause MMI to show "No Network"
+   */
+  if( (rr_data->cr_data.cd.sys_info_read EQ SYS_INFO_EXCEPT_2TER) AND
+      ((GET_STATE(STATE_ATT) EQ ATT_CS2) OR (GET_STATE(STATE_ATT) EQ ATT_CS3)) )
+  {
+    TRACE_EVENT("SI2 Ter missing - wait for T_RESELECT expiry");
+    TIMERSTART (TABORT, TABORT_VALUE);
+    return;
+  }
+
+  /*If the MS is carrying out a search for a list of PLMNs, this may take */
+  /*longer than 10s and the MMI is not displaying the PLMN name */
+  /*Boot Time:If MM has initiated a power scan for quick registration
+    *do not send RR_ABORT_IND here. 
+    */
+  if((rr_data->ms_data.req_mm_service NEQ FUNC_NET_SRCH_BY_MMI) AND
+     (rr_data->ms_data.req_mm_service NEQ FUNC_ST_PWR_SCAN))
+  {
+    att_code_net_lost();
+#ifdef FF_PS_RSSI
+    RX_SetValue ( 0, RX_QUAL_UNAVAILABLE, RX_ACCE_UNAVAILABLE);
+#else
+    RX_SetValue (0);
+#endif
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS              MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : check_tnnn                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : Starts timer TABORT
+
+*/
+void tstart_tabort( USHORT val )
+{
+  GET_INSTANCE_DATA;
+  if( rr_data->net_lost )
+  {
+    if(!IS_TIMER_ACTIVE(TABORT))
+    {
+      TIMERSTART (TABORT, val);
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : check_tnnn                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : Checks to see if timer TNNN is running or not
+
+*/
+static int check_tnnn (void)
+{
+  GET_INSTANCE_DATA;
+  int nc;
+  int tnnn_active = FALSE;
+
+  /* check all timer counter for active state */
+  for (nc = 0; nc < (int)ELEMENTS(rr_data->nc_data); nc++)
+  {
+    if (rr_data->nc_data[nc].tnnn)
+    {
+      tnnn_active = TRUE;
+      break;
+    }
+  }
+  return tnnn_active;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : set_tnnn                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Sets timer TNNN
+
+*/
+GLOBAL void set_tnnn (int index, USHORT value)
+{
+  GET_INSTANCE_DATA;
+/* Implements Measure#32: Row 443 */
+  switch (index)
+  {
+    case CR_INDEX:
+      TRACE_TIMER_P2 ("T-Start:TNNN[CR%d]=%d", rr_data->nc_data[index].arfcn, value);
+      break;
+    case SC_INDEX:
+      TRACE_TIMER_P2 ("T-Start:TNNN[SC%d]=%d", rr_data->nc_data[index].arfcn, value);
+      break;
+    default:
+      TRACE_TIMER_P2 ("T-Start:TNNN[%d]=%d", rr_data->nc_data[index].arfcn, value);
+      break;
+  }
+
+  if (!check_tnnn ())
+  {/* up to now there are no timer counter active -> start physical timer */
+    trace_timer (TNNN, value);
+    rr_data->t_running[TNNN] = 1;
+
+    /*
+     * start physical periodically timer.
+     */
+        TIMER_PSTART (rr_handle, TNNN, ONE_SEC, ONE_SEC);
+  }
+
+  /* set the new timer counter */
+  rr_data->nc_data[index].tnnn = value / ONE_SEC;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : reset_tnnn                 |
++--------------------------------------------------------------------+
+
+  PURPOSE : Resets timer TNNN
+
+*/
+GLOBAL void reset_tnnn (int index)
+{
+  GET_INSTANCE_DATA;
+  if (rr_data->nc_data[index].tnnn)
+  {
+/* Implements Measure#32: Row 444 */
+    switch (index)
+    {
+      case CR_INDEX:
+        TRACE_TIMER_P1 ("T-Stop:TNNN[CR%d]", rr_data->nc_data[index].arfcn);
+        break;
+      case SC_INDEX:
+        TRACE_TIMER_P1 ("T-Stop:TNNN[SC%d]", rr_data->nc_data[index].arfcn);
+        break;
+      default:
+        TRACE_TIMER_P1 ("T-Stop:TNNN[%d]", rr_data->nc_data[index].arfcn);
+        break;
+    }
+
+    /* reset the timer counter */
+    rr_data->nc_data[index].tnnn = 0;
+
+    if (IS_TIMER_ACTIVE(TNNN) AND !check_tnnn ())
+      TIMERSTOP (TNNN);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : is_tnnn                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Returns value of timer TNNN
+
+*/
+GLOBAL int is_tnnn (int index)
+{
+  GET_INSTANCE_DATA;
+  if (rr_data->nc_data[index].tnnn)
+  {
+/* Implements Measure#32: Row 446 */
+    switch (index)
+    {
+      case CR_INDEX:
+        TRACE_TIMER_P2 ("T-Check:TNNN[CR%d]=%d", rr_data->nc_data[index].arfcn, 
+                rr_data->nc_data[index].tnnn*ONE_SEC);
+        break;
+      case SC_INDEX:
+        TRACE_TIMER_P2 ("T-Check:TNNN[SC%d]=%d", rr_data->nc_data[index].arfcn, 
+                rr_data->nc_data[index].tnnn*ONE_SEC);
+        break;
+      default:
+        TRACE_TIMER_P2 ("T-Check:TNNN[%d]=%d", rr_data->nc_data[index].arfcn, 
+                rr_data->nc_data[index].tnnn*ONE_SEC);
+        break;
+    }
+  }
+  else
+  {
+/* Implements Measure#32: Row 445 */
+    switch (index)
+    {
+      case CR_INDEX:
+        TRACE_TIMER_P1 ("T-Check:TNNN[CR%d] inactive", rr_data->nc_data[index].arfcn);
+        break;
+      case SC_INDEX:
+        TRACE_TIMER_P1 ("T-Check:TNNN[SC%d] inactive", rr_data->nc_data[index].arfcn);
+        break;
+      default:
+        TRACE_TIMER_P1 ("T-Check:TNNN[%d] inactive", rr_data->nc_data[index].arfcn);
+        break;
+    }
+  }
+
+  return rr_data->nc_data[index].tnnn;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_ext_meas               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer TIM_EXT_MEAS.
+
+*/
+
+GLOBAL void tim_ext_meas (void)
+{
+  TRACE_FUNCTION ("tim_ext_meas ()");
+  dat_emo_stop ( TRUE );
+}
+
+#if defined FF_EOTD
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)       MODULE  : RR_TIM                     |
+| STATE   : code                ROUTINE : tim_apdu                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Timeout of timer TAPDU.
+
+*/
+
+GLOBAL void tim_apdu (void)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_apdu ()");
+  rr_applic_rx_init ( &rr_data->applic_rx );
+}
+#endif /* FF_EOTD */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : RR_TIM                   |
+| STATE   : code                  ROUTINE : tim_exec_timeout         |
++--------------------------------------------------------------------+
+
+  PURPOSE : execute timeout for the new frame variant.
+
+*/
+
+GLOBAL void tim_exec_timeout (USHORT index)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_exec_timeout()");
+
+  if (index >= NUM_OF_RR_TIMERS)
+  {
+#if defined(TIMER_TRACE)
+    SYST_TRACE_P ((SYST, "tim_exec_timeout(%u)", index));
+#endif
+  }
+  else
+  {
+    if (index NEQ TNNN) /* TNNN timer has its own trace */
+    {
+      trace_timer (index, -1);
+      rr_data->t_running[index] = 0;
+    }
+
+    if (rr_data->t_expire[index])
+      rr_data->t_expire[index] ();
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : RR_TIM                   |
+| STATE   : code                  ROUTINE : tim_stop_timer           |
++--------------------------------------------------------------------+
+
+  PURPOSE : stop timer in the new frame variant.
+
+*/
+
+GLOBAL void tim_stop_timer (USHORT index)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_stop_timer()");
+
+  if (index >= NUM_OF_RR_TIMERS)
+  {
+#if defined(TIMER_TRACE)
+    SYST_TRACE_P ((SYST, "tim_stop_timer(%u)", index));
+#endif
+  }
+  else
+  {
+    trace_timer (index, 0);
+    rr_data->t_running[index] = 0;
+        TIMER_STOP (rr_handle, index);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : RR_TIM                   |
+| STATE   : code                  ROUTINE : tim_start_timer          |
++--------------------------------------------------------------------+
+
+  PURPOSE : start timer in the new frame variant.
+
+*/
+
+GLOBAL void tim_start_timer (USHORT index, T_TIME value)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_start_timer()");
+
+  if (index >= NUM_OF_RR_TIMERS)
+  {
+#if defined(TIMER_TRACE)
+    SYST_TRACE_P ((SYST, "tim_start_timer(%u)", index));
+#endif
+  }
+  else
+  {
+    trace_timer (index, value);
+    rr_data->t_running[index] = 1;
+    TIMER_START (rr_handle, index, value);
+   
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6147)         MODULE  : RR_TIM                   |
+| STATE   : code                  ROUTINE : tim_check_timer          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Checks if a specified timer is running
+
+*/
+#if defined(TIMER_TRACE)
+GLOBAL BOOL tim_check_timer(USHORT index)
+{
+  GET_INSTANCE_DATA;
+  TRACE_FUNCTION ("tim_check_timer()");
+
+  if (index >= NUM_OF_RR_TIMERS)
+  {
+    SYST_TRACE_P ((SYST, "tim_check_timer(%u)", index));
+    return FALSE;
+  }
+  else
+  {
+    trace_timer (index, -2);
+    return (rr_data->t_running[index]);
+  }
+}
+#endif  /* TIMER_TRACE */
+#endif /* RR_TIM_C */