diff src/g23m-gsm/rr/rr_em.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_em.c	Fri Oct 16 06:25:50 2020 +0000
@@ -0,0 +1,2107 @@
+/*	
++-----------------------------------------------------------------------------
+|  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 Module defines the engineering mode (EM) device driver for the
+|             G23 protocol stack. This driver is used to control all engineering
+|             mode related functions.
++-----------------------------------------------------------------------------
+*/
+
+#ifndef RR_EM_C
+#define RR_EM_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"
+#include "rr_em.h"
+
+/*==== EXPORT =====================================================*/
+
+/*==== VARIABLES ==================================================*/
+
+#ifdef FF_EM_MODE
+
+/*
+  These variables are used between entities. Even this is not a clean solution it is a straigth forward
+  way to reduce the overhead to a minimum. A clean solution would be based on an only usage of primitives
+  which would stress the os with no aditional advantage!!
+*/
+/* these are accessed by ACI */
+GLOBAL UBYTE    em_rr_sem_buffer [EM_RR_SEM_SIZE]; /*lint -esym(552,em_rr_sem_buffer) -esym(765,em_rr_sem_buffer ) */
+GLOBAL UBYTE    em_rr_sem_index;                  /*lint -esym(765,em_rr_sem_index)*/
+GLOBAL UBYTE    em_act_dlt = 0; /*lint -esym(765,em_act_dlt) | used by ALR */
+GLOBAL UBYTE    em_act_rlt = 0; /*lint -esym(765,em_act_rlt) | used by ALR */
+
+static USHORT ma [MAX_MA_CHANNELS];     /* MA list after starting time */
+static USHORT ma2[MAX_MA_CHANNELS];     /* MA list before starting time if available */
+static UBYTE  v_start=0;                  /* starting time valid */
+static UBYTE  maio2=0;
+
+static T_HANDLE  sem_EM_RR;
+static UBYTE em_rr_trace_occured;
+
+
+/* Event tracing flags for EM */
+GLOBAL BOOL rr_v[EM_MAX_RR_EVENTS];
+GLOBAL USHORT em_assign_fail_rr_cause;
+GLOBAL USHORT em_handover_fail_rr_cause;
+
+LOCAL void em_rr_sem_clear (void);
+LOCAL void rr_em_first_event_check(void);
+
+#endif /* FF_EM_MODE */
+
+/*==== FUNCTIONS ==================================================*/
+#ifdef FF_EM_MODE
+
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_get_hchn
++------------------------------------------------------------------------------
+|  Description  :  This function stores the hopping channels after change occured.
+|
+|  Parameters   :  channel_array  - channel mode 1
+|                  channel2_array - channel mode 2
+|                  start          - valid flag for channel mode2
+|                  maio_2         - MAIO for before time configuration
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+
+GLOBAL void dat_em_get_hchn (USHORT* channel_array, USHORT* channel2_array, UBYTE start,UBYTE maio_2)
+{
+ TRACE_FUNCTION ("dat_em_get_hchn()");
+
+ memset(ma, 0, 65);
+ memset(ma2, 0, 65);
+ memcpy(ma, channel_array, 65);
+ v_start = start;
+ if (v_start) {
+  maio2 = maio_2;
+  memcpy(ma2, channel2_array, 65); }
+}
+/*
++------------------------------------------------------------------------------
+|  Function     :  em_init_get_hchn
++------------------------------------------------------------------------------
+|  Description  :  initiates the hopping list. This is necessary, because a request
+|                  of the hopping list immideatly after switch on causes a reset.
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+
+GLOBAL void em_init_get_hchn ()
+{
+ TRACE_FUNCTION ("em_init_get_hchn()");
+
+ ma[0]  = NOT_PRESENT_16BIT;
+ ma2[0] = NOT_PRESENT_16BIT;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  em_get_first_codec
++------------------------------------------------------------------------------
+|  Description  :  Returns the highest bit rate AMR codec mode
+|  
+|  Parameters   :  acs - Active codec set
+|                  
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+
+GLOBAL UBYTE em_get_first_codec(UBYTE acs)
+{
+  UBYTE i;
+ 
+  /* Find Highest bit rate codec mode from ACS */
+  for(i=0;i<8;i++)
+  {
+    if((0x80>>i) & acs )
+      break;
+  }
+
+  /* First codec( Highest bit rate codec mode) */
+  return (EM_AMR_MODE_12_2-i);
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_sc_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_SC_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_SC_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_sc_info_req (T_EM_SC_INFO_REQ *em_sc_info_req)
+{
+  GET_INSTANCE_DATA;
+  PALLOC(em_sc_info_cnf, EM_SC_INFO_CNF);
+  memset (em_sc_info_cnf, 0, sizeof (T_EM_SC_INFO_CNF));
+ 
+  PFREE(em_sc_info_req);
+  TRACE_FUNCTION ("dat_em_sc_info_req()");
+
+  em_sc_info_cnf->vocoder = EM_VOC_NA;
+
+  switch (GET_STATE (STATE_ATT))
+  {
+    case ATT_IDLE:
+      if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+      {
+        em_sc_info_cnf->arfcn   = rr_data->nc_data[SC_INDEX].arfcn;
+        em_sc_info_cnf->c1      = rr_data->nc_data[SC_INDEX].c1;
+        em_sc_info_cnf->c2      = rr_data->nc_data[SC_INDEX].c2;
+        em_sc_info_cnf->rxlev   = rr_data->nc_data[SC_INDEX].rxlev;
+        em_sc_info_cnf->bsic    = rr_data->nc_data[SC_INDEX].bsic;
+        em_sc_info_cnf->dsc     = em_act_dlt;
+        em_sc_info_cnf->txlev   = rr_data->sc_data.cd.cell_options.pow_ctrl;
+        em_sc_info_cnf->tn      = rr_data->sc_data.chan_desc.tn;
+        em_sc_info_cnf->lac     = rr_data->nc_data[SC_INDEX].lai.lac;
+        em_sc_info_cnf->cba     = rr_data->nc_data[SC_INDEX].rach.cell_bar_access;
+        em_sc_info_cnf->cbq     = rr_data->nc_data[SC_INDEX].c2_par.cbq;
+        em_sc_info_cnf->cell_id = rr_data->nc_data[SC_INDEX].cell_id;
+        em_sc_info_cnf->cell_type_ind = EM_CELL_GSM;
+#ifdef GPRS
+        if(rr_data->nc_data[SC_INDEX].rac NEQ NOT_PRESENT_8BIT)
+          em_sc_info_cnf->cell_type_ind = EM_CELL_GPRS;
+#endif
+      }
+      else if (rr_data->nc_data[SC_INDEX].bcch_status EQ NON_DECODED)
+      {
+        em_sc_info_cnf->arfcn   = rr_data->nc_data[SC_INDEX].arfcn;
+        em_sc_info_cnf->rxlev   = rr_data->nc_data[SC_INDEX].rxlev;
+        em_sc_info_cnf->bsic    = rr_data->nc_data[SC_INDEX].bsic;
+      }
+      break;
+
+    case ATT_DEDICATED:
+      if (!rr_data->ms_data.measurement_report.valid)
+        break;
+
+      em_sc_info_cnf->arfcn    = rr_data->ms_data.measurement_report.arfcn;
+      em_sc_info_cnf->bsic     = rr_data->nc_data[SC_INDEX].bsic;
+      em_sc_info_cnf->txlev    = rr_data->sc_data.cd.cell_options.pow_ctrl;
+      em_sc_info_cnf->tn       = rr_data->sc_data.chan_desc.tn;
+      em_sc_info_cnf->lac      = rr_data->nc_data[SC_INDEX].lai.lac;
+      em_sc_info_cnf->cell_id  = rr_data->nc_data[SC_INDEX].cell_id;
+      em_sc_info_cnf->rxlev_f  = rr_data->ms_data.measurement_report.rx_lev_full;
+      em_sc_info_cnf->rxlev_s  = rr_data->ms_data.measurement_report.rx_lev_sub;
+      em_sc_info_cnf->rlt      = em_act_rlt;
+      em_sc_info_cnf->tav      = rr_data->sc_data.new_ta;
+      em_sc_info_cnf->rxqual_f = rr_data->ms_data.measurement_report.rx_qual_full;
+      em_sc_info_cnf->rxqual_s = rr_data->ms_data.measurement_report.rx_qual_sub;
+      em_sc_info_cnf->vocoder  = rr_data->sc_data.ch_mode;
+      if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+      {
+        em_sc_info_cnf->cell_type_ind = EM_CELL_GSM;
+#ifdef GPRS
+        if(rr_data->nc_data[SC_INDEX].rac NEQ NOT_PRESENT_8BIT)
+          em_sc_info_cnf->cell_type_ind = EM_CELL_GPRS;
+#endif
+      }
+      break;
+
+    default:
+      break;
+  }/*switch*/
+  PSENDX(MMI, em_sc_info_cnf);
+} /*dat_em_sc_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_nc_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_NC_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_NC_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_nc_info_req (T_EM_NC_INFO_REQ *em_nc_info_req)
+{
+  GET_INSTANCE_DATA;
+  UBYTE index = 0;
+  UBYTE index2 = 0;
+  PALLOC(em_nc_info_cnf, EM_NC_INFO_CNF);
+  memset (em_nc_info_cnf, 0, sizeof (T_EM_NC_INFO_CNF));
+  memset (em_nc_info_cnf->rac, 0xff, EM_MAX_NUM_NC);
+
+  PFREE(em_nc_info_req);
+  TRACE_FUNCTION ("dat_em_nc_info_req()");
+
+  switch (GET_STATE (STATE_ATT))
+  {
+    case ATT_IDLE:
+      for (index = 0 , index2 = 0 ; index < EM_MAX_NUM_NC ; index++)
+      {
+        if (rr_data->nc_data[index].bcch_status EQ DECODED)
+        {
+          em_nc_info_cnf->arfcn_nc[index2]    = rr_data->nc_data[index].arfcn;
+          em_nc_info_cnf->c1_nc[index2]       = rr_data->nc_data[index].c1;
+          em_nc_info_cnf->c2_nc[index2]       = rr_data->nc_data[index].c2;
+          em_nc_info_cnf->rxlev_nc[index2]    = rr_data->nc_data[index].rxlev;
+          em_nc_info_cnf->bsic_nc[index2]     = rr_data->nc_data[index].bsic;
+          em_nc_info_cnf->cell_id_nc[index2]  = rr_data->nc_data[index].cell_id;
+          em_nc_info_cnf->lac_nc[index2]      = rr_data->nc_data[index].lai.lac;
+          em_nc_info_cnf->frame_offset[index2]      = rr_data->ms_data.measurement_report.ncells.frame_offset[index];
+          em_nc_info_cnf->time_alignmt[index2]      = rr_data->ms_data.measurement_report.ncells.time_alignmt[index];
+          em_nc_info_cnf->cba_nc[index2]      = rr_data->nc_data[index].rach.cell_bar_access;
+          em_nc_info_cnf->cbq_nc[index2]      = rr_data->nc_data[index].c2_par.cbq;
+          em_nc_info_cnf->cell_type_ind[index2]     = EM_CELL_GSM;
+#ifdef GPRS
+          em_nc_info_cnf->rac[index2]               = rr_data->nc_data[index].rac;
+
+          /* rac in nc_data is set only when v_gprs_ind is present in SI3/SI4 rest
+             octets. Since v_gprs_ind is not stored,rac is used to check gprs 
+             support in the cell */
+          if(em_nc_info_cnf->rac[index2] NEQ NOT_PRESENT_8BIT)
+            em_nc_info_cnf->cell_type_ind[index2]   = EM_CELL_GPRS; 
+#endif
+          em_nc_info_cnf->cell_resel_offset[index2] = rr_data->nc_data[index].c2_par.cell_reselect_offset;
+          em_nc_info_cnf->temp_offset[index2]       = rr_data->nc_data[index].c2_par.temp_offset;
+          em_nc_info_cnf->rxlev_acc_min[index2]     = rr_data->nc_data[index].select_para.rxlev_access_min;
+          index2++;
+        } /* if decoded */
+
+        else if (rr_data->nc_data[index].bcch_status EQ NON_DECODED)
+        {
+          em_nc_info_cnf->arfcn_nc[index2]   = rr_data->nc_data[index].arfcn;
+          em_nc_info_cnf->rxlev_nc[index2]   = rr_data->nc_data[index].rxlev;
+          em_nc_info_cnf->bsic_nc[index2]    = rr_data->nc_data[index].bsic;
+          index2++;
+        } /* if non decoded */
+      } /* for */
+      em_nc_info_cnf->no_ncells = rr_data->ms_data.measurement_report.ncells.no_of_ncells;
+      break;
+
+    case ATT_DEDICATED:
+      {
+        if (!rr_data->ms_data.measurement_report.valid)
+          break;
+
+        em_nc_info_cnf->no_ncells = rr_data->ms_data.measurement_report.ncells.no_of_ncells;
+
+        for (index = 0; index< rr_data->ms_data.measurement_report.ncells.no_of_ncells; index++)
+        {
+          /*in the measurement report the cells are ordered by fieldstrength*/
+          em_nc_info_cnf->arfcn_nc[index]    = rr_data->ms_data.measurement_report.ncells.arfcn[index];
+          em_nc_info_cnf->rxlev_nc[index]    = rr_data->ms_data.measurement_report.ncells.rx_lev[index];
+          em_nc_info_cnf->bsic_nc[index]     = rr_data->ms_data.measurement_report.ncells.bsic[index];
+          em_nc_info_cnf->frame_offset[index]= rr_data->ms_data.measurement_report.ncells.frame_offset[index];
+          em_nc_info_cnf->time_alignmt[index]= rr_data->ms_data.measurement_report.ncells.time_alignmt[index];
+        } /*for*/
+      }/*case*/
+      break;
+
+    default:
+      break;
+  }/*switch*/
+  PSENDX(MMI, em_nc_info_cnf);
+}/*dat_em_nc_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_loc_pag_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_LOC_PAG_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_LOC_PAG_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_loc_pag_info_req (T_EM_LOC_PAG_INFO_REQ *em_loc_pag_info_req)
+{
+  GET_INSTANCE_DATA;
+  PALLOC(em_loc_pag_info_cnf, EM_LOC_PAG_INFO_CNF);
+  memset (em_loc_pag_info_cnf, 0, sizeof (T_EM_LOC_PAG_INFO_CNF));
+
+  PFREE(em_loc_pag_info_req);
+  TRACE_FUNCTION ("dat_em_loc_pag_info_req()");
+
+  if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+  {
+    memcpy(em_loc_pag_info_cnf->mcc, rr_data->nc_data[SC_INDEX].lai.mcc, SIZE_MCC);
+
+    /*check for MNC with 2 digits*/
+	/* Fixed for Issue 21468 */
+    if (rr_data->nc_data[SC_INDEX].lai.mnc[2] NEQ 0xF) /*defines a 3 digit NMC*/
+    {
+      memcpy(em_loc_pag_info_cnf->mnc, rr_data->nc_data[SC_INDEX].lai.mnc, SIZE_MNC);
+    }
+    else /*2 digit -> leave the first value empty*/
+    {
+      em_loc_pag_info_cnf->mnc[1] = rr_data->nc_data[SC_INDEX].lai.mnc[0];
+      em_loc_pag_info_cnf->mnc[2] = rr_data->nc_data[SC_INDEX].lai.mnc[1];
+    }
+
+    em_loc_pag_info_cnf->bs_pa_mfrms  = rr_data->nc_data[SC_INDEX].control_descr.bs_pa_mfrms;
+    em_loc_pag_info_cnf->t3212        = rr_data->nc_data[SC_INDEX].control_descr.t3212;
+  }
+
+  if (rr_data->ms_data.tmsi_available EQ TRUE)
+    em_loc_pag_info_cnf->tmsi       = rr_data->ms_data.tmsi_binary;
+
+  PSENDX(MMI, em_loc_pag_info_cnf);
+}/*dat_em_loc_pag_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_plmn_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_PLMN_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_PLMN_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_plmn_info_req (T_EM_PLMN_INFO_REQ *em_plmn_info_req)
+{
+  GET_INSTANCE_DATA;
+  PALLOC(em_plmn_info_cnf, EM_PLMN_INFO_CNF);
+  memset (em_plmn_info_cnf, 0, sizeof (T_EM_PLMN_INFO_CNF));
+  
+  PFREE(em_plmn_info_req);
+  TRACE_FUNCTION ("dat_em_plmn_info_req()");
+
+  em_plmn_info_cnf->no_creq_max = rr_data->nc_data[SC_INDEX].rach.max_retrans;
+  em_plmn_info_cnf->reest_flag  = rr_data->nc_data[SC_INDEX].rach.re;
+  em_plmn_info_cnf->txpwr_max   = rr_data->nc_data[SC_INDEX].select_para.ms_txpwr_max_cch;
+  em_plmn_info_cnf->rxlev_min   = rr_data->nc_data[SC_INDEX].select_para.rxlev_access_min;
+  em_plmn_info_cnf->rel_cause   = 0xff; /* these info will be parsed by aci */
+
+  PSENDX(MMI, em_plmn_info_cnf);
+}/*dat_em_plmn_info_req*/
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_cip_hop_dtx_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_CIP_HOP_DTX_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_CIP_HOP_DTX_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_cip_hop_dtx_info_req (T_EM_CIP_HOP_DTX_INFO_REQ *em_cip_hop_dtx_info_req)
+{
+  GET_INSTANCE_DATA;
+  UBYTE i;
+  PALLOC(em_cip_hop_dtx_info_cnf, EM_CIP_HOP_DTX_INFO_CNF);
+  memset (em_cip_hop_dtx_info_cnf, 0, sizeof (T_EM_CIP_HOP_DTX_INFO_CNF));
+
+  PFREE(em_cip_hop_dtx_info_req);
+  TRACE_FUNCTION ("dat_em_cip_hop_dtx_info_req()");
+
+  /* Intialize to 0xffff. No hopping channels */
+  em_cip_hop_dtx_info_cnf->hop_chn.ma[0]  = NOT_PRESENT_16BIT;
+  em_cip_hop_dtx_info_cnf->hop_chn2.ma[0] = NOT_PRESENT_16BIT;
+  
+  if((GET_STATE(STATE_ATT) EQ ATT_DEDICATED) AND 
+	                            (GET_STATE(STATE_DAT) EQ DAT_DEDICATED))
+  {
+    /* cipher status */
+    em_cip_hop_dtx_info_cnf->ciph_stat = rr_data->sc_data.ciph_on;
+
+    /* Hopping status */
+    em_cip_hop_dtx_info_cnf->hop = rr_data->sc_data.chan_desc.hop;
+
+    if (rr_data->sc_data.chan_desc.hop EQ H_NO)
+    { /* Hopping is not configured */
+      em_cip_hop_dtx_info_cnf->arfcn = rr_data->sc_data.chan_desc.arfcn;
+    }
+    else
+    { /* hopping sequence no   */
+      em_cip_hop_dtx_info_cnf->hsn    = rr_data->sc_data.chan_desc.hsn;
+    }
+
+    if(em_cip_hop_dtx_info_cnf->hop NEQ H_NO)
+    {
+      /* MAIO */
+      em_cip_hop_dtx_info_cnf->hop_chn.maio = rr_data->sc_data.chan_desc.maio;
+
+      i=0;
+      while((i<MAX_MA_CHANNELS) AND (ma[i] NEQ NOT_PRESENT_16BIT))
+      {
+        em_cip_hop_dtx_info_cnf->hop_chn.ma[i] = ma[i];
+        i++;
+      }
+    
+      /* Number of hopping channels */
+      em_cip_hop_dtx_info_cnf->hop_chn.nr_arfcns = i;
+      if(i < MAX_MA_CHANNELS) 
+      {
+        em_cip_hop_dtx_info_cnf->hop_chn.ma[i] = NOT_PRESENT_16BIT;
+      }
+
+      /* starting time status */
+      em_cip_hop_dtx_info_cnf->v_start = v_start;
+  
+      /* Hopping list after time */
+      if (v_start)
+      {
+        /* MAIO */
+        em_cip_hop_dtx_info_cnf->hop_chn2.maio = maio2;
+      
+        i=0;
+        while((i<MAX_MA_CHANNELS) AND (ma2[i] NEQ NOT_PRESENT_16BIT))
+        {
+          em_cip_hop_dtx_info_cnf->hop_chn2.ma[i] = ma2[i];
+          i++;
+        }
+        /* Number of hopping channels */
+        em_cip_hop_dtx_info_cnf->hop_chn2.nr_arfcns = i;
+        if(i < MAX_MA_CHANNELS)
+        {
+          em_cip_hop_dtx_info_cnf->hop_chn2.ma[i] = NOT_PRESENT_16BIT;
+        }
+      } /* v_start */
+      
+    } /* hop NEQ H_NO */
+  
+  } /* dedicated state */
+
+  /* DTX status */
+  em_cip_hop_dtx_info_cnf->dtx_stat  = rr_data->sc_data.cd.dtx; 
+
+  PSENDX(MMI, em_cip_hop_dtx_info_cnf);
+}/*dat_em_cip_hop_dtx_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_mobdata_power_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_POWER_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_POWER_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_mobdata_power_info_req (T_EM_POWER_INFO_REQ *em_power_info_req)
+{
+  GET_INSTANCE_DATA;
+  PALLOC(em_power_info_cnf, EM_POWER_INFO_CNF);
+
+  PFREE(em_power_info_req);
+
+  TRACE_FUNCTION ("dat_em_mobdata_power_info_req()");
+
+  memset (em_power_info_cnf, 0, sizeof (T_EM_POWER_INFO_CNF));
+  memcpy(&em_power_info_cnf->classm2, &rr_data->ms_data.classmark2, sizeof (T_classm2));
+  memcpy(&em_power_info_cnf->classm3, &rr_data->ms_data.classmark3, sizeof (T_classm3));
+
+  PSENDX(MMI, em_power_info_cnf);
+}/*dat_em_mobdata_power_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_mobdata_id_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_IDENTITY_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_IDENTITY_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_mobdata_id_info_req (T_EM_IDENTITY_INFO_REQ *em_identity_info_req)
+{
+  GET_INSTANCE_DATA;
+  PALLOC(em_identity_info_cnf, EM_IDENTITY_INFO_CNF);
+  memset (em_identity_info_cnf, 0, sizeof (T_EM_IDENTITY_INFO_CNF));
+
+  PFREE(em_identity_info_req);
+  TRACE_FUNCTION ("dat_em_mobdata_id_info_req()");
+
+  /*
+   *   The values for IMEI and IMEISV are identical up to the last 4bits. The 'ident_type' distinguish
+   *   IMEI and IMEISV where ident_type = 3 is synonymously with IMEISV. In case only IMEI is needed,
+   *   em_mm_mobdata_id_info_req->em_imei.ident_dig[16] should not considered.
+   */
+
+  em_identity_info_cnf->em_imeisv.ident_type   = rr_data->ms_data.imei.ident_type;
+  em_identity_info_cnf->em_imeisv.v_ident_dig  = rr_data->ms_data.imei.v_ident_dig;
+  em_identity_info_cnf->em_imeisv.c_ident_dig  = rr_data->ms_data.imei.c_ident_dig;
+  em_identity_info_cnf->em_imeisv.odd_even     = rr_data->ms_data.imei.odd_even;
+  memcpy (em_identity_info_cnf->em_imeisv.ident_dig, rr_data->ms_data.imei.ident_dig, 16);
+
+  if (rr_data->ms_data.imsi_available) /* SIM available */
+  {
+    em_identity_info_cnf->em_imsi.ident_type    = rr_data->ms_data.imsi.ident_type;
+    em_identity_info_cnf->em_imsi.v_ident_dig   = rr_data->ms_data.imsi.v_ident_dig;
+    em_identity_info_cnf->em_imsi.c_ident_dig   = rr_data->ms_data.imsi.c_ident_dig;
+    em_identity_info_cnf->em_imsi.odd_even      = rr_data->ms_data.imsi.odd_even;
+    memcpy (em_identity_info_cnf->em_imsi.ident_dig, rr_data->ms_data.imsi.ident_dig, 16);
+  }
+
+  if (rr_data->ms_data.tmsi_available EQ TRUE)
+    em_identity_info_cnf->tmsi     = rr_data->ms_data.tmsi_binary;
+
+  PSENDX(MMI, em_identity_info_cnf);
+} /*dat_em_mobdata_id_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_mobdata_version_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_SW_VERSION_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_SW_VERSION_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_mobdata_version_info_req (T_EM_SW_VERSION_INFO_REQ *em_sw_version_info_req)
+{
+  PALLOC(em_sw_version_info_cnf, EM_SW_VERSION_INFO_CNF);
+  PFREE(em_sw_version_info_req);
+
+
+  TRACE_FUNCTION ("dat_em_mobdata_version_info_req()");
+
+  memset (em_sw_version_info_cnf, 0, sizeof (T_EM_SW_VERSION_INFO_CNF));
+
+  em_sw_version_info_cnf->v_mmi  = 0xFF;
+  em_sw_version_info_cnf->v_sim  = 0xFF;
+  em_sw_version_info_cnf->v_cc   = 0xFF;
+  em_sw_version_info_cnf->v_ss   = 0xFF;
+  em_sw_version_info_cnf->v_sms  = 0xFF;
+  em_sw_version_info_cnf->v_mm   = 0xFF;
+  em_sw_version_info_cnf->v_rr   = 0xFF;
+  em_sw_version_info_cnf->v_dl   = 0xFF;
+  em_sw_version_info_cnf->v_l1   = 0xFF;
+
+  PSENDX(MMI, em_sw_version_info_cnf);
+}/*dat_em_mobdata_version_info_req*/
+
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_amr_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_AMR_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_AMR_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_amr_info_req (T_EM_AMR_INFO_REQ *em_amr_info_req)
+{
+  GET_INSTANCE_DATA;
+  UBYTE i=0;
+  PALLOC(em_amr_info_cnf, EM_AMR_INFO_CNF);
+  memset (em_amr_info_cnf, 0, sizeof (T_EM_AMR_INFO_CNF));
+ 
+  PFREE(em_amr_info_req);
+  TRACE_FUNCTION ("dat_em_amr_info_req()");
+
+  /* AMR information is valid only in dedicated state, when chan mode is AMR */
+  if((GET_STATE(STATE_ATT) EQ ATT_DEDICATED) AND 
+	                              (GET_STATE(STATE_DAT) EQ DAT_DEDICATED))
+  {
+    if(rr_data->sc_data.ch_mode EQ CM_AMR)
+    {
+      /* AMR vocoder type */
+      em_amr_info_cnf->amr_vocoder = rr_data->sc_data.chan_desc.chan_type;
+
+      /* Initial codec mode indicator */
+      em_amr_info_cnf->amr_icmi    = rr_data->sc_data.amr_conf.icmi;
+
+      /* Initial codec mode. Valid if icmi = 1(Start mode signalled) */
+      em_amr_info_cnf->amr_icm     = rr_data->sc_data.amr_conf.st_mode;
+
+      /* Active codec set */
+      em_amr_info_cnf->amr_acs     = rr_data->sc_data.amr_conf.set_amr;
+
+      /* First codec( Highest bit rate codec mode) */
+      em_amr_info_cnf->amr_first_codec = 
+                   em_get_first_codec(rr_data->sc_data.amr_conf.set_amr);
+
+      if(rr_data->sc_data.amr_conf.v_cod_prop)
+      {
+        /* Number of codec modes */
+        em_amr_info_cnf->amr_nr_modes = rr_data->sc_data.amr_conf.c_cod_prop + 1;
+
+        /* Threshold and Hysteresis properties between codec modes */
+        for(i=0;i<rr_data->sc_data.amr_conf.c_cod_prop;i++)
+        {
+          memcpy(&em_amr_info_cnf->amr_cod_prop[i],&rr_data->sc_data.amr_conf.cod_prop[i],
+                 sizeof(T_amr_cod_prop));
+        }
+      }  
+      else
+      {
+        /* Number of codec modes */
+        em_amr_info_cnf->amr_nr_modes = 1;
+      }
+    } /* CM_AMR */
+  } /* ATT DEDICATED */
+
+  PSENDX(MMI, em_amr_info_cnf);
+} /*dat_em_amr_info_req*/
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_init_rr_event_trace
++------------------------------------------------------------------------------
+|  Description  :  Initialize the event tracing flags for RR
+|
+|  Parameters   :  void
+|
+|  Return       :  void
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void em_init_rr_event_trace(void)
+{
+ UBYTE i;
+
+ TRACE_FUNCTION ("em_init_rr_event_trace()");
+
+ for (i=0; i< EM_MAX_RR_EVENTS; i++)
+   rr_v[i] = 0;
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : rr_em_rr_event_req
++------------------------------------------------------------------------------
+|  Description  :  Set the event tracing flags according the bitmask
+|
+|  Parameters   :  Primitive - Bitmask(T_EM_RR_EVENT_REQ)
+|
+|  Return       :  void
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void rr_em_rr_event_req (T_EM_RR_EVENT_REQ *em_rr_event_req)
+{
+ UBYTE i;
+
+ TRACE_FUNCTION ("rr_em_rr_event_req()");
+
+ /*
+  *  The event tracing flags are set according the bitmask. rr_v[i] are
+  *  the flags belonging to the event number described in 8443.601
+ */
+ for(i=1; i<33; i++)
+   rr_v[i] = ((em_rr_event_req->bitmask_rr_l & (0x01<<(i-1))) > 0) ? TRUE : FALSE;
+
+ for(i=33; i<(EM_MAX_RR_EVENTS); i++)
+   rr_v[i] = ((em_rr_event_req->bitmask_rr_h & (0x01<<(i-1))) > 0) ? TRUE : FALSE;
+
+ /*
+   A new event trace is generated therefor the flag is set to 0.
+ */
+ em_rr_trace_occured = 0;
+
+ PFREE(em_rr_event_req);
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_2
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define EVT_LEN_OFFSET     2  /* Event Number and Length value bytes */
+#define BUFFER_2_LENGTH   2
+GLOBAL UBYTE em_write_buffer_2 (UBYTE event_no)
+{
+ UBYTE em_rr_event_buffer[BUFFER_2_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_2()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;                      /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write]   = 0x00; /* Value length - 0 equals no data */
+
+ return (em_rr_sem (BUFFER_2_LENGTH, em_rr_event_buffer));              /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_3
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_3_LENGTH 3
+GLOBAL UBYTE em_write_buffer_3  (UBYTE event_no, UBYTE value)
+{
+ UBYTE em_rr_event_buffer[BUFFER_3_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_3()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;                /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_3_LENGTH-EVT_LEN_OFFSET;  /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write]   = value;                   /* Data to be stored */
+
+ return (em_rr_sem (BUFFER_3_LENGTH, em_rr_event_buffer));        /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_3a
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value (USHORT)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_3A_LENGTH 4
+GLOBAL UBYTE em_write_buffer_3a (UBYTE event_no, USHORT value)
+{
+ UBYTE em_rr_event_buffer[BUFFER_3A_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_3a()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_3A_LENGTH-EVT_LEN_OFFSET; /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = (UBYTE)(value >> 8);    /* Data to be stored - MSB first */
+ em_rr_event_buffer[em_rr_buffer_write++] = (UBYTE)(value );        /* LSB second */
+
+ return (em_rr_sem (BUFFER_3A_LENGTH, em_rr_event_buffer));      /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_4
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, length of data and value1 and value2
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_4_LENGTH 4
+GLOBAL UBYTE em_write_buffer_4  (UBYTE event_no, UBYTE value1, UBYTE value2)
+{
+ UBYTE em_rr_event_buffer[BUFFER_4_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_4()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_4_LENGTH-EVT_LEN_OFFSET;  /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value1;                 /* Value 1 */
+ em_rr_event_buffer[em_rr_buffer_write++] = value2;                 /* Value 2 */
+
+ return (em_rr_sem (BUFFER_4_LENGTH, em_rr_event_buffer));       /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_4a
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value, data cs (USHORT)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_4A_LENGTH 5
+GLOBAL UBYTE em_write_buffer_4a (UBYTE event_no, UBYTE value, USHORT cs)
+{
+ UBYTE em_rr_event_buffer[BUFFER_4A_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_4a()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_4A_LENGTH-EVT_LEN_OFFSET;  /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value;                  /* first data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = (UBYTE)(cs >> 8);       /* Data to be stored - MSB first */
+ em_rr_event_buffer[em_rr_buffer_write++] = (UBYTE)(cs);            /* LSB second */
+
+ return (em_rr_sem (BUFFER_4A_LENGTH, em_rr_event_buffer));         /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_4b
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value, data plmn (T_plmn)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_4B_LENGTH  9
+GLOBAL UBYTE em_write_buffer_4b (UBYTE event_no, UBYTE value, T_plmn plmn)
+{
+ UBYTE em_rr_event_buffer[BUFFER_4B_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_4b()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ memset(em_rr_event_buffer, 0, BUFFER_4B_LENGTH);
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;                  /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_4B_LENGTH-EVT_LEN_OFFSET;  /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value;
+ if(plmn.v_plmn)
+ {
+  memcpy(&em_rr_event_buffer[em_rr_buffer_write], plmn.mcc, SIZE_MCC);
+  em_rr_buffer_write += SIZE_MCC;
+  memcpy(&em_rr_event_buffer[em_rr_buffer_write], plmn.mnc, SIZE_MNC);
+ }
+
+ return (em_rr_sem (BUFFER_4B_LENGTH, em_rr_event_buffer));        /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_4c
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value1, data plmn (T_plmn)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_4C_LENGTH ((MAX_PLMN*(SIZE_MCC+SIZE_MNC))+EVT_LEN_OFFSET)
+GLOBAL UBYTE em_write_buffer_4c (UBYTE event_no, UBYTE value1, T_plmn plmn[MAX_PLMN])
+{
+ UBYTE em_rr_event_buffer[BUFFER_4C_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+ UBYTE length = 0;
+ UBYTE i;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_4c()");
+ /* Ensure value1 is within specified boundaries */
+ if( value1 > MAX_PLMN )
+ {
+   value1 = MAX_PLMN;
+ }
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ memset(em_rr_event_buffer, 0, BUFFER_4C_LENGTH);
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;                     /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = 1+value1*(SIZE_MCC + SIZE_MNC); /* Value length - 0 equals no value */
+ for (i=0; i<value1; i++) {
+   if(plmn[i].v_plmn)
+   {
+     memcpy(em_rr_event_buffer + em_rr_buffer_write, plmn[i].mcc, SIZE_MCC);
+     em_rr_buffer_write += SIZE_MCC;
+     memcpy(em_rr_event_buffer + em_rr_buffer_write, plmn[i].mnc, SIZE_MNC);
+     em_rr_buffer_write += SIZE_MNC;
+   }
+ }
+ length = (EVT_LEN_OFFSET + value1*(SIZE_MCC + SIZE_MNC));
+
+ return (em_rr_sem (length, em_rr_event_buffer));                          /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_5
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value1, data value2, data cs (USHORT)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_5_LENGTH  5
+GLOBAL UBYTE em_write_buffer_5 (UBYTE event_no, UBYTE value1, UBYTE value2, UBYTE value3)
+{
+ UBYTE em_rr_event_buffer[BUFFER_5_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_5()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_5_LENGTH-EVT_LEN_OFFSET; /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value1;                 /* first data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value2;                 /* second data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value3;                 /* Data */
+
+ return (em_rr_sem (BUFFER_5_LENGTH, em_rr_event_buffer));       /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_5c
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value, data plmn (T_plmn)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_5C_LENGTH  10
+GLOBAL UBYTE em_write_buffer_5c (UBYTE event_no, UBYTE value1, UBYTE value2, T_plmn plmn)
+{
+ UBYTE em_rr_event_buffer[BUFFER_5C_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_5c()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ memset(em_rr_event_buffer, 0, BUFFER_5C_LENGTH);
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;                 /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_5C_LENGTH-EVT_LEN_OFFSET;  /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value1;
+ em_rr_event_buffer[em_rr_buffer_write++] = value2;
+ if(plmn.v_plmn)
+ {
+  memcpy(em_rr_event_buffer + em_rr_buffer_write, plmn.mcc, SIZE_MCC);
+  em_rr_buffer_write += SIZE_MCC;
+  memcpy(em_rr_event_buffer + em_rr_buffer_write, plmn.mnc, SIZE_MNC);
+ }
+
+ return (em_rr_sem (BUFFER_5C_LENGTH, em_rr_event_buffer));        /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_8
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value1, data value2, data cs (USHORT)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_8_LENGTH  8
+GLOBAL UBYTE em_write_buffer_8 (UBYTE event_no, UBYTE value1, UBYTE value2, UBYTE value3, UBYTE value4,
+                            UBYTE value5, UBYTE value6)
+{
+ UBYTE em_rr_event_buffer[BUFFER_8_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_8()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_8_LENGTH-EVT_LEN_OFFSET; /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value1;                 /* first data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value2;                 /* second data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value3;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value4;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value5;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value6;                 /* data */
+
+ return (em_rr_sem (BUFFER_8_LENGTH, em_rr_event_buffer));       /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_write_buffer_9
++------------------------------------------------------------------------------
+|  Description  :  Perform buffer check and store corresponding data in it.
+|
+|  Parameters   :  Event number, data value1, data value2, data cs (USHORT)
+|
+|  Return       :  TRUE/FALSE
+|
++------------------------------------------------------------------------------
+*/
+#define BUFFER_9_LENGTH  9
+GLOBAL UBYTE em_write_buffer_9 (UBYTE event_no, UBYTE value1, UBYTE value2, UBYTE value3,
+                           UBYTE value4,   UBYTE value5, UBYTE value6, UBYTE value7)
+{
+ UBYTE em_rr_event_buffer[BUFFER_9_LENGTH];
+ UBYTE em_rr_buffer_write = 0;
+
+ TRACE_FUNCTION ("rr_em_write_buffer_9()");
+
+ /*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+ rr_em_first_event_check();
+
+ em_rr_event_buffer[em_rr_buffer_write++] = event_no;               /* Event number */
+ em_rr_event_buffer[em_rr_buffer_write++] = BUFFER_9_LENGTH-EVT_LEN_OFFSET; /* Value length - 0 equals no value */
+ em_rr_event_buffer[em_rr_buffer_write++] = value1;                 /* first data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value2;                 /* second data info */
+ em_rr_event_buffer[em_rr_buffer_write++] = value3;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value4;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value5;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value6;                 /* data */
+ em_rr_event_buffer[em_rr_buffer_write++] = value7;                 /* data */
+
+ return (em_rr_sem (BUFFER_9_LENGTH, em_rr_event_buffer));       /* Data is stored inside buffer, reset flag */
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : rr_semaphore_err
++------------------------------------------------------------------------------
+|  Description  :  Semaphor error
+|
+|
+|  Parameters   :  void
+|
+|  Return       :  void
+|
++------------------------------------------------------------------------------
+*/
+static void rr_semaphore_err (void)
+{
+ static UCHAR out = 0;
+  if (!out)
+  {
+    out = 1;
+/* Implements Measure#32: Row 224 */
+    TRACE_EVENT ("semaphore error");
+
+  }
+}
+
+
+/*
++------------------------------------------------------------------------------
+|  Function     : rr_enter_critical_section
++------------------------------------------------------------------------------
+|  Description  :
+|                 Attempt to access critical section by taking control
+|                 of the semaphore
+|
+|  Parameters   : void
+|
+|  Return       : int
+|
++------------------------------------------------------------------------------
+*/
+static int rr_enter_critical_section (T_HANDLE sem)
+{
+  if (vsi_s_get (VSI_CALLER sem) NEQ VSI_OK)
+  {
+    SYST_TRACE ( "** Enter Critical Sec:semaphore NOT cleared **");
+    rr_semaphore_err();
+    return -1;
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : rr_leave_critical_section
++------------------------------------------------------------------------------
+|  Description  :
+|                 Relinquish control of semaphore and release access to
+|                 critical section
+|
+|  Parameters   : void
+|
+|  Return       : int
+|
++------------------------------------------------------------------------------
+*/
+static int rr_leave_critical_section (T_HANDLE sem)
+{
+  if (vsi_s_release (VSI_CALLER sem) NEQ VSI_OK)
+  {
+    SYST_TRACE ( "** Leave Critical Sec:semaphore NOT cleared **");
+    rr_semaphore_err();
+    return -1;
+  }
+  else
+  {
+    return 0;
+  }
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem_init
++------------------------------------------------------------------------------
+|  Description  :
+|                 Initialise Semaphore
+|
+|  Parameters   : void
+|
+|  Return       : int
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void em_rr_sem_init (void)
+{
+  sem_EM_RR  = vsi_s_open (VSI_CALLER "EM_RR_SEM",1);
+
+  if (sem_EM_RR NEQ VSI_ERROR)
+    em_rr_sem_clear ();
+  else
+    SYST_TRACE ("RR:can´t open semaphore \"EM_RR_SEM\"");
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem_exit
++------------------------------------------------------------------------------
+|  Description  :
+|                 Close the semaphore
+|
+|  Parameters   : void
+|
+|  Return       : void
+|
++------------------------------------------------------------------------------
+*/
+GLOBAL void em_rr_sem_exit (void)
+{
+  if (sem_EM_RR NEQ VSI_ERROR)
+    vsi_s_close (VSI_CALLER sem_EM_RR);
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem_clear
++------------------------------------------------------------------------------
+|  Description  :
+|                 Clear semaphore
+|
+|  Parameters   : void
+|
+|  Return       : void
+|
++------------------------------------------------------------------------------
+*/
+LOCAL void em_rr_sem_clear (void)
+{
+  if (rr_enter_critical_section(sem_EM_RR))
+  {
+    return;
+  }
+
+  em_rr_sem_index = 0;
+  if(rr_leave_critical_section(sem_EM_RR))
+  {
+    return;
+  }
+  SYST_TRACE ( "RR:em_rr_sem_index cleared");
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem_reset
++------------------------------------------------------------------------------
+|  Description  :
+|                 Reset the semaphore
+|
+|  Parameters   : void
+|
+|  Return       : UBYTE
+|
++------------------------------------------------------------------------------
+*/
+/*lint -esym(714,em_rr_sem_reset) | Symbol not referenced         | used by ACI */
+/*lint -esym(765,em_rr_sem_reset) | external could be made static | used by ACI */
+
+GLOBAL void em_rr_sem_reset (void)
+{
+  em_rr_sem_index = 0;
+  if(rr_leave_critical_section(sem_EM_RR))
+  {
+    return;
+  }
+
+  SYST_TRACE ( "RR:em_rr_sem_index reset OK");
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem_read
++------------------------------------------------------------------------------
+|  Description  :
+|                 Read state of the semaphore. The rr semaphor will be read by
+|                 the engineering mode via aci.
+|
+|  Parameters   : void
+|
+|  Return       : UBYTE
+|
++------------------------------------------------------------------------------
+*/
+/*lint -esym(714,em_rr_sem_read) | Symbol not referenced         | used by ACI */
+/*lint -esym(765,em_rr_sem_read) | external could be made static | used by ACI */
+
+GLOBAL void em_rr_sem_read (void)
+{
+  TRACE_FUNCTION ("em_rr_sem_read()");
+
+  {
+    USHORT    semCount;
+
+    if (vsi_s_status (VSI_CALLER sem_EM_RR, &semCount) NEQ VSI_OK)
+    {
+      SYST_TRACE ( "** RR:sem status error **");
+      rr_semaphore_err();
+      return;
+    }
+    if (semCount EQ 0)
+    {
+      vsi_o_ttrace(VSI_CALLER TC_EVENT, "semCount = %d", semCount);
+      SYST_TRACE ( "semCount EQ 0");
+      return;
+    }
+  }
+
+  rr_enter_critical_section(sem_EM_RR);
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     : em_rr_sem
++------------------------------------------------------------------------------
+|  Description  :
+|
+|
+|  Parameters   : void
+|
+|  Return       : TRUE/FALSE - TRUE keeps the event flag valid,
+|                              FALSE indicates a successful flag handle
+|
++------------------------------------------------------------------------------
+*/
+/*lint -esym(714,em_rr_sem) | Symbol not referenced         | used by ACI */
+/*lint -esym(765,em_rr_sem) | external could be made static | used by ACI */
+GLOBAL UBYTE em_rr_sem (UBYTE length, UBYTE *data)
+{
+  UBYTE     i;
+
+  TRACE_FUNCTION ("em_rr_sem()");
+
+  {
+    USHORT    semCount;
+
+    if (vsi_s_status (VSI_CALLER sem_EM_RR, &semCount) NEQ VSI_OK)
+    {
+      rr_semaphore_err();
+      return FALSE;
+    }
+    if (semCount EQ 0)
+    {
+      vsi_o_ttrace(VSI_CALLER TC_EVENT, "semCount = %d", semCount);
+      SYST_TRACE ( "semCount EQ 0");
+      return FALSE;
+    }
+  }
+
+  /*
+   *  buffer overflow protection
+   */
+  if (( em_rr_sem_index + length)  > EM_RR_SEM_SIZE )
+  {
+    TRACE_FUNCTION ("rr buffer overflow");
+    return FALSE;
+  }
+
+  if(rr_enter_critical_section(sem_EM_RR))
+    return FALSE;
+
+  for (i=0; i<length; i++)
+    em_rr_sem_buffer[em_rr_sem_index++] = *(data++);
+
+  if(rr_leave_critical_section(sem_EM_RR))
+  {
+    SYST_TRACE ( "** Unable to clear semaphore **");
+    return FALSE;
+  }
+
+  return TRUE;             /* indicates that flag was handled */
+} /* endfunc em_rr_sem */
+
+
+/*
++------------------------------------------------------------------------------
+|  Function     : rr_em_first_event_check()
++------------------------------------------------------------------------------
+|  Description  :  Checks if first EM-Event ocured
+|
+|  Parameters   :  None
+|
+|  Return       :  None
+|
++------------------------------------------------------------------------------
+*/
+
+/*
+   ACI is informed about the first event trace, used for later data processing.
+ */
+
+LOCAL void rr_em_first_event_check(void)
+{
+ TRACE_FUNCTION("rr_em_first_event_check()");
+
+ if(em_rr_trace_occured EQ 0)
+ {
+  PALLOC(em_notification, EM_DATA_IND);
+  em_notification->entity = EM_RR;
+  PSENDX(MMI, em_notification);
+  em_rr_trace_occured++;
+ }
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  rr_em_pco_trace_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_PCO_TRACE_REQ.
+|
+|  Parameters   :  UBYTE pco_bitmap
+|
+|  Return       :  void
+|
+|  Purpose      :  with this primitive the requested EM Data is traced in the PCO.
++------------------------------------------------------------------------------
+*/
+GLOBAL void rr_em_pco_trace_req (T_EM_PCO_TRACE_REQ *em_pco_trace_req)
+{
+  GET_INSTANCE_DATA;
+  UBYTE em_cell_type = EM_CELL_NA;
+  TRACE_FUNCTION("rr_em_pco_trace_req()");
+
+  /*check for SC data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_SC_INFO)
+  {
+       switch (GET_STATE (STATE_ATT))
+    {
+      case ATT_IDLE:
+
+        if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+        {
+          em_cell_type = EM_CELL_GSM;
+#ifdef GPRS
+          if(rr_data->nc_data[SC_INDEX].rac NEQ NOT_PRESENT_8BIT)
+            em_cell_type = EM_CELL_GPRS;	 
+#endif
+          
+          TRACE_EVENT_EM_P8("EM_SC_INFO_REQ_IDLE_DECODED: arfcn:%d c1:%d c2:%d rxlev:%d bsic:%d cell_id:%d dsc:%d cell_type:%d",
+            
+            rr_data->nc_data[SC_INDEX].arfcn,
+            rr_data->nc_data[SC_INDEX].c1,
+            rr_data->nc_data[SC_INDEX].c2,
+            rr_data->nc_data[SC_INDEX].rxlev,
+            rr_data->nc_data[SC_INDEX].bsic,
+            rr_data->nc_data[SC_INDEX].cell_id,
+            em_act_dlt,
+            em_cell_type);
+
+          TRACE_EVENT_EM_P5("EM_SC_INFO_REQ_IDLE_DECODED: txlev:%d tn:%d lac:%d cba:%d cbq:%d",
+            rr_data->sc_data.cd.cell_options.pow_ctrl,
+            rr_data->sc_data.chan_desc.tn,
+            rr_data->nc_data[SC_INDEX].lai.lac,
+            rr_data->nc_data[SC_INDEX].rach.cell_bar_access,
+            rr_data->nc_data[SC_INDEX].c2_par.cbq);
+        }
+        else if (rr_data->nc_data[SC_INDEX].bcch_status EQ NON_DECODED)
+        {
+          TRACE_EVENT_EM_P4("EM_SC_INFO_REQ_IDLE_NON_DECODED: cell_type:%d arfcn:%d rxlev:%d bsic:%d",
+            em_cell_type,
+            rr_data->nc_data[SC_INDEX].arfcn,
+            rr_data->nc_data[SC_INDEX].rxlev,
+            rr_data->nc_data[SC_INDEX].bsic);
+        }
+        break;
+
+      case ATT_DEDICATED:
+        if (!rr_data->ms_data.measurement_report.valid)
+          break;
+
+        em_cell_type = EM_CELL_GSM;
+
+#ifdef GPRS
+          if(rr_data->nc_data[SC_INDEX].rac NEQ NOT_PRESENT_8BIT)
+            em_cell_type = EM_CELL_GPRS;
+#endif
+
+        TRACE_EVENT_EM_P1("EM_SC_INFO_REQ_DEDICATED: cell_type:%d", em_cell_type);
+
+        TRACE_EVENT_EM_P6("EM_SC_INFO_REQ_DEDICATED: arfcn:%d bsic:%d cell_id:%d txlev:%d tn:%d rxlev_f:%d",
+          rr_data->ms_data.measurement_report.arfcn,
+          rr_data->nc_data[SC_INDEX].bsic,
+          rr_data->nc_data[SC_INDEX].cell_id,
+          rr_data->sc_data.cd.cell_options.pow_ctrl,
+          rr_data->sc_data.chan_desc.tn,
+          rr_data->ms_data.measurement_report.rx_lev_full);
+
+        TRACE_EVENT_EM_P6("EM_SC_INFO_REQ_DEDICATED: rxlev_s:%d rlt:%d ta:%d rxqual_f:%d rxqual_s:%d vocoder:%d",
+          rr_data->ms_data.measurement_report.rx_lev_sub,
+          em_act_rlt,
+          rr_data->sc_data.new_ta,
+          rr_data->ms_data.measurement_report.rx_qual_full,
+          rr_data->ms_data.measurement_report.rx_qual_sub,
+          rr_data->sc_data.ch_mode);
+
+        break;
+
+      default:
+        break;
+    }/*switch - state*/
+  }/*if - SC data*/
+
+  /*check NC data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_NC_INFO)
+  {
+    UBYTE index = 0;
+    UBYTE rac   = 0xff;
+    
+    switch (GET_STATE (STATE_ATT))
+    {
+      case ATT_IDLE:
+        
+        TRACE_EVENT_EM_P1("EM_NC_INFO_REQ_IDLE: num_nc:%d", /*number of neighbour cells*/
+          rr_data->ms_data.measurement_report.ncells.no_of_ncells);
+
+        for (index = 0; index < EM_MAX_NUM_NC ; index++) /*report cells ordered by index in NC list*/
+        {
+          em_cell_type = EM_CELL_NA;
+
+          if (rr_data->nc_data[index].bcch_status EQ DECODED)
+          {
+            em_cell_type = EM_CELL_GSM;
+            rac = 0xff;
+#ifdef GPRS
+            rac = rr_data->nc_data[index].rac;
+            if(rr_data->nc_data[index].rac NEQ NOT_PRESENT_8BIT)
+              em_cell_type = EM_CELL_GPRS;
+#endif
+
+            TRACE_EVENT_EM_P8("EM_NC_INFO_REQ_IDLE_DECODED: cell_type:%d rac:%d index:%d arfcn:%d c1:%d c2:%d rxlev:%d bsic:%d",
+              em_cell_type,
+              rac,
+              index,
+              rr_data->nc_data[index].arfcn,
+              rr_data->nc_data[index].c1,
+              rr_data->nc_data[index].c2,
+              rr_data->nc_data[index].rxlev,
+              rr_data->nc_data[index].bsic);
+
+            TRACE_EVENT_EM_P6("EM_NC_INFO_REQ_IDLE_DECODED: cid:%d lac:%d f_o:%ld t_a:%ld cba:%d cbq:%d",
+              rr_data->nc_data[index].cell_id,
+              rr_data->nc_data[index].lai.lac,
+              rr_data->ms_data.measurement_report.ncells.frame_offset[index],
+              rr_data->ms_data.measurement_report.ncells.time_alignmt[index],
+              rr_data->nc_data[index].rach.cell_bar_access,
+              rr_data->nc_data[index].c2_par.cbq);
+
+            TRACE_EVENT_EM_P3("EM_NC_INFO_REQ_IDLE_DECODED: cell_resel_off:%d temp_off:%d rxlev_acc_min:%ld",
+              rr_data->nc_data[index].c2_par.cell_reselect_offset,
+              rr_data->nc_data[index].c2_par.temp_offset,
+              rr_data->nc_data[index].select_para.rxlev_access_min);
+
+          } /* if decoded */
+
+          else if (rr_data->nc_data[index].bcch_status EQ NON_DECODED)
+          {
+            TRACE_EVENT_EM_P4("EM_NC_INFO_REQ_IDLE_NON_DECODED: cell_type:%d arfcn:%d rxlev:%d bsic:%d",
+              em_cell_type,
+              rr_data->nc_data[index].arfcn,
+              rr_data->nc_data[index].rxlev,
+              rr_data->nc_data[index].bsic);
+          } /* if non decoded */
+        } /* for */
+
+        break;
+
+      case ATT_DEDICATED:
+        {
+        if (!rr_data->ms_data.measurement_report.valid)
+          break;
+
+        TRACE_EVENT_EM_P1("EM_NC_INFO_REQ_DEDICATED: num_nc:%d",
+          rr_data->ms_data.measurement_report.ncells.no_of_ncells);
+
+        for (index = 0; index< rr_data->ms_data.measurement_report.ncells.no_of_ncells; index++)
+        {
+        /*in the measurement report the cells are ordered by fieldstrength -
+          non valid measurements are at the end*/
+          TRACE_EVENT_EM_P6("EM_NC_INFO_REQ_DEDICATED: index:%d arfcn:%d rx_lev:%d bsic:%d f_o:%ld t_a:%ld",
+            index,
+            rr_data->ms_data.measurement_report.ncells.arfcn[index],
+            rr_data->ms_data.measurement_report.ncells.rx_lev[index],
+            rr_data->ms_data.measurement_report.ncells.bsic[index],
+            rr_data->ms_data.measurement_report.ncells.frame_offset[index],
+            rr_data->ms_data.measurement_report.ncells.time_alignmt[index]);
+        }/*for*/
+
+        }/*case*/
+        break;
+
+      default:
+        break;
+    }/*switch - state*/
+  }/*if - NC data*/
+
+  /*check Location and Paging data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_LOC_PAG_INFO)
+  {
+    if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+    {
+      TRACE_EVENT_EM_P8("EM_LOC_PAG_INFO_REQ_DECODED: mcc:%d %d %d mnc:%d %d %d bs_pa_mfrms:%d t3212:%d",
+        rr_data->nc_data[SC_INDEX].lai.mcc[0],
+        rr_data->nc_data[SC_INDEX].lai.mcc[1],
+        rr_data->nc_data[SC_INDEX].lai.mcc[2],
+
+        /*2 digits vs. 3 digits*/
+        rr_data->nc_data[SC_INDEX].lai.mnc[2] NEQ 0xF ? rr_data->nc_data[SC_INDEX].lai.mnc[0] :
+                                                        0 ,
+        rr_data->nc_data[SC_INDEX].lai.mnc[2] NEQ 0xF ? rr_data->nc_data[SC_INDEX].lai.mnc[1] :
+                                                        rr_data->nc_data[SC_INDEX].lai.mnc[0],
+        rr_data->nc_data[SC_INDEX].lai.mnc[2] NEQ 0xF ? rr_data->nc_data[SC_INDEX].lai.mnc[2] :
+                                                        rr_data->nc_data[SC_INDEX].lai.mnc[1],
+
+        rr_data->nc_data[SC_INDEX].control_descr.bs_pa_mfrms,
+        rr_data->nc_data[SC_INDEX].control_descr.t3212);
+    }
+    if (rr_data->ms_data.tmsi_available EQ TRUE)
+      TRACE_EVENT_EM_P1("EM_LOC_PAG_INFO_REQ_TMSI: %d", rr_data->ms_data.tmsi_binary);
+  }/*if - Location and Paging data*/
+  
+  /*check PLMN parameters*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_PLMN_INFO)
+  {
+    TRACE_EVENT_EM_P4("EM_PLMN_INFO_REQ: no_creq_max:%d re_flag:%d TXPOW_max:%d RXLEV_acc_min:%d",
+      rr_data->nc_data[SC_INDEX].rach.max_retrans,
+      rr_data->nc_data[SC_INDEX].rach.re,
+      rr_data->nc_data[SC_INDEX].select_para.ms_txpwr_max_cch,
+      rr_data->nc_data[SC_INDEX].select_para.rxlev_access_min);
+
+  }/* if - PLMN parameters*/
+  
+  /*check Ciphering Hopping DTX data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_CIPH_HOP_DTX_INFO)
+  {
+    UBYTE i,offset;
+/* Implements Measure#32: Row 242 */
+    char *basestr="EM_CIP_HOP_DTX_INFO_REQ_FREQ";
+    
+    /*to store the trace output*/
+    char hop_freq_list[MAX_SPRINTF_STRING_LEN]; /*lint !e813 , info about length*/
+    
+    if((GET_STATE(STATE_ATT) EQ ATT_DEDICATED) AND 
+	                            (GET_STATE(STATE_DAT) EQ DAT_DEDICATED))
+    {
+
+      TRACE_EVENT_EM_P6("EM_CIP_HOP_DTX_INFO_REQ_DEDICATED: ciph:%d dtx:%d v_start:%d hop:%d hsn:%d arfcn:%d",
+      rr_data->sc_data.ciph_on,
+      rr_data->sc_data.cd.dtx,
+      v_start,
+      rr_data->sc_data.chan_desc.hop,
+      rr_data->sc_data.chan_desc.hop NEQ H_NO ? rr_data->sc_data.chan_desc.hsn : NOT_PRESENT_16BIT,
+      rr_data->sc_data.chan_desc.arfcn);
+
+      if(rr_data->sc_data.chan_desc.hop NEQ H_NO)
+      {
+/* Implements Measure#32: Row 242 */
+        offset = sprintf(hop_freq_list, "%s1:  ", basestr);
+
+
+    for (i = 0; (i < MAX_MA_CHANNELS) AND (ma[i] NEQ NOT_PRESENT_16BIT); i++)
+    {
+      offset += sprintf(hop_freq_list+offset, "%u ", ma[i]);
+      /*
+       * 4 spaces for freq + 1 blank space + 1 space for '\0'
+       */
+      if(offset > MAX_SPRINTF_STRING_LEN - 6)
+      {    
+        TRACE_EVENT_EM (hop_freq_list);
+/* Implements Measure#32: Row 245 */
+        offset = sprintf(hop_freq_list, "%s1_CONT:  ", basestr);
+      }
+    }
+    TRACE_EVENT_EM (hop_freq_list);
+        TRACE_EVENT_EM_P2("EM_CIP_HOP_DTX_INFO_REQ_FREQ1: nr_arfcns:%d, maio:%d",
+          i,rr_data->sc_data.chan_desc.maio);
+     } /* If hopping valid */
+
+    if (v_start)
+    {
+  
+/* Implements Measure#32: Row 247 */
+      offset = sprintf(hop_freq_list, "%s2:  ", basestr);/*before starting time*/
+
+      for (i = 0; (i < MAX_MA_CHANNELS) AND (ma2[i] NEQ NOT_PRESENT_16BIT); i++)
+      {
+        offset += sprintf(hop_freq_list+offset, "%u ", ma2[i]);
+        if(offset > MAX_SPRINTF_STRING_LEN - 6)
+        {    
+          TRACE_EVENT_EM (hop_freq_list);
+/* Implements Measure#32: Row 248 */
+          offset = sprintf(hop_freq_list, "%s2_CONT:  ", basestr);
+        }
+      }
+      TRACE_EVENT_EM (hop_freq_list);
+        TRACE_EVENT_EM_P2("EM_CIP_HOP_DTX_INFO_REQ_FREQ2: nr_arfcns:%d, maio:%d",i, maio2);
+  
+    }/*if - starting time valid*/
+    } /* ATT dedicated state */
+    else
+    {
+      TRACE_EVENT_EM_P1("EM_CIP_HOP_DTX_INFO_REQ_IDLE: dtx:%d", rr_data->sc_data.cd.dtx);
+    } /* ATT idle state */
+  }/*if - ciphering, hopping, dtx*/
+  
+  /*check Power (Classmark) data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_POWER_INFO)
+  {/*here the em_power_info_cnf struckture is used, because I couldn't find classmark definition*/
+    PALLOC(em_power_info_cnf, EM_POWER_INFO_CNF);
+    memset (em_power_info_cnf, 0, sizeof (T_EM_POWER_INFO_CNF));
+    memcpy(&em_power_info_cnf->classm2, &rr_data->ms_data.classmark2, sizeof (T_classm2));
+    memcpy(&em_power_info_cnf->classm3, &rr_data->ms_data.classmark3, sizeof (T_classm3));
+
+    TRACE_EVENT_EM_P6("EM_POWER_INFO_REQ_CLASSMARK_2: rev_lev:%d es_ind:%d a5_1:%d rf_pow_cap:%d ps_cap:%d ss_screen:%d",
+      em_power_info_cnf->classm2.rev_lev,  em_power_info_cnf->classm2.es_ind,
+      em_power_info_cnf->classm2.a5_1,     em_power_info_cnf->classm2.rf_pow_cap,
+      em_power_info_cnf->classm2.ps_cap,   em_power_info_cnf->classm2.ss_screen);
+    TRACE_EVENT_EM_P6("EM_POWER_INFO_REQ_CLASSMARK_2: sm_cap:%d freq_cap:%d class_3:%d cmsp:%d a5_3:%d a5_2:%d",
+      em_power_info_cnf->classm2.sm_cap,   em_power_info_cnf->classm2.freq_cap,
+      em_power_info_cnf->classm2.class_3,  em_power_info_cnf->classm2.cmsp,
+      em_power_info_cnf->classm2.a5_3,     em_power_info_cnf->classm2.a5_2);
+
+    TRACE_EVENT_EM_P6("EM_POWER_INFO_REQ_CLASSMARK_3: mb_sub:%d a5_7:%d a5_6:%d a5_5:%d a5_4:%d v_radio_cap_2:%d",
+      em_power_info_cnf->classm3.mb_sub,           em_power_info_cnf->classm3.a5_7,
+      em_power_info_cnf->classm3.a5_6,             em_power_info_cnf->classm3.a5_5,
+      em_power_info_cnf->classm3.a5_4,             em_power_info_cnf->classm3.v_radio_cap_2);
+    TRACE_EVENT_EM_P6("EM_POWER_INFO_REQ_CLASSMARK_3: ra_cap_2:%d v_ra_cap_1:%d ra_cap_1:%d v_r_sup:%d r_sup:%d v_m_s_class:%d",
+      em_power_info_cnf->classm3.radio_cap_2,      em_power_info_cnf->classm3.v_radio_cap_1,
+      em_power_info_cnf->classm3.radio_cap_1,      em_power_info_cnf->classm3.v_r_support,
+      em_power_info_cnf->classm3.r_support,        em_power_info_cnf->classm3.v_m_s_class);
+    TRACE_EVENT_EM_P6("EM_POWER_INFO_REQ_CLASSMARK_3: m_s_class:%d ucs2_treat:%d ext_meas_cap:%d v_meas_cap:%d sw_time:%d sws_time:%d",
+      em_power_info_cnf->classm3.m_s_class,        em_power_info_cnf->classm3.ucs2_treat,
+      em_power_info_cnf->classm3.ext_meas_cap,     em_power_info_cnf->classm3.v_meas_cap,
+      em_power_info_cnf->classm3.meas_cap.sw_time, em_power_info_cnf->classm3.meas_cap.sws_time);
+
+    PFREE(em_power_info_cnf);
+
+  }/* if - Power (Classmark) data*/
+  
+  /*check Identity data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_IDENTITY_INFO)
+  {   
+    TRACE_EVENT_EM_P4("EM_IDENTITY_INFO_REQ_IMEI: id_type:%d v_id:%d c_id:%d odd_even:%d",
+      rr_data->ms_data.imei.ident_type,
+      rr_data->ms_data.imei.v_ident_dig,
+      rr_data->ms_data.imei.c_ident_dig,
+      rr_data->ms_data.imei.odd_even);
+
+    TRACE_EVENT_EM_P8("EM_IDENTITY_INFO_REQ: imei_1: %d %d %d %d %d %d %d %d",
+      rr_data->ms_data.imei.ident_dig[0], rr_data->ms_data.imei.ident_dig[1],
+      rr_data->ms_data.imei.ident_dig[2], rr_data->ms_data.imei.ident_dig[3],
+      rr_data->ms_data.imei.ident_dig[4], rr_data->ms_data.imei.ident_dig[5],
+      rr_data->ms_data.imei.ident_dig[6], rr_data->ms_data.imei.ident_dig[7]);
+    TRACE_EVENT_EM_P8("EM_IDENTITY_INFO_REQ: imei_2: %d %d %d %d %d %d %d %d",
+      rr_data->ms_data.imei.ident_dig[8],  rr_data->ms_data.imei.ident_dig[9],
+      rr_data->ms_data.imei.ident_dig[10], rr_data->ms_data.imei.ident_dig[11],
+      rr_data->ms_data.imei.ident_dig[12], rr_data->ms_data.imei.ident_dig[13],
+      rr_data->ms_data.imei.ident_dig[14], rr_data->ms_data.imei.ident_dig[15]);
+
+    if (rr_data->ms_data.imsi_available) /* SIM available */
+    {
+      TRACE_EVENT_EM_P4("EM_IDENTITY_INFO_REQ_IMSI: id_type:%d v_id:%d c_id:%d odd_even:%d",
+        rr_data->ms_data.imsi.ident_type,
+        rr_data->ms_data.imsi.v_ident_dig,
+        rr_data->ms_data.imsi.c_ident_dig,
+        rr_data->ms_data.imsi.odd_even);
+      TRACE_EVENT_EM_P8("EM_IDENTITY_INFO_REQ: imsi_1: %d %d %d %d %d %d %d %d",
+        rr_data->ms_data.imsi.ident_dig[0], rr_data->ms_data.imsi.ident_dig[1],
+        rr_data->ms_data.imsi.ident_dig[2], rr_data->ms_data.imsi.ident_dig[3],
+        rr_data->ms_data.imsi.ident_dig[4], rr_data->ms_data.imsi.ident_dig[5],
+        rr_data->ms_data.imsi.ident_dig[6], rr_data->ms_data.imsi.ident_dig[7]);
+      TRACE_EVENT_EM_P8("EM_IDENTITY_INFO_REQ: imsi_2: %d %d %d %d %d %d %d %d",
+        rr_data->ms_data.imsi.ident_dig[8],  rr_data->ms_data.imsi.ident_dig[9],
+        rr_data->ms_data.imsi.ident_dig[10], rr_data->ms_data.imsi.ident_dig[11],
+        rr_data->ms_data.imsi.ident_dig[12], rr_data->ms_data.imsi.ident_dig[13],
+        rr_data->ms_data.imsi.ident_dig[14], rr_data->ms_data.imsi.ident_dig[15]);
+      }/*if - SIM available*/
+
+    if (rr_data->ms_data.tmsi_available EQ TRUE)
+      TRACE_EVENT_EM_P1("EM_IDENTITY_INFO_REQ: tmsi_bin: %ld", rr_data->ms_data.tmsi_binary);
+  }/*if - Identity data*/
+  
+   /*check AMR configuration data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_AMR_INFO)
+  {
+    if((GET_STATE(STATE_ATT) EQ ATT_DEDICATED) AND 
+	                                (GET_STATE(STATE_DAT) EQ DAT_DEDICATED))
+    {
+      if(rr_data->sc_data.ch_mode EQ CM_AMR)
+      {
+        UBYTE amr_index,amr_nr_modes = 1;
+
+        TRACE_EVENT_EM_P5("EM_AMR_INFO_REQ_DEDICATED: vocoder:%d icmi:%d icm:%d acs:%d first_codec:%d",
+        rr_data->sc_data.chan_desc.chan_type,
+        rr_data->sc_data.amr_conf.icmi,
+        rr_data->sc_data.amr_conf.st_mode,
+        rr_data->sc_data.amr_conf.set_amr,
+        em_get_first_codec(rr_data->sc_data.amr_conf.set_amr));
+
+        if(rr_data->sc_data.amr_conf.v_cod_prop) 
+        {
+          /* Number of codec modes */
+          amr_nr_modes = rr_data->sc_data.amr_conf.c_cod_prop + 1;
+
+          TRACE_EVENT_EM_P1("EM_AMR_INFO_REQ_DEDICATED: amr_num_modes:%d",
+          amr_nr_modes);
+
+          /* Threshold and Hysteresis properties between codec modes */
+          for(amr_index=0;amr_index<amr_nr_modes;amr_index++)
+          {
+            TRACE_EVENT_EM_P2("EM_AMR_COD_PROP: thr:%d hyst:%d",
+            rr_data->sc_data.amr_conf.cod_prop[amr_index].codec_thr,
+            rr_data->sc_data.amr_conf.cod_prop[amr_index].codec_hyst);
+          }
+        } /* codec properties */
+      } /* AMR configured */
+      else
+      {
+        TRACE_EVENT_EM("EM_AMR_INFO_REQ_DEDICATED: AMR not configured");
+      } /* AMR not configured in dedicated state */
+    } /* ATT dedicated state */
+    else
+    {
+      TRACE_EVENT_EM("EM_AMR_INFO_REQ_IDLE: Not Applicable");
+    } /* ATT idle state */
+  } /* EM_PCO_AMR_INFO */
+  
+#if !defined (WIN32)
+  /*check SW Version data*/
+  if(em_pco_trace_req->pco_bitmap & EM_PCO_SW_VERSION_INFO)
+  {
+    TRACE_EVENT_EM_P1("EM_SW_SIM: %s",sim_version());
+    TRACE_EVENT_EM_P1("EM_SW_SMS: %s",sms_version());
+    TRACE_EVENT_EM_P1("EM_SW_SS:  %s",ss_version()) ;
+    TRACE_EVENT_EM_P1("EM_SW_CC:  %s",cc_version()) ;
+    TRACE_EVENT_EM_P1("EM_SW_MM:  %s",mm_version()) ;
+    TRACE_EVENT_EM_P1("EM_SW_RR:  %s",rr_version()) ;
+    TRACE_EVENT_EM_P1("EM_SW_DL:  %s",dl_version()) ;
+    TRACE_EVENT_EM_P1("EM_SW_L1:  %s",l1_version()) ;
+  }/*if - SW Version data*/
+#endif
+ 
+  PFREE(em_pco_trace_req);
+}/*rr_em_pco_trace_req*/
+
+
+/* ------------------ Microtec Cooperation Functions ----------*/
+#ifdef GPRS /* changes for later:  Include extra compile switch for fmm */
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_fmm_sc_info_req
++------------------------------------------------------------------------------
+|  Description  :  This function provides the data for microtec fmm - Program
+|
+|  Parameters   :  Primitive from EM - T_EM_FMM_SC_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+This function sends the latest stored data of the SC. It is only interesting
+during a GPRS connection (PTM). Therefor the ATT_STATE is ATT_IDLE (or RE_SELECTION).
+
+*/
+
+GLOBAL void dat_em_fmm_sc_info_req (T_EM_FMM_SC_INFO_REQ *em_fmm_sc_info_req)
+{ 
+  /*GET_INSTANCE_DATA;*/
+ PFREE(em_fmm_sc_info_req);
+
+ TRACE_FUNCTION ("dat_fmm_em_sc_info_req()");
+
+#ifdef FF_WAP
+ {
+  PALLOC(em_fmm_sc_info_cnf, EM_FMM_SC_INFO_CNF);
+
+  memset (em_fmm_sc_info_cnf, 0, sizeof (T_EM_FMM_SC_INFO_CNF));
+
+  switch (GET_STATE (STATE_ATT))
+  {
+   case ATT_IDLE:
+     if (rr_data->nc_data[SC_INDEX].bcch_status EQ DECODED)
+     {
+      em_fmm_sc_info_cnf->arfcn			      = rr_data->nc_data[SC_INDEX].arfcn;
+      em_fmm_sc_info_cnf->c1		  	      = rr_data->nc_data[SC_INDEX].c1;
+      em_fmm_sc_info_cnf->c2			        = rr_data->nc_data[SC_INDEX].c2;
+      em_fmm_sc_info_cnf->rac			        = rr_data->nc_data[SC_INDEX].rac;
+      em_fmm_sc_info_cnf->hyst			      = rr_data->nc_data[SC_INDEX].select_para.cell_resel_hyst;
+      em_fmm_sc_info_cnf->c32			        = rr_data->nc_data[SC_INDEX].c32;	/*c32_used abfragen ?*/
+      em_fmm_sc_info_cnf->gprs_prio_class = rr_data->nc_data[SC_INDEX].cr_par.priority_class;
+     }
+     else if (rr_data->nc_data[SC_INDEX].bcch_status EQ NON_DECODED)
+     {
+      em_fmm_sc_info_cnf->arfcn   = rr_data->nc_data[SC_INDEX].arfcn;
+     }
+     break;
+   case ATT_CS3:
+     break; /* Cell reselection - if needed can be included later*/
+   default:
+     break;
+  } /*switch*/
+ 
+/* TRACE_EVENT_P7("arfcn:%d c1:%d c2:%d rac:%d hyst:%d c32:%d prio:%d" , em_fmm_sc_info_cnf->arfcn,\
+      em_fmm_sc_info_cnf->c1 , em_fmm_sc_info_cnf->c2	,  em_fmm_sc_info_cnf->rac , em_fmm_sc_info_cnf->hyst,\
+      em_fmm_sc_info_cnf->c32, em_fmm_sc_info_cnf->gprs_prio_class);*/
+
+  PSENDX( WAP, em_fmm_sc_info_cnf);
+ }
+
+#endif /*FF_WAP*/
+
+}
+
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_fmm_nc_info_req
++------------------------------------------------------------------------------
+|  Description  :  Process the primitive EM_FMM_NC_INFO_REQ.
+|
+|  Parameters   :  Primitive from EM - T_EM_FMM_NC_INFO_REQ
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+This function sends the latest stored data of the NC. It is only interesting
+during a GPRS connection (PTM). Therefor the ATT_STATE is ATT_IDLE or RE_SELECTION.
+So the measurement report results should also be available in the nc_data.
+*/
+GLOBAL void dat_em_fmm_nc_info_req (T_EM_FMM_NC_INFO_REQ *em_fmm_nc_info_req)
+{
+  /*GET_INSTANCE_DATA;*/
+ PFREE(em_fmm_nc_info_req);
+
+ TRACE_FUNCTION ("dat_em_fmm_nc_info_req()");
+
+#ifdef FF_WAP
+ {
+  UBYTE index = 0, index2 = 0;
+  PALLOC(em_fmm_nc_info_cnf, EM_FMM_NC_INFO_CNF);
+
+  memset (em_fmm_nc_info_cnf, 0, sizeof (T_EM_FMM_NC_INFO_CNF));
+
+  switch (GET_STATE (STATE_ATT))
+  {
+		case ATT_IDLE:
+		  em_fmm_nc_info_cnf->no_ncells = rr_data->ms_data.measurement_report.ncells.no_of_ncells;
+			for (index = index2 = 0; index< EM_MAX_NUM_NC; index++)
+			{
+				if (rr_data->nc_data[index].bcch_status EQ DECODED)
+				{
+          em_fmm_nc_info_cnf->arfcn_nc[index2]			= rr_data->nc_data[index].arfcn;
+          em_fmm_nc_info_cnf->c2_nc[index2]			= rr_data->nc_data[index].c2;
+          em_fmm_nc_info_cnf->rac_nc[index2]			= rr_data->nc_data[index].rac;
+          em_fmm_nc_info_cnf->c31_nc[index2]			= rr_data->nc_data[index].c31;
+          em_fmm_nc_info_cnf->c32_nc[index2]			= rr_data->nc_data[index].c32;
+          em_fmm_nc_info_cnf->gprs_prio_class_nc[index2]	= rr_data->nc_data[index].cr_par.priority_class;
+          index2++;
+       	} /* if decoded */
+
+				else if (rr_data->nc_data[index].bcch_status EQ NON_DECODED)
+				{
+          em_fmm_nc_info_cnf->arfcn_nc[index]   = rr_data->nc_data[index].arfcn;
+				} /* if non decoded */
+			} /* for */
+
+			break;
+		default:
+			break;
+	}/*switch*/
+
+/* for (index = 0 ; index < EM_MAX_NUM_NC ; index++)
+   TRACE_EVENT_P6("arfcn:%d c2:%d rac:%d c31:%d c32:%d prio:%d", em_fmm_nc_info_cnf->arfcn_nc[index],\
+                    em_fmm_nc_info_cnf->c2_nc[index], em_fmm_nc_info_cnf->rac_nc[index],\
+                    em_fmm_nc_info_cnf->c31_nc[index], em_fmm_nc_info_cnf->c32_nc[index],\
+                    em_fmm_nc_info_cnf->gprs_prio_class_nc[index]);*/
+
+  PSENDX( WAP, em_fmm_nc_info_cnf);
+ }
+
+#endif /*FF_WAP*/
+
+
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_fmm_reselection_start_ind
++------------------------------------------------------------------------------
+|  Description  :  Indicates the start of an cell reselection to FMM
+|
+|  Parameters   :  void
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_fmm_reselection_start_ind (void)
+{
+  /*GET_INSTANCE_DATA;*/
+  TRACE_FUNCTION("dat_em_fmm_reselection_start_ind()");
+#ifdef FF_WAP
+  {
+    PALLOC(em_fmm_reselection_start_ind, EM_FMM_RESELECTION_START_IND);
+    memset (em_fmm_reselection_start_ind, 0, sizeof (T_EM_FMM_RESELECTION_START_IND));
+    em_fmm_reselection_start_ind->arfcn = rr_data->nc_data[rr_data->reselect_index].arfcn;
+    em_fmm_reselection_start_ind->rac = rr_data->nc_data[rr_data->reselect_index].rac;
+    em_fmm_reselection_start_ind->res_type = rr_data->sc_data.selection_type;
+
+/*    TRACE_EVENT_P3("em_fmm_reselection_start_ind %d,%d,%d",em_fmm_reselection_start_ind->arfcn,
+              em_fmm_reselection_start_ind->rac,em_fmm_reselection_start_ind->res_type );*/
+
+    PSENDX(WAP, em_fmm_reselection_start_ind);
+  }
+
+#endif /*FF_WAP */
+
+}
+
+/*
++------------------------------------------------------------------------------
+|  Function     :  dat_em_fmm_reselection_end_ind
++------------------------------------------------------------------------------
+|  Description  :  Indicates the end of an cell reselection to FMM
+|
+|  Parameters   :  void
+|
+|  Return       :  void
++------------------------------------------------------------------------------
+*/
+GLOBAL void dat_em_fmm_reselection_end_ind (void)
+{
+  /*GET_INSTANCE_DATA;*/
+  TRACE_FUNCTION("dat_em_fmm_reselection_end_ind()");
+#ifdef FF_WAP
+  {
+    PALLOC(em_fmm_resel_end_ind, EM_FMM_RESELECTION_END_IND);
+    memset (em_fmm_resel_end_ind, 0, sizeof (T_EM_FMM_RESELECTION_END_IND));
+    em_fmm_resel_end_ind->arfcn = rr_data->nc_data[SC_INDEX].arfcn;
+    em_fmm_resel_end_ind->rac = rr_data->nc_data[SC_INDEX].rac;
+/*    TRACE_EVENT_P2("em_fmm_reselection_end_ind %d,%d",em_fmm_resel_end_ind->arfcn,
+              em_fmm_resel_end_ind->rac);*/
+
+    PSENDX(WAP, em_fmm_resel_end_ind);
+  }
+
+#endif /*FF_WAP*/
+ 
+}
+
+
+#endif /* GPRS */
+
+#endif /* FF_EM_MODE */
+
+
+
+#endif /* RR_EM_C */