view g23m-gsm/rr/rr_em.c @ 8:b36540edb046

L1/cfile/l1_*.c: initial import from tcs211-l1-reconst
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 05:45:03 +0000
parents 75a11d740a02
children
line wrap: on
line source

/*	
+-----------------------------------------------------------------------------
|  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

#include "config.h"
#include "fixedconf.h"
#include "condat-features.h"

#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 */