view src/g23m-gsm/alr2/alr_gprs.c @ 303:f76436d19a7a default tip

!GPRS config: fix long-standing AT+COPS chance hanging bug There has been a long-standing bug in FreeCalypso going back years: sometimes in the AT command bring-up sequence of an ACI-only MS, the AT+COPS command would produce only a power scan followed by cessation of protocol stack activity (only L1 ADC traces), instead of the expected network search sequence. This behaviour was seen in different FC firmware versions going back to Citrine, and seemed to follow some law of chance, not reliably repeatable. This bug has been tracked down and found to be specific to !GPRS configuration, stemming from our TCS2/TCS3 hybrid and reconstruction of !GPRS support that was bitrotten in TCS3.2/LoCosto version. ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3 version and had to be pulled from TCS2 - but as it turns out, there is a new field in the MMR_REG_REQ primitive that needs to be set correctly, and that psa_mms.c module is the place where this initialization needed to be added.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 08 Jun 2023 08:23:37 +0000
parents 3a14ee9a9843
children
line wrap: on
line source

/*
+-----------------------------------------------------------------------------
|  Project :  GSM-PS
|  Modul   :  ALR_GPRS
+-----------------------------------------------------------------------------
|  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 implements the necessary funtionality
|             for switching to and from GPRS mode and also
|             the handling if determining if GPRS is supported
|             by the cell.
+-----------------------------------------------------------------------------
*/
#ifndef ALR_GPRS_C
#define ALR_GPRS_C


#define ENTITY_PL

/*==== INCLUDES ===================================================*/
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
#include "typedefs.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_alr.h"
#include "mon_alr.h"
#include "pei.h"
#include "tok.h"
#include "pcm.h"
#include "alr_gprs.h"
#define TRACING
#include "alr.h"
#define TRACING

#define TRACING

#if defined (TRACING)
#define ALR_TRACE_GPRS(a)  ALR_TRACE(a)
#else
#define ALR_TRACE_GPRS(a)
#endif

LOCAL BOOL gprs_read_si13                (UBYTE               si13_position);
LOCAL void gprs_alr_nc_enter_ptm         (void);
LOCAL void gprs_alr_tb_meas_ind          (T_TB_MEAS_IND*      report);

LOCAL const T_FUNC tb_table[] = {
  MAK_FUNC_0( gprs_alr_tb_meas_ind, TB_MEAS_IND ) /* 0 */
};

#define ONLY_BCC                 7
static UBYTE gprs_support = 0;

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_get_table         |
+--------------------------------------------------------------------+

  PURPOSE :

*/
void gprs_alr_get_table(const T_FUNC **tab, USHORT *n)
{
    *tab = tb_table;
    *n   = TAB_SIZE (tb_table);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_mon_ctrl_req      |
+--------------------------------------------------------------------+

  PURPOSE :

*/
/*
 * required for TESTMODE A/B
 */
EXTERN UBYTE grlc_test_mode_active(void);
void gprs_alr_mon_ctrl_req(T_MPH_MON_CTRL_REQ* ctrl_req)
{
  ALR_TRACE_GPRS("mon_ctrl_req");

  switch(GET_STATE(STATE_MA))
  {
    case MA_CELL_SELECTION:
      switch(ctrl_req->action)
      {
        case START_MON_EBCCH:
          if(ctrl_req->si_to_read EQ UPDATE_SI13)
          {
            PALLOC(req, MPHC_SCELL_EBCCH_REQ);
            req->schedule_array_size                 = 1;
            req->schedule_array[0].modulus           = 8;
            req->schedule_array[0].relative_position = 0;

            ma_scell_ebcch_req(req);
          }
          break;
        default:
          break;
      }
      break;
    case MA_CELL_RESELECTION:
      switch(ctrl_req->action)
      {
        case START_MON_EBCCH:
          /*for SI13 reading control*/
          if(ctrl_req->si_to_read EQ UPDATE_SI13)
          {
            PALLOC(req, MPHC_SCELL_EBCCH_REQ);
            req->schedule_array_size                 = 1;
            req->schedule_array[0].modulus           = 8;
            req->schedule_array[0].relative_position = 0;

            ma_scell_ebcch_req(req);
          }
          break;
        default:
          break;
      }
      break;
    case MA_IDLE:
      switch(ctrl_req->action)
      {
        case START_MON_EBCCH:
          /*for SI13 reading control*/
          if(ctrl_req->si_to_read EQ UPDATE_SI13)
          {
            PALLOC(req, MPHC_SCELL_EBCCH_REQ);
            req->schedule_array_size                 = 1;
            req->schedule_array[0].modulus           = 8;
            req->schedule_array[0].relative_position = 0;

            ma_scell_ebcch_req(req);
          }
          break;
        case START_MON_NBCCH:
          {
            USHORT  si_mask = 0;
            UBYTE   tc      = 0;  /* refer to GSM Spec 05.02, clause 6.3.1.3 Mapping of BCCH data */
            UBYTE   i,k;

            switch(ctrl_req->si_to_read)
            {
              case UPDATE_SI13:
                gprs_read_si13(SI13_ON_NBCCH);
                break;

              case UPDATE_SI13_GSM:
              {
                PALLOC(scell_bcch_req, MPHC_SCELL_NBCCH_REQ);

                scell_bcch_req->schedule_array_size                 = 1;
                scell_bcch_req->schedule_array[0].modulus           = 8;
                scell_bcch_req->schedule_array[0].relative_position = 4;
                ma_scell_nbcch_req(scell_bcch_req);
              }
              break;

              case UNSPECIFIED_SI:
              case COMPLETE_SI:
                ma_clean_sys_buffer (IND_ALL_IDLE_SI);
                ma_scell_full_nbcch();
                break;

              case UPDATE_SI1:
                si_mask = IND_SI_1;
                tc = (1<<0);
                break;
              case UPDATE_SI2_SI2BIS_OR_SI2TER:
                si_mask = IND_SI_2 | IND_SI_2BIS | IND_SI_2TER;
                tc = (1<<1) | (1<<4) | (1<<5);
                break;
              case UPDATE_SI3_SI4_SI7_OR_SI8:
                si_mask = IND_SI_3 | IND_SI_4;
                tc = (1<<2) | (1<<3) | (1<<6) | (1<<7);
                break;
              case UPDATE_SI9:
                break;
            }

            if ( si_mask )
            {
              PALLOC(scell_bcch_req, MPHC_SCELL_NBCCH_REQ);
              k = 0;
              scell_bcch_req->schedule_array_size = k;
              for ( i = 0; i < 8; i++ )
              {
                if ( (tc & (1 << i)) != 0 )
                {
                  scell_bcch_req->schedule_array[k].modulus = 8;
                  scell_bcch_req->schedule_array[k].relative_position = i;
                  k++;
                  scell_bcch_req->schedule_array_size = k;
                }
              }
              ma_clean_sys_buffer ( si_mask );
              ma_scell_nbcch_req ( scell_bcch_req );
            }
          }
          break;
        case STOP_MON_CCCH:
          /* PBCCH is present, stop all activities */
          /*ma_stop_active_procs(STOP_PCH_READING | STOP_MEASUREMENTS);*/
          pch_stop();
          /*alr_data->gprs_data.pbcch = 1;*/
          break;
        case START_MON_CCCH:
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            pch_configure (NULL, PGM_NORMAL);
            pch_save_pgm(PGM_NORMAL); /* reset saved pgm to REORG_CS */
            pch_start_ccch_req();
          }
          break;

        case LEAVING_PIM_PBCCH:
          /* we are about to enter PAM or PTM */
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            TRACE_EVENT("leave pim");
            alr_data->gprs_data.pim = FALSE;
            pch_stop();
            cb_stop();
            nc_suspend();
          }
          else
          {
            TRACE_EVENT("huch pim");
          }
          break;
        case LEAVING_PAM_PBCCH:
          /* we are about to enter PTM or PIM */
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            /* do nothing, nothing should be active */
            alr_data->gprs_data.pim = FALSE;
            TRACE_EVENT("leave pam");
          }
          else
          {
            TRACE_EVENT("huch pam");
          }
          break;
        case LEAVING_PTM_PBCCH:
          /* we are about to enter PIM */
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            TRACE_EVENT("leave ptm");
            alr_data->gprs_data.pim = FALSE;
            pch_stop();
            nc_suspend();
            alr_data->gprs_data.ptm = FALSE;
          }
          else
          {
            TRACE_EVENT("huch ptm");
          }
          break;
        case ENTER_PTM_PBCCH:
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            alr_data->gprs_data.ptm = TRUE;
            alr_data->gprs_data.pim = FALSE;
            nc_start_pbcch();
          }
          break;
        case ENTER_PIM_PBCCH:
          if(alr_data->gprs_data.pbcch EQ TRUE)
          {
            alr_data->gprs_data.pim = TRUE;
            alr_data->gprs_data.ptm = FALSE;
            nc_start_pbcch();
            cb_start();
          }
          break;
        case ENTER_PTM_BCCH:
          /*
           * convert counters and set NC process to IDLE
           */
          alr_data->gprs_data.pim = FALSE;
          gprs_alr_nc_enter_ptm();
          break;
        default:
          break;
      }
      break;
    case MA_PTM:
      switch(ctrl_req->action)
      {
        case START_MON_EBCCH:
          /*for SI13 reading control*/
          if(ctrl_req->si_to_read EQ UPDATE_SI13)
          {
            PALLOC(req, MPHC_SCELL_EBCCH_REQ);
            req->schedule_array_size                 = 1;
            req->schedule_array[0].modulus           = 8;
            req->schedule_array[0].relative_position = 0;

            ma_scell_ebcch_req(req);
          }
          break;
        case START_MON_NBCCH:
          gprs_read_si13(SI13_ON_NBCCH);
          break;
        case START_MON_CCCH:
          pch_configure (NULL, PGM_NORMAL);
          if(alr_data->gprs_data.pbcch EQ TRUE)
            pch_save_pgm(PGM_NORMAL); /* reset saved pgm to REORG_CS */
          else
          {
            pch_save_pgm(PGM_REORG_CS); /* reset saved pgm to REORG_CS */
            alr_data->pch_data.last_start_ccch_req.bs_pa_mfrms = NOT_PRESENT_8BIT;
          }

          pch_start_ccch_req();
          break;
         /*
          * This case is necessary to stop ccch monitoring in MA_PTM
          * This is required for Testmode A/B
          */
         case STOP_MON_CCCH:
           if(grlc_test_mode_active())
           {
             ma_stop_active_procs(STOP_PCH_READING | STOP_MEASUREMENTS);
             TRACE_EVENT("STOP_MON_CCCH: TESTMODE A/B is running !!!!");
           }
          break;
         case ENTER_PTM_BCCH:
          /*
           * convert counters and set NC process to IDLE
           */
          gprs_alr_nc_enter_ptm();
          break;
        default:
          break;
      }
      break;

    case MA_CON_EST:
      switch(ctrl_req->action)
      {
        case ENTER_PTM_BCCH:
          /*
           * convert counters and set NC process to IDLE
           */
          gprs_alr_nc_enter_ptm();
          break;
        default:
          break;
      }
      break;
    default:
      break;
  }
  PFREE (ctrl_req);

}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_check_packet_paging
+--------------------------------------------------------------------+

  PURPOSE :

*/

#define P1_REST_OCTET_LEN     5
#define GSM408_SPARE_PADDING   0x2b

/*lint -e749 (Info -- local enumeration constant not referenced) */
enum t_p1_ie {  NLN = 0,
                PRIO1,
                PRIO2,
                GRCI,
                PPI1,
                PPI2
};
/*lint +e749 (Info -- local enumeration constant not referenced) */

#define NEXT_BIT(bit_pos,byte_pos) if( (bit_pos >>=1) == 0 ) { bit_pos=0x80; byte_pos++;}

LOCAL enum t_p1_ie p1_ie;
LOCAL UBYTE element_size[PPI2+1] = {
   3,
   3,
   3,
   0,
   1,
   1
 };



BOOL gprs_alr_check_packet_paging(UBYTE* frame, UBYTE which)
{
  UBYTE  byte_pos = 0;
  UBYTE  bit  = 0x80;
  UBYTE *frame_ptr = frame;

  ALR_TRACE_GPRS("check packet paging");
  /* point after Mobile Identity 1 */
  frame = frame + 4 + frame[4] + 1;
  /* check if Mobile Identity 2 is present */
  if (frame[0] EQ 0x17)
    /* skip Mobile Identity 2 */
    /* rest octets = start of mob 2 + len of mob 2 + TL */
    frame= frame + frame[1] + 2;

  if( frame - frame_ptr >= MAX_L2_FRAME_SIZE )
    return FALSE;

  /* decode packet paging */
  for(p1_ie = NLN; p1_ie < PPI2+1;p1_ie++)
  {
    if((frame[byte_pos] & bit) EQ
       (GSM408_SPARE_PADDING & bit))
    {
      /* L:
       *   - element is not used
       *   - check next bit for next element
       */
      if(p1_ie NEQ (which+GRCI))
      {
        NEXT_BIT(bit,byte_pos);/*lint!e720 (Info -- Boolean test of assignment) */
      }
      else
      {
        ALR_TRACE_GPRS("no packet");
        return FALSE;
      }
    }
    else
    {
      /* H:
       *   - element is used
       *   - skip the bits used by this element
       *     except PPIx
       */
      ALR_TRACE_GPRS("element used");
      if(p1_ie NEQ (which+GRCI))
      {
        UBYTE i;
        for(i=element_size[p1_ie]+1; i > 0; i--)
        {
          NEXT_BIT(bit,byte_pos);/*lint!e720 (Info -- Boolean test of assignment) */
        }
      }
      else
      {
        ALR_TRACE_GPRS("packet paging");
        return TRUE;
      }
    }
  }
  return FALSE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_check_packet_paging_2
+--------------------------------------------------------------------+

  PURPOSE :

*/

/*lint -e749 (Info -- local enumeration constant not referenced) */
enum t_p2_ie {
  p2CN3 = 0,
  p2NLN,
  p2PRIO1,
  p2PRIO2,
  p2PRIO3,
  p2PPI3
};
/*lint -e749 (Info -- local enumeration constant not referenced) */

LOCAL enum t_p2_ie p2_ie;
LOCAL UBYTE p2_element_size[p2PPI3+1] = {
  2,
  3,
  3,
  3,
  3,
  1
};

BOOL gprs_alr_check_packet_paging_2(UBYTE* frame, UBYTE which)
{
  UBYTE byte_pos = 0;
  UBYTE bit  = 0x80;

  if(which NEQ 3) return FALSE;
  ALR_TRACE_GPRS("check packet paging 2");
  frame += frame[13]+14;
  /* decode packet paging */
  for(p2_ie = p2CN3; p2_ie < p2PPI3+1;p2_ie++)
  {
    if((frame[byte_pos] & bit) EQ
       (GSM408_SPARE_PADDING & bit))
    {
      /* L:
       *   - element is not used
       *   - check next bit for next element
       */
      if(p2_ie NEQ p2PPI3)
      {
        NEXT_BIT(bit,byte_pos);/*lint!e720 (Info -- Boolean test of assignment) */
      }
      else
      {
        ALR_TRACE_GPRS("no packet");
        return FALSE;
      }
    }
    else
    {
      /* H:
       *   - element is used
       *   - skip the bits used by this element
       *     except PPIx
       */
      ALR_TRACE_GPRS("element used");
      if(p2_ie NEQ p2PPI3)
      {
        UBYTE i;
        for(i=p2_element_size[p2_ie]+1; i > 0; i--)
        {
          NEXT_BIT(bit,byte_pos);/*lint!e720 (Info -- Boolean test of assignment) */
        }
      }
      else
      {
        ALR_TRACE_GPRS("packet paging");
        return TRUE;
      }
    }
  }
  return FALSE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_store_ptmsi       |
+--------------------------------------------------------------------+

  PURPOSE :

*/
void gprs_alr_store_ptmsi(UBYTE indic, ULONG tmsi)
{
  alr_data->gprs_data.v_ptmsi = indic;
  alr_data->gprs_data.ptmsi   = tmsi;
  TRACE_EVENT_P2("v: %d ptmsi: %x", indic, tmsi);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_store_ptmsi       |
+--------------------------------------------------------------------+

  PURPOSE : Store the candidate PTMSI

*/
void gprs_alr_store_ptmsi2(UBYTE indic2, ULONG tmsi2)
{
  alr_data->gprs_data.v_ptmsi2 = indic2;
  alr_data->gprs_data.ptmsi2   = tmsi2;
  TRACE_EVENT_P2("v: %d ptmsi: %x", indic2, tmsi2);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_check_ptmsi       |
+--------------------------------------------------------------------+

  PURPOSE :

*/
BOOL gprs_alr_check_ptmsi(ULONG ptmsi_pag)
{

  if((alr_data->gprs_data.v_ptmsi AND
      alr_data->gprs_data.ptmsi EQ ptmsi_pag) OR
     (alr_data->gprs_data.v_ptmsi2 AND
      alr_data->gprs_data.ptmsi2 EQ ptmsi_pag))
  {
    ALR_TRACE_GPRS("ptmsi match");
    ma_pch_paging_ind (ID_PTMSI, CN_PACKET);
    return TRUE;
  }

  return FALSE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_check_downlink_assign
+--------------------------------------------------------------------+

  PURPOSE :

*/
void gprs_alr_check_downlink_assign(T_MPHC_DATA_IND* data_ind)
{
  /* check dl bit */
  if(data_ind->l2_frame.content[3] & 0x20) {
    ma_send_unitdata (data_ind);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_read_si13             |
+--------------------------------------------------------------------+

  PURPOSE :

*/
BOOL gprs_check_read_si13_only(UBYTE si13_position)
{
  if(gprs_support AND
     si13_position EQ SI13_ON_NBCCH)
    return FALSE;
  else
    return TRUE;
}

LOCAL BOOL gprs_read_si13(UBYTE si13_position)
{
  ALR_TRACE_GPRS("read si13");

  if(gprs_support AND
     si13_position EQ SI13_ON_NBCCH)
  {
    PALLOC(scell_bcch_req, MPHC_SCELL_NBCCH_REQ);
    /*
     * we want to read SI13 on TC=4 which has to be send at least
     * on every 4th consecutive occurence of TC=4
     */
    scell_bcch_req->schedule_array_size                 = 1;
    scell_bcch_req->schedule_array[0].modulus           = 8;
    scell_bcch_req->schedule_array[0].relative_position = 4;
    ma_scell_nbcch_req(scell_bcch_req);
    return FALSE;
  }
  else return TRUE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_stop                  |
+--------------------------------------------------------------------+

  PURPOSE :

*/
void gprs_alr_init(void)
{
  ALR_TRACE_GPRS("gprs_alr_init");
  alr_data->gprs_data.ign_pgm    = FALSE;
  alr_data->gprs_data.pbcch      = FALSE;
  alr_data->gprs_data.ptm        = FALSE;
  alr_data->gprs_data.check_bsic = FALSE;
  alr_data->gprs_data.sync_only  = FALSE;
  alr_data->gprs_data.pcco_active= FALSE;
  alr_data->nc_sync_with_grr     = FALSE;
  gprs_support = FALSE;
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_tb_meas_ind       |
+--------------------------------------------------------------------+

  PURPOSE :

*/
LOCAL void gprs_alr_tb_meas_ind (T_TB_MEAS_IND *report)
{
  ALR_TRACE_GPRS("tb_meas_ind");
  switch(GET_STATE(STATE_MA))
  {
    case MA_PTM:
       /*Measurement Report in Packet Transfer Mode*/
      {
        USHORT temp;
        USHORT index;
        UBYTE  diff;
        UBYTE  i,lim;
        T_NC*  pcell;

        if(report->tb_meas_result[0].arfcn EQ NOT_PRESENT_16BIT)
        {
          lim = alr_data->nc_data.c_ba_arfcn;
        }
        else
        {
          lim = TB_BA_LIST_SIZE;
        }

        /* 
         * reduce the time for next sync
         * Decrement the 10sec timer counter variable by 2
         */
        alr_data->nc_data.c_ncsync_tim = alr_data->nc_data.c_ncsync_tim-2;
        if ((signed char)( alr_data->nc_data.c_ncsync_tim) < 0)
          alr_data->nc_data.c_ncsync_tim = 0;

        if( alr_data->nc_data.c_ncsync_tim==0 )
        {
          /* 10 sec have elapsed. Perform all requisite tasks */
          nc_ncsync_tim_expiry();
        }
  
        for (pcell=&alr_data->nc_data.cell[0], i = 0; i < lim; i++,pcell++)
        {
          if(lim EQ alr_data->nc_data.c_ba_arfcn)
          {
            index = i;
          }
          else
          {
            /* For all cells look if it is in BA(BCCH)  */
            switch(index = nc_get_index(ARFCN_TO_G23(report->tb_meas_result[i].arfcn)))
            {
              case LAST_BSIC_REQ:
              case NOT_PRESENT_16BIT:
                continue;
              default:
                break;
            }
          }
          /*
           * the ncell is in the list
           * so store the rxlev values
           */

          if (alr_data->nc_data.cell[index].c_rxlev EQ NOT_PRESENT_8BIT)
          {
            /*
             * if it is a new cell, build an average from the first value
             * to speed up fb sb read
             */
            if ((signed short) (report->tb_meas_result[i].rxlev) < 0)
            {
              report->tb_meas_result[i].rxlev = 0;
            }

            alr_data->nc_data.cell[index].rxlev[0] = report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;
            alr_data->nc_data.cell[index].rxlev[1] = report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;
            alr_data->nc_data.cell[index].rxlev[2] = report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;
            alr_data->nc_data.cell[index].rxlev[3] = report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;
            alr_data->nc_data.cell[index].rxlev[4] = report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;
            alr_data->nc_data.cell[index].c_rxlev = 0;
          }
          else
          {
            if ((signed short) (report->tb_meas_result[i].rxlev) < 0)
              report->tb_meas_result[i].rxlev = 0;

            alr_data->nc_data.cell[index].rxlev[alr_data->nc_data.cell[index].c_rxlev++] =
              report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas;

            if (alr_data->nc_data.cell[index].c_rxlev >= 5)
              alr_data->nc_data.cell[index].c_rxlev = 0;
          }

          temp = (USHORT)(alr_data->nc_data.cell[index].rxlev[0] +
                          alr_data->nc_data.cell[index].rxlev[1] +
                          alr_data->nc_data.cell[index].rxlev[2] +
                          alr_data->nc_data.cell[index].rxlev[3] +
                          alr_data->nc_data.cell[index].rxlev[4]);

          alr_data->nc_data.cell[index].rxlev_average = (UBYTE)(temp / 5);
          /*
           * store the results seperately for averaging when NC=1 or NC=2 
           */
#ifdef GPRS
          if(alr_data->nwctrl_meas_active)
          {
            pcell->nc_rxlev += (report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas);
            pcell->c_nc_rxlev++;
          }
#endif

          TRACE_EVENT_P3("%d %d rx: %d ",i, alr_data->nc_data.cell[i].ba_arfcn,
            report->tb_meas_result[i].rxlev / report->tb_meas_result[i].num_meas);

          switch (alr_data->nc_data.cell[index].status)
          {
            case INACTIVE:
              nc_set_status (index, IDLE);
              break;
            case EXCLUDED:
              diff = (UBYTE)(alr_data->nc_data.cell[index].rxlev_average -
                             alr_data->nc_data.cell[index].last_rxlev);

              if (diff < 128 AND diff >= 6)
              {
                /* result is positive and more than 6 dBm */
                nc_set_status (index, IDLE);
              }
              break;
            default:
              break;
          }

        } /* for all */
        PFREE(report);

        nc_check_activity();
      }
      break;
    default:
      PFREE(report);
      break;
  }
}


/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_nc_enter_ptm      |
+--------------------------------------------------------------------+

  PURPOSE : After the Packet Access Phase we enter Packet Transfer
            Mode and have to do Measurements and Cell Reselection like
            in Idle Mode.
*/

LOCAL void gprs_alr_nc_enter_ptm (void)
{
  nc_resume();  /* set NC_STATE to IDLE */

  alr_data->nc_data.c_reports   = (alr_data->nc_data.c_reports*10)/alr_data->nc_data.max_reports;
  alr_data->nc_data.max_reports = 10;
  alr_data->nc_data.cell[LAST_BSIC_REQ].status = INACTIVE;

  TRACE_EVENT_P2("glob reps: %d max_report: %d", alr_data->nc_data.c_reports, alr_data->nc_data.max_reports);
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_check_page_mode       |
+--------------------------------------------------------------------+

  PURPOSE : Do not change the page mode configuration in L1
            if ing_pgm is set. ie. we have to stay in REORG.

*/
void gprs_check_page_mode(T_MPHC_DATA_IND* data_ind)
{
  if(alr_data->gprs_data.ign_pgm EQ TRUE)
  {
    pch_check_page_mode_cr(data_ind);
  }
  else
  {
    pch_check_page_mode(data_ind);
  }
}

/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103)       MODULE  : ALR_GPRS                   |
| STATE   : code                ROUTINE : gprs_alr_is_supported      |
+--------------------------------------------------------------------+

  PURPOSE : This function returns whether GPRS is supported in
            the cell.

*/
GLOBAL BOOL gprs_alr_is_supported( void )
{
  return( gprs_support EQ TRUE );
}

void set_gprs_support( UBYTE support )
{
  gprs_support = support;
}

#endif /* ALR_GPRS_C */