view src/g23m-gsm/rr/rr_datg.c @ 683:81394dcdf4d3

uartfax.c: OM-style wakeup interrupt implemented for Tango
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 26 Jun 2020 03:06:16 +0000
parents 27a4235405c6
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 holds the functions for handling primitives
|             sent from entity GRR to entity RR and vice versa.
+-----------------------------------------------------------------------------
*/

#ifndef RR_DATG_C
#define RR_DATG_C

#ifdef GPRS

#define ENTITY_RR

/*==== INCLUDES ===================================================*/

#include <string.h>
#include <stddef.h>
#include "typedefs.h"
#include "pcm.h"
#include "pconst.cdg"
#include "mconst.cdg"
#include "message.h"
#include "ccdapi.h"
#include "vsi.h"
#include "custom.h"
#include "gsm.h"
#include "prim.h"
#include "pei.h"
#include "tok.h"
#include "rr_gprs.h"
#include "rr.h"

static UBYTE get_r_bit (void);
static void  handle_non_gprs_param(T_non_gprs* non_gprs);
static void  dat_rrgrr_rr_est_ind (void);
static void  dat_build_rr_initialisation_request  (void);

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_channel_req               |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_CHANNEL_REQ received from GRR.
            This primitive indicates to the RR to send a channel request

*/

void dat_rrgrr_channel_req (T_RRGRR_CHANNEL_REQ *chan_req)
{
  GET_INSTANCE_DATA;
  USHORT req = (USHORT) (chan_req->req_data + 0x0400);
  TRACE_FUNCTION ("gprs_rrgrr_channel_req()");

  /*
   * check availability of GPRS
   */
  switch (GET_STATE(STATE_GPRS)) /* rr_data->gprs_data.gprs_avail) */
  {
    case GPRS_PIM_BCCH:
    case GPRS_PAM_BCCH:
    case GPRS_PTM_BCCH:
      if (GET_STATE(STATE_DAT) NEQ DAT_NULL)
      {
        switch (req)
        {
          case ESTCS_GPRS_1P:
          case ESTCS_GPRS_SB:
          case ESTCS_PAGING:
            /*
             * reset values used in the Packet Access
             * Procedure
             */
            if (IS_TIMER_ACTIVE(T3126))
            {
              TIMERSTOP(T3126);
            }
            memset(rr_data->gprs_data.rr_sdu, NOT_PRESENT_8BIT,
                   sizeof(rr_data->gprs_data.rr_sdu));
            rr_data->gprs_data.tma_in_progress = FALSE;
            rr_data->gprs_data.fn              = NOT_PRESENT_32BIT;
            rr_data->gprs_data.req_ref_idx     = NOT_PRESENT_8BIT;
            rr_data->sc_data.first_attempt     = TRUE;
            rr_data->repeat_est                = FALSE;
            /* start procedure */
            dat_start_immediate_assign((USHORT)(req EQ
                                       ESTCS_PAGING ? ESTCS_GPRS_PAGING : req));
            SET_STATE(STATE_GPRS, GPRS_PAM_BCCH);
            break;
          default:
            TRACE_EVENT("channel request with wrong value");
            break;
        }
      }
      else
      {
        TRACE_EVENT ("store channel req");
        if(! srv_store_prim((T_PRIM *)D2P(chan_req)))
        {
          TRACE_EVENT("prim store full");
          PFREE(chan_req);
        }
        return;
      }
      break;
    case GPRS_PIM_PBCCH:
    case GPRS_PAM_PBCCH:
    case GPRS_PTM_PBCCH:
      TRACE_EVENT ("chan_req w/ PBCCH!");
      break;
    case GPRS_ACTIVATED:
      TRACE_EVENT ("no cell selected yet, or cell supports no GPRS");
      break;
    case GPRS_SUSPENDED_BCCH:
    case GPRS_SUSPENDED_PBCCH:
      TRACE_EVENT ("GPRS is suspended!");
      break;
    default:
      TRACE_EVENT ("GPRS not supported");
      break;
  }
  PFREE (chan_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_check_gprs_imm_ass              |
+-----------------------------------------------------------------------------+

  PURPOSE : checks an incoming immediate assignment message and forwards
            it to GRR if necessary.

*/

GLOBAL BOOL dat_check_gprs_imm_ass (T_MPH_UNITDATA_IND * unitdata,
                                     T_D_IMM_ASSIGN     * imm_assign,
                                     UBYTE index)
{
  GET_INSTANCE_DATA;
  BOOL ret = FALSE;
  int  send_indication = 0;

  TRACE_FUNCTION ("dat_check_gprs_imm_ass()");

  if (GET_STATE(STATE_GPRS) NEQ GPRS_PAM_BCCH)
    return FALSE; /* normal circuit switched handling */

  TRACE_EVENT_P7 ("fn=%u tma=%u ri=%x d_t=%u (tmaip=%u fn=%d ri=%d)",
      unitdata->fn, imm_assign->tma, index, imm_assign->d_t,
      rr_data->gprs_data.tma_in_progress, rr_data->gprs_data.fn,
      rr_data->gprs_data.req_ref_idx);

  if (imm_assign->tma EQ TMA_1)
  {
    /* Message indicates to be the first message of two in a
     * two-message assignment of a downlink TBF.
     */
    if (rr_data->gprs_data.tma_in_progress)
    {
      TRACE_ERROR ("more than one TMA after another!");
      TRACE_EVENT_P4 ("ri=%x?%x(old) fn=%u?%u(old)",
        index, rr_data->gprs_data.req_ref_idx,
        unitdata->fn, rr_data->gprs_data.fn);
    }

    rr_data->gprs_data.tma_in_progress = TRUE;

    /*
     * store message, framenumber and burst index
     */
    gprs_rrgrr_store_sdu(rr_data->gprs_data.rr_sdu, &unitdata->sdu);
    rr_data->gprs_data.fn = unitdata->fn;
    rr_data->gprs_data.req_ref_idx = index;
    ret = TRUE; /* further treatment by GRR */
  }
  else
  {
    if (rr_data->gprs_data.tma_in_progress)
    { /*
       * MS awaits the second message of two in a two-message assignment
       * of a downlink TBF.
       * The message must belong to the same channel request
       * and the time difference must be less than two multiframes.
       */
      BOOL in_time, same_reference_index;
      U32  delta_fn;

      if (rr_data->gprs_data.fn > unitdata->fn)
        delta_fn = unitdata->fn + HYPERFRAME - rr_data->gprs_data.fn;
      else
        delta_fn = unitdata->fn - rr_data->gprs_data.fn;

      in_time = (delta_fn/51) < 2;
      same_reference_index = rr_data->gprs_data.req_ref_idx EQ index;

      TRACE_EVENT_P6 ("TMA:delta_fn=%u %s time, %sequal ref idx(%x?%x): %s",
        delta_fn, in_time?"in":"out of", same_reference_index?"":"un",
        rr_data->gprs_data.req_ref_idx, index,
        (in_time AND same_reference_index)?"OK":"not ok");

      if (in_time AND same_reference_index)
      { /* This is the matching second message of a tma.
         * -> Send both immediate assignments
         */
        send_indication = 2;
        ret = TRUE; /* further treatment by GRR */
      }
      else
      {
        TRACE_ERROR ("MS awaits second message of a tma, this is not the right one!");

        if (!in_time)
        {
          /*
           * If the MS does not received the second IMMEDIATE ASSIGNMENT message
           * in a two-message assignment within two multiframe periods following
           * the first message, the MS shall discard the IA message received.
           */
          rr_data->gprs_data.tma_in_progress = FALSE;
          rr_data->gprs_data.fn = NOT_PRESENT_32BIT;
          rr_data->gprs_data.req_ref_idx = NOT_PRESENT_8BIT;
        }

        if(imm_assign->d_t EQ D_T_TBF)
        {
          /*
           * stop timer and set RR state
           * the handling of PDCH is done by GPRS
           */
          ret = TRUE; /* further treatment by GPRS */
        }
        else
        {
          /*
           * allocation on SDCCH for GPRS
           * normal RR establishment
           */
          ret = FALSE;
        }
      }
    }
    else
    { /*
       * MS donīt await the second message of two in a two-message assignment
       * of a downlink TBF and the message isnīt the first message of a tma.
       *
       * -> Send one indication to GRR
       */
      send_indication = 1;

      if(imm_assign->d_t EQ D_T_TBF)
      {
        /*
         * stop timer and set RR state
         * the handling of PDCH is done by GPRS
         */
        ret = TRUE; /* further treatment by GRR */
      }
      else
        /*
         * allocation on SDCCH for GPRS
         * normal RR establishment
         */
        ret = FALSE;
    }
  }

  if (send_indication)
  {
    if (send_indication EQ 2)
    {
      PALLOC_SDU ( rrgrr_ia_ind, RRGRR_IA_IND, MAX_L2_FRAME_SIZE * BITS_PER_BYTE); /* T_RRGRR_IA_IND */
      /*
       * indicate first immediate assignment
       */
      gprs_rrgrr_fill_from_stored_sdu(&rrgrr_ia_ind->sdu, rr_data->gprs_data.rr_sdu);
      rrgrr_ia_ind->fn    = 0;      /* not valid */
      rrgrr_ia_ind->r_bit = 0;      /* not valid */
      PSENDX (GRR, rrgrr_ia_ind);
    }
    {
      PALLOC_SDU ( rrgrr_ia_ind2, RRGRR_IA_IND, MAX_L2_FRAME_SIZE * BITS_PER_BYTE); /* T_RRGRR_IA_IND */
      /*
       * indicate second or sole immediate assignment
       */
      if (unitdata->sdu.o_buf >= 8)
      {
        unitdata->sdu.o_buf -= 8;
        unitdata->sdu.l_buf += 8;
      }
      else
      {
        TRACE_ERROR("dat_check_gprs_imm_ass(), not able to move offset o_buf");
      }
      gprs_rrgrr_fill_from_stored_sdu(&rrgrr_ia_ind2->sdu,
        &unitdata->sdu.buf[unitdata->sdu.o_buf/8]);
      rrgrr_ia_ind2->fn = unitdata->fn;
      rrgrr_ia_ind2->r_bit = get_r_bit ();
      PSENDX (GRR, rrgrr_ia_ind2);
    }
  }

  TRACE_EVENT_P1 ("dat_check_gprs_imm_ass() returns %u", ret);
  return ret;
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_check_immediate_assignment_ext |
+-----------------------------------------------------------------------------+

  PURPOSE : checks an incoming immediate assignment extended message
            and forwards it to GRR if necessary.

*/

GLOBAL void dat_check_imm_ass_ext (T_MPH_UNITDATA_IND * unitdata,
                                                 UBYTE index)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("grps_check_immediate_assignment_ext()");

  /*switch (rr_data->ms_data.establish_cause)
  {
    case ESTCS_GPRS_1P:
    case ESTCS_GPRS_SB:
    case ESTCS_GPRS_PAGING:*/
  switch (GET_STATE(STATE_GPRS))
  {
    case GPRS_PAM_BCCH:
      /*
       * Immediate Assignment Extended received on AGCH during connection
       * establishment
       */
      {
        PALLOC_SDU (rrgrr_iaext_ind, RRGRR_IAEXT_IND, MAX_L2_FRAME_SIZE * BITS_PER_BYTE);
        gprs_rrgrr_store_sdu(rr_data->gprs_data.rr_sdu, &unitdata->sdu);
        gprs_rrgrr_fill_from_stored_sdu(&rrgrr_iaext_ind->sdu, rr_data->gprs_data.rr_sdu);

        rrgrr_iaext_ind->ia_index = index;
        rrgrr_iaext_ind->fn       = unitdata->fn;
        rrgrr_iaext_ind->r_bit    = get_r_bit();

        PSENDX (GRR, rrgrr_iaext_ind);
      }
      break;
    default:
      break;
  }
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : att_check_imm_ass_rej               |
+-----------------------------------------------------------------------------+

  PURPOSE : checks an incoming immediate assignment reject message and forwards
            it to GRR if necessary.

*/

GLOBAL UBYTE dat_check_imm_ass_rej (UBYTE wait_ind)
{
  GET_INSTANCE_DATA;
  UBYTE ret = FALSE;

  TRACE_FUNCTION ("att_check_imm_ass_rej()");

/*
  switch (rr_data->ms_data.establish_cause)
  {
    case ESTCS_GPRS_1P:
    case ESTCS_GPRS_SB:
    case ESTCS_GPRS_PAGING:
    */
  switch (GET_STATE(STATE_GPRS))
  {
    case GPRS_PAM_BCCH:
      /*
       * Immediate Assignment Reject received on AGCH during connection
       * establishment
       */
      {
        PALLOC( rrgrr_assignment_rej_ind, RRGRR_ASSIGNMENT_REJ_IND);

        rrgrr_assignment_rej_ind->wait_ind = wait_ind;
        rrgrr_assignment_rej_ind->r_bit    = get_r_bit ();

        PSENDX (GRR, rrgrr_assignment_rej_ind);
      }
      ret = TRUE;
      break;
      /* return TRUE; */
    default:
      break;
  }
  return ret;
  /* return FALSE; */
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_check_imm_assign_pch            |
+-----------------------------------------------------------------------------+

  PURPOSE : checks an incoming immediate assignment message in idle mode on
            PCH

*/

GLOBAL UBYTE dat_check_imm_assign_pch (T_MPH_UNITDATA_IND * unitdata,
                                       T_D_IMM_ASSIGN     * imm_assign)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_check_imm_assign_pch()");
  TRACE_EVENT("check dl ass");
  if(imm_assign->d_t EQ D_T_TBF AND
     imm_assign->dl  EQ DL_1)
  {
    PALLOC_SDU ( rrgrr_ia_ind, RRGRR_IA_DOWNLINK_IND, MAX_L2_FRAME_SIZE * BITS_PER_BYTE);
    switch(GET_STATE(STATE_GPRS))
    {
      case GPRS_NULL:
      case GPRS_ACTIVATED:
        /*
         * here it would be possible to store it if we are in
         * cell reselection
         * but i think this does not make sense:
         * -> this is not page (ia_dl is only cell wide),
         * -> we dont know if its actually for us.
         * -> first we have to do a Cell Update.
         */
      case GPRS_SUSPENDED_BCCH:
      case GPRS_SUSPENDED_PBCCH:
        TRACE_EVENT_P1("dl ass in state %d", GET_STATE(STATE_GPRS) );
        PFREE(rrgrr_ia_ind);
        return TRUE;
      case GPRS_PIM_BCCH:
      case GPRS_PAM_BCCH:
        /*
         * Immediate Assignment received in idle mode and it is a PDCH
         */
        TRACE_EVENT("dl ass");
        rr_data->start_cell_reselection = FALSE;
        TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection);
        gprs_rrgrr_store_sdu(rr_data->gprs_data.rr_sdu, &unitdata->sdu);
        gprs_rrgrr_fill_from_stored_sdu(&rrgrr_ia_ind->sdu, rr_data->gprs_data.rr_sdu);
        rrgrr_ia_ind->fn    = unitdata->fn;
        rrgrr_ia_ind->r_bit = NOT_PRESENT_8BIT;

        PSENDX (GRR, rrgrr_ia_ind);
        return TRUE;
      default:
		PFREE(rrgrr_ia_ind);
        return FALSE;
    }
  }
  return FALSE;
}



/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_check_packet_paging_ind         |
+-----------------------------------------------------------------------------+

  PURPOSE : checks an incoming paging whether it is for GPRS.

*/

UBYTE dat_check_packet_paging_ind (T_MPH_PAGING_IND * pag_ind)
{
  GET_INSTANCE_DATA;
  UBYTE ret=2;
  TRACE_FUNCTION ("dat_check_packet_paging_ind ()");

  if (pag_ind->channel_needed EQ CN_PACKET)
  {
    switch(GET_STATE(STATE_GPRS))
    {
      case GPRS_PIM_BCCH:
        {
          /*
           * Inform GRR about packet paging
           */
          PALLOC ( rrgrr_packet_paging_ind, RRGRR_PACKET_PAGING_IND );
          switch (pag_ind->identity_type)
          {
            case ID_IMSI:
              rrgrr_packet_paging_ind->pg_type = RRGRR_IMSI;
              break;
            case ID_PTMSI:
              rrgrr_packet_paging_ind->pg_type = RRGRR_PTMSI;
              break;
            default:
              TRACE_EVENT("packet paging with TMSI");
              break;
          }
          PSENDX (GRR, rrgrr_packet_paging_ind);
        }
        ret = 2;
        break;
      case GPRS_NULL:
      case GPRS_ACTIVATED:
        /*strange cases, ignore it */
        break;
      case GPRS_SUSPENDED_BCCH:
      case GPRS_SUSPENDED_PBCCH:
        /*is is a packet paging but we are suspended so ignore it*/
        ret = 2;
        break;
      default:
        break;
    }
  }
  else
  {
    /* normal CS paging */
    switch(GET_STATE(STATE_GPRS))
    {
      case GPRS_SUSPENDED_BCCH:
      case GPRS_SUSPENDED_PBCCH:
      case GPRS_NULL:
      case GPRS_ACTIVATED:
        /* we are already suspended so just react to the paging */
        /* or GPRS is not activated */
        ret = 0;
        break;
      default:
        /* ask GRR */
        ret = 1;
        break;
    }
  }
  return ret;
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_start_sabm                     |
+-----------------------------------------------------------------------------+

  PURPOSE : starts connection establishment if a packet service is requested.

*/

BOOL dat_gprs_start_sabm(void)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("gprs_start_sabm()");

  switch (GET_STATE(STATE_GPRS))
  {
    /*
     * Mobile originated packet connection
     */
    case GPRS_PAM_BCCH:
      dat_build_rr_initialisation_request ();
      return TRUE;
    default:
      return FALSE;
  }
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_build_rr_initialisation_request|
+-----------------------------------------------------------------------------+

  PURPOSE : starts connection establishment if a mobile originated packet
            service is requested and it builds

*/

static void dat_build_rr_initialisation_request (void)
{
  GET_INSTANCE_DATA;
  MCAST (rr_init_req, D_RR_INIT_REQ);
  PALLOC_MSG (establish_req, DL_ESTABLISH_REQ, D_RR_INIT_REQ);

  TRACE_FUNCTION ("grps_build_rr_initialisation_request()");
  TRACE_EVENT ("POWER CLASS: grps_build_rr_initialisation_request()");

  dat_code_prr_channel (&establish_req->ch_type,
                        &establish_req->sapi,
                        rr_data->sc_data.chan_desc.chan_type);

  /*
   * fill message parameter
   */
  rr_init_req->msg_type               = D_RR_INIT_REQ;
  rr_init_req->ciph_key_num.key_seq   = rr_data->ms_data.cksn;
  memcpy(&rr_init_req->mob_class_2, &rr_data->ms_data.classmark2,
         sizeof(rr_init_req->mob_class_2));

  /*
   * set power classes
   */
  rr_init_req->mob_class_2.rf_pow_cap = att_get_power ();

  /*
   * set all other parameter
   */
  rr_init_req->chan_coding.mac_mode   = rr_data->gprs_data.mac_req;
  rr_init_req->chan_coding.cod_scheme = rr_data->gprs_data.cs_req;

  /*
   * store tlli independent from the used binary format
   */
  rr_init_req->ded_tlli.l_ded_tlli = 32;
  rr_init_req->ded_tlli.o_ded_tlli = 0;
  ccd_codeByte (rr_init_req->ded_tlli.b_ded_tlli, 0,  8, (UBYTE)(rr_data->gprs_data.tlli >> 24));
  ccd_codeByte (rr_init_req->ded_tlli.b_ded_tlli, 8,  8, (UBYTE)(rr_data->gprs_data.tlli >> 16));
  ccd_codeByte (rr_init_req->ded_tlli.b_ded_tlli, 16, 8, (UBYTE)(rr_data->gprs_data.tlli >> 8));
  ccd_codeByte (rr_init_req->ded_tlli.b_ded_tlli, 24, 8, (UBYTE)rr_data->gprs_data.tlli);

  rr_init_req->chan_req_desc.or_ty = rr_data->gprs_data.p_chan_req_des.mo_mt;

  if (rr_init_req->chan_req_desc.or_ty)
  {
    rr_init_req->chan_req_desc.v_crd_prio    = 1;
    rr_init_req->chan_req_desc.crd_prio      = rr_data->gprs_data.p_chan_req_des.prio;
    rr_init_req->chan_req_desc.v_rlc_mode    = 1;
    rr_init_req->chan_req_desc.rlc_mode      = rr_data->gprs_data.p_chan_req_des.rlc_mode_req;
    rr_init_req->chan_req_desc.v_llc_fr_type = 1;
    rr_init_req->chan_req_desc.llc_fr_type   = rr_data->gprs_data.p_chan_req_des.llc_type;
    rr_init_req->chan_req_desc.v_rbw         = 1;
    rr_init_req->chan_req_desc.rbw           = rr_data->gprs_data.p_chan_req_des.req_bwd;
    rr_init_req->chan_req_desc.v_rlc_c_oct   = 1;
    rr_init_req->chan_req_desc.rlc_c_oct     = rr_data->gprs_data.p_chan_req_des.rlc_octets;
  }

  rr_init_req->gprs_meas_res.c_val    = rr_data->gprs_data.gprs_meas_results.c_value;
  rr_init_req->gprs_meas_res.rxqual   = rr_data->gprs_data.gprs_meas_results.rxqual;
  rr_init_req->gprs_meas_res.sign_var = rr_data->gprs_data.gprs_meas_results.sign_var;

  for_dat_est_req_content  (establish_req);
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_stop_dcch_ind                  |
+-----------------------------------------------------------------------------+

  PURPOSE : inform GRR about failed layer 2 establishment.

*/
void dat_stop_dcch_ind (UBYTE stop_cause)
{
  GET_INSTANCE_DATA;
  PALLOC(stop, RRGRR_STOP_DCCH_IND);
  TRACE_FUNCTION ("gprs_stop_dcch_ind()");
  stop->stop_cause = stop_cause;
  /* we will do a CR anyway */
  SET_STATE(STATE_GPRS, GPRS_ACTIVATED);
  PSENDX(GRR, stop);
}



/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_rrgrr_gprs_data_req            |
+-----------------------------------------------------------------------------+

  PURPOSE : The primitive RRGRR_GPRS_DATA_REQ contains various parameters from
            GRR. Layer 1 is configured and some data are stored.
*/

void dat_rrgrr_gprs_data_req (T_RRGRR_GPRS_DATA_REQ *data_req)
{
  GET_INSTANCE_DATA;
  /*
   * store parameter
   */

  rr_data->gprs_data.tlli              = data_req->tlli;
  rr_data->gprs_data.p_chan_req_des    = data_req->p_chan_req_des;
  rr_data->gprs_data.gprs_meas_results = data_req->gprs_meas_results;
  rr_data->gprs_data.mac_req           = data_req->mac_req;
  rr_data->gprs_data.cs_req            = data_req->cs_req;
  rr_data->gprs_data.current_rai       = data_req->rai;

  if(rr_data->gprs_data.ptmsi  NEQ data_req->old_ptmsi OR
     rr_data->gprs_data.ptmsi2 NEQ data_req->new_ptmsi)
  {
    rr_data->gprs_data.ptmsi  = data_req->old_ptmsi;
    rr_data->gprs_data.ptmsi2 = data_req->new_ptmsi;
    att_mph_identity_req ();
  }

  PFREE (data_req);
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_data_ind                  |
+-----------------------------------------------------------------------------+

  PURPOSE : Send the primitive rrgrr_data_ind to GRR.
            This primitive indicates to the GRR that a
            CTRL Message on DCCH for RR was received.
  IN      : frame_number
  OUT     : rrgrr_data_ind

*/

void dat_rrgrr_data_ind (T_DL_DATA_IND* dl_data_ind)
{
  USHORT soff,doff;
  PALLOC_SDU ( rrgrr_data_ind, RRGRR_DATA_IND, dl_data_ind->sdu.l_buf );

  TRACE_EVENT ("dat_rrgrr_data_ind ()");

  /*
   * compute byte offsets (soff,doff) into message streams,
   * assume that o_buf is multiple of 8
   */

  doff = (USHORT)(rrgrr_data_ind->sdu.o_buf / BITS_PER_BYTE);
  soff = (USHORT)(   dl_data_ind->sdu.o_buf / BITS_PER_BYTE);

  memcpy ( &rrgrr_data_ind->sdu.buf[doff],
           &   dl_data_ind->sdu.buf[soff], BYTELEN ( dl_data_ind->sdu.l_buf ) );

  rrgrr_data_ind->fn = NOT_PRESENT_32BIT;

  PFREE ( dl_data_ind );
  PSENDX (GRR, rrgrr_data_ind);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_rrgrr_data_req                 |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_DATA_REQ received from GRR.
            This primitive indicates to the RR to send a block on DCCH.
  IN      :
  OUT     :

*/

void dat_rrgrr_data_req (T_RRGRR_DATA_REQ *rrgrr_data_req)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_data_req ()");

  switch(GET_STATE(STATE_GPRS))
  {
    case GPRS_DEDI_SDCCH:
      {
        PPASS (rrgrr_data_req, dl_data_req, DL_DATA_REQ);

        dat_code_prr_channel (&dl_data_req->ch_type,
                              &dl_data_req->sapi,
                              rr_data->sc_data.chan_desc.chan_type);
        dat_vsd_bit_set ((T_L3_SDU *)&dl_data_req->sdu, SET_ONLY);
        for_dat_l3_data_req (dl_data_req);
      }
      break;
    default:
      break;
  }

  PFREE (rrgrr_data_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rgrr_suspend_dcch_req           |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_SUSPEND_DCCH_REQ received from GRR.
            This primitive is used by GRR to order RR to stop the
            dedicated channel. It is only a trigger.
  IN      : RRGRR-SUSPEND-DCCH-REQ
  OUT     : DL-SUSPEND-REQ and MPH-DEDICATED-REQ

*/
void dat_rrgrr_suspend_dcch_req( T_RRGRR_SUSPEND_DCCH_REQ  *suspend_dcch_req)
{
  GET_INSTANCE_DATA;
  PALLOC (dedicated_req, MPH_DEDICATED_REQ);

  TRACE_EVENT ("dat_rrgrr_suspend_dcch_req ()");

  for_suspend_layer_2();

  memset (dedicated_req, 0, sizeof (T_MPH_DEDICATED_REQ));
  dedicated_req->mod = MODE_PDCH_ASSIGN;
  PSENDX (PL, dedicated_req);

  SET_STATE (STATE_DAT, DAT_PDCH_ASS);

  PFREE (suspend_dcch_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_suspend_dcch_cnf          |
+-----------------------------------------------------------------------------+

  PURPOSE : Create the primitive RRGRR_SUSPEND_DCCH_CNF and send it to GRR.
            As a response GRR will start the establishment of a TBF.
  IN      : nothing
  OUT     : RRGRR_SUSPEND_DCCH_CNF

*/
void dat_rrgrr_suspend_dcch_cnf( void )
{
  PALLOC (suspend_dcch_cnf, RRGRR_SUSPEND_DCCH_CNF);
  PSENDX (GRR, suspend_dcch_cnf);
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_reconnect_dcch_req        |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR-RECONNECT-DCCH-REQ received from GRR.
            This primitive is used by GRR during a PDCH Assignment procedure
            and RR Network Controlled Cell Change Order to order RR to
            continue with the dedicated channel.
  IN      : T-RRGRR-RECONNECT-DCCH-REQ
  OUT     : DL-DATA-REQ(u-assign-fail) or MPH_DEDICATED_FAIL_REQ

*/
void dat_rrgrr_reconnect_dcch_req (T_RRGRR_RECONNECT_DCCH_REQ  *reconnect_dcch_req)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_reconnect_dcch_req()");

  if ( rr_data->gprs_data.tbf_est EQ TBF_EST_PDCH OR
       rr_data->gprs_data.tbf_est EQ TBF_EST_CCO     )
  {
    UBYTE next_state;

    if ( rr_data->gprs_data.tbf_est EQ TBF_EST_PDCH )
      next_state = DAT_PDCH_ASS_3;
    else
      next_state = DAT_CCO_3;

    /*
     * The dedicated channel has been suspended at PL and DL.
     * However RR could not established the TBF.
     */

    rr_data->gprs_data.tbf_est = TBF_EST_NONE;
    dat_code_mph_old_chan_req();
    rr_data->gprs_data.reconn_cause = reconnect_dcch_req->reconn_cause;
    rr_data->gprs_data.cco_need_reconnect_cnf = TRUE;
    SET_STATE (STATE_DAT, next_state);
  }
  else /* Any other state assuming D_PDCH_ASS_CMD has been sent to GRR.
          GRR cannot evaluate the message. */
    {
    MCAST (u_assign_fail, U_ASSIGN_FAIL);
    PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_ASSIGN_FAIL);

    /*
     * set channel type and SAPI
     */
    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type);

    u_assign_fail->msg_type = U_ASSIGN_FAIL;
    u_assign_fail->rr_cause = reconnect_dcch_req->reconn_cause;
    for_dat_data_req (dl_data_req);

    dat_rrgrr_reconnect_dcch_cnf (RECONN_OK);
  }
  PFREE (reconnect_dcch_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_reconnect_dcch_cnf        |
+-----------------------------------------------------------------------------+

  PURPOSE : Create the primitive RRGRR_RECONNECT_DCCH_CNF and send it to GRR.
            This indicates the outcome of the Reconnection procedure to GRR.
  IN      : nothing
  OUT     : RRGRR-RECONNECT-DCCH-CNF

*/
void dat_rrgrr_reconnect_dcch_cnf( UBYTE reconn_state )
{
  PALLOC (reconnect_dcch_cnf, RRGRR_RECONNECT_DCCH_CNF);
  TRACE_EVENT ("dat_rrgrr_reconnect_dcch_cnf()");
  reconnect_dcch_cnf->reconn_state = reconn_state;
  PSENDX (GRR, reconnect_dcch_cnf);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rgrr_resumed_tbf_req            |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR-RESUMED-TBF-REQ received from GRR.
            This primitive is used by GRR to order RR to indicate the
            successful outcome of a TBF establishment at GRR.
            This is applicable during PDCH Assignment and RR Network Contolled
            Cell Change Order.
  IN      : RRGRR-RESUMED-TBF-REQ
  OUT     : MPH-IDLE-REQ and DL-RELEASE-REQ

*/
void dat_rrgrr_resumed_tbf_req( T_RRGRR_RESUMED_TBF_REQ *resumed_tbf_req )
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_resumed_tbf_req ()");

  if ( rr_data->gprs_data.tbf_est EQ TBF_EST_PDCH OR
       rr_data->gprs_data.tbf_est EQ TBF_EST_CCO     )
  {
    PALLOC (dl_release_req, DL_RELEASE_REQ);

    rr_data->gprs_data.tbf_est = TBF_EST_NONE;

    att_build_idle_req(SC_INDEX, MODE_PACKET_TRANSFER);

    /*
     * Note that also during a Cell Change Order the states DAT_PDCH* are used.
     */

    SET_STATE (STATE_GPRS, GPRS_PTM_BCCH);
    SET_STATE (STATE_DAT, DAT_PDCH_ASS_2);

    dat_code_prr_channel (&dl_release_req->ch_type,
                          &dl_release_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type);

    dl_release_req->mode = DL_NORMAL_RELEASE;
    PSENDX (DL, dl_release_req);
  }
  PFREE (resumed_tbf_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_resumed_tbf_cnf           |
+-----------------------------------------------------------------------------+

  PURPOSE : Create a primitive RGRR_RESUMED_TBF_CNF and send it to GRR.
            This indicates the successful outcome of the release of the DCCH
            which was in use before the TBF was established.
  IN      : nothing
  OUT     : RGRR-RESUMED-TBF-CNF

*/
void dat_rrgrr_resumed_tbf_cnf( void )
{
  GET_INSTANCE_DATA;
  PALLOC (rrgrr_resumed_tbf_cnf, RRGRR_RESUMED_TBF_CNF);

  TRACE_EVENT ("dat_rrgrr_resumed_tbf_cnf ()");

  SET_STATE(STATE_GPRS, GPRS_PTM_BCCH);
  SET_STATE(STATE_DAT,  DAT_IDLE);
  SET_STATE(STATE_ATT,  ATT_IDLE);

  PSENDX (GRR, rrgrr_resumed_tbf_cnf);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_change_order              |
+-----------------------------------------------------------------------------+

  PURPOSE : Handle the message RR Network Controlled Cell Change Order.
  IN      : DL-DATA-IND
  OUT     : RRGRR-DATA-IND

*/
void dat_rrgrr_change_order (T_DL_DATA_IND *dl_data_ind, T_D_CHANGE_ORDER *d_change_order)
{
  GET_INSTANCE_DATA;
  for_check_cell_descr (&d_change_order->cell_desc);   /* check if the BCCH is ok */

  if ( rr_data->ms_data.error.cs EQ 0 )   /* '0' indicates successful message decoding */
  {
    T_cell_desc *cell_desc;
    
    for_suspend_layer_2();

    if ( rr_data->gprs_data.dl_data_ind NEQ NULL )
    {
      PFREE ( rr_data->gprs_data.dl_data_ind );
    }
    rr_data->gprs_data.dl_data_ind = dl_data_ind;

    dat_att_null();
    cs_set_all();

    cell_desc = &d_change_order->cell_desc;
    rr_data->gprs_data.bsic  = (UBYTE)(( cell_desc->ncc << 3 ) + cell_desc->bcc);
    rr_data->gprs_data.arfcn = (USHORT)(( cell_desc->bcch_arfcn_hi << 8 ) +
                               cell_desc->bcch_arfcn_lo);
    TIMERSTOP(T_DEDICATED_MODE);
    rr_data->mode_after_dedi = MODE_CELL_CHANGE_ORDER;
    att_stop_dedicated();
  }
  else
  {
    MCAST (handov_fail, U_HANDOV_FAIL);
    PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_HANDOV_FAIL);

    handov_fail->msg_type = U_HANDOV_FAIL;
    handov_fail->rr_cause = RRC_PROT_UNSPECIFIED;
    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type);
    for_dat_data_req (dl_data_req);
    PFREE ( dl_data_ind );
  }
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_check_packet_access             |
+-----------------------------------------------------------------------------+

  PURPOSE : change state from conn. establishment to dedicated
  IN      :
  OUT     :

*/

BOOL dat_check_packet_access(void)
{
  GET_INSTANCE_DATA;
  if(GET_STATE(STATE_GPRS) EQ GPRS_PAM_BCCH)
  {
    SET_STATE(STATE_GPRS, GPRS_DEDI_SDCCH);
    return TRUE;
  }
  else return FALSE;
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_ask_paging_ind                 |
+-----------------------------------------------------------------------------+

  PURPOSE : Ask GRR if paging should be processed. Answer will come in
            RRGRR_RR_EST_RSP primitive

*/

void dat_ask_paging_ind (T_MPH_PAGING_IND *pag_ind)
{
  GET_INSTANCE_DATA;
  TRACE_FUNCTION ("dat_ask_paging_ind ()");

  rr_data->gprs_data.pag_dat.id_type   = pag_ind->identity_type;
  rr_data->gprs_data.pag_dat.chan_need = pag_ind->channel_needed;

  rr_data->start_cell_reselection = FALSE;
  TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection);
  /* ask GRR if paging should be processed */
  dat_rrgrr_rr_est_ind ();
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_ask_paging_ind_pa_only          |
+-----------------------------------------------------------------------------+

  PURPOSE : Ask GRR if paging should be processed. Answer will come in
            RRGRR_RR_EST_RSP primitive. Only applicable in state GPRS_PA.

*/

void dat_ask_paging_ind_pa_only (T_MPH_PAGING_IND *pag_ind)
{
  GET_INSTANCE_DATA;
  if ( GET_STATE(STATE_GPRS) EQ GPRS_PAM_BCCH AND pag_ind->channel_needed NEQ CN_PACKET )
      dat_ask_paging_ind ( pag_ind );
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_rr_est_ind                |
+-----------------------------------------------------------------------------+

  PURPOSE : Send the primitive rrgrr_est_ind to GRR.
            This primitive indicates to the GRR that an RR connection
            establishment was received from the network via paging.
            It is only a trigger.
  IN      :
  OUT     : rrgrr_rr_est_ind

*/

static void dat_rrgrr_rr_est_ind (void)
{
  PALLOC ( rrgrr_est_ind, RRGRR_RR_EST_IND );
  TRACE_EVENT ("dat_rrgrr_est_ind ()");
  PSENDX (GRR, rrgrr_est_ind);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_rr_est_req                |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_RR_EST_REQ received from GRR.
            This primitive indicates to the RR a RR connection establishment
            was received on paging channel (PCCCH or PACCH). RR has to start
            a RR connection as if it has received a connection establishment
            on CCCH.
  IN      :
  OUT     :

*/

void dat_rrgrr_rr_est_req (T_RRGRR_RR_EST_REQ *est_req)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_rr_est_req ()");

  switch(GET_STATE(STATE_GPRS))
  {
    case GPRS_PTM_BCCH:
    case GPRS_PAM_BCCH:
    case GPRS_PTM_PBCCH:
    case GPRS_PAM_PBCCH:
    case GPRS_PIM_PBCCH:
      rr_data->gprs_data.gprs_suspend = est_req->susp_req;
      rr_data->gprs_data.gprs_resump  = GPRS_RESUMPTION_ACK;

      if(est_req->non_gprs.v_non_gprs)
      {
        handle_non_gprs_param(&est_req->non_gprs);
      }

      switch(GET_STATE(STATE_GPRS))
      {
        case GPRS_PIM_BCCH:
        case GPRS_PAM_BCCH:
        case GPRS_PTM_BCCH:
          SET_STATE(STATE_GPRS, GPRS_SUSPENDED_BCCH);
          break;
        case GPRS_PIM_PBCCH:
        case GPRS_PAM_PBCCH:
        case GPRS_PTM_PBCCH:
          SET_STATE(STATE_GPRS, GPRS_SUSPENDED_PBCCH);
          break;
        default:
          break;
      }

      dat_begin_start_immediate_assign (est_req->ident_type,
                                        est_req->ch_needed);
      break;
    default:
      break;
  }
  PFREE (est_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : handle_non_gprs_param				  |
+-----------------------------------------------------------------------------+

  PURPOSE :  Processes RGRR_RR_EST_REQ  parameters   received from GRR.
  IN      :  Non GPRS parameter structure of the RRGRR_RR_EST_REQ primitive.
  OUT     :

*/

static void handle_non_gprs_param(T_non_gprs* non_gprs)
{
  GET_INSTANCE_DATA;
  rr_data->nc_data[SC_INDEX].control_descr.att            = non_gprs->att;
  rr_data->nc_data[SC_INDEX].control_descr.bs_ag_blks_res = non_gprs->bs_ag_blks_res;
  rr_data->nc_data[SC_INDEX].control_descr.ccch_conf      = non_gprs->ccch_conf;
  rr_data->nc_data[SC_INDEX].control_descr.bs_pa_mfrms    = non_gprs->bs_pa_mfrms;
  rr_data->nc_data[SC_INDEX].rach.max_retrans             = non_gprs->max_retrans;
  rr_data->nc_data[SC_INDEX].rach.tx_integer              = non_gprs->tx_integer;
  rr_data->nc_data[SC_INDEX].select_para.ms_txpwr_max_cch = non_gprs->gprs_ms_txpwr_max_cch;
  rr_data->nc_data[SC_INDEX].select_para.neci             = non_gprs->neci;
  rr_data->sc_data.cd.cell_options.pow_ctrl               = non_gprs->pwrc;

  if(non_gprs->dtx EQ 2)
    rr_data->sc_data.cd.dtx = DTX_NOT_USED;
  else
    rr_data->sc_data.cd.dtx = DTX_USED;

  rr_data->sc_data.cd.dtx_half = rr_data->sc_data.cd.dtx_full =
    rr_data->sc_data.cd.dtx;

  rr_data->sc_data.cd.cell_options.rlt                    = non_gprs->radio_link_timeout;

  if(non_gprs->ec)
    rr_data->nc_data[SC_INDEX].rach.ac &= 0x0400;
  if(non_gprs->v_T3212)
    rr_data->nc_data[SC_INDEX].control_descr.t3212        = non_gprs->T3212;
  
#ifdef REL99
  /*Copy Early Classmark Sending Control flag received in PSI2 by GRR*/
  rr_data->nc_data[SC_INDEX].c2_par.ecsc = non_gprs->ecsc;
#endif
}
/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_rr_est_rsp                |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_RR_EST_RSP received from GRR.
            This primitive indicates to the RR whether an establishment of
            RR connection is allowed or not. This primitive is an answer
            to the RRGRR_RR_EST_IND primitive.
  IN      :
  OUT     :

*/

void dat_rrgrr_rr_est_rsp (T_RRGRR_RR_EST_RSP *est_rsp)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_rr_est_rsp ()");

  rr_data->start_cell_reselection = TRUE;
  TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection);

  /* establishment allowed */
  if (est_rsp->rr_est)
  {
    rr_data->gprs_data.gprs_suspend = est_rsp->susp_req;
    rr_data->gprs_data.gprs_resump  = GPRS_RESUMPTION_ACK;
    switch(GET_STATE(STATE_GPRS))
    {
      case GPRS_PIM_BCCH:
      case GPRS_PAM_BCCH:
      case GPRS_PTM_BCCH:
        SET_STATE(STATE_GPRS, GPRS_SUSPENDED_BCCH);
        break;
      case GPRS_PIM_PBCCH:
      case GPRS_PAM_PBCCH:
      case GPRS_PTM_PBCCH:
        SET_STATE(STATE_GPRS, GPRS_SUSPENDED_PBCCH);
        break;
      default:
        break;
    }
    dat_begin_start_immediate_assign (rr_data->gprs_data.pag_dat.id_type,
                                      rr_data->gprs_data.pag_dat.chan_need);
  }

  rr_data->gprs_data.pag_dat.id_type   = 0;
  rr_data->gprs_data.pag_dat.chan_need = 0;

  PFREE (est_rsp);
}


/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_gprs_suspend_req				  |
+-----------------------------------------------------------------------------+

  PURPOSE : Builds  GPRS suspension request message.
  IN      :
  OUT     :

*/

void dat_gprs_suspend_req (void)
{
  GET_INSTANCE_DATA;
  if(rr_data->gprs_data.gprs_suspend)
  {
    /*
     * building of the GPRS Suspension Request message
     */
    MCAST (susp_req, U_GPRS_SUSP_REQ);
    PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_GPRS_SUSP_REQ);

    /*
     * set channel type and SAPI for layer 2
     */
    dat_code_prr_channel (&dl_data_req->ch_type,
                          &dl_data_req->sapi,
                          rr_data->sc_data.chan_desc.chan_type);
    susp_req->msg_type = U_GPRS_SUSP_REQ;

    /*
     * store tlli independent from the used binary format
     */
    susp_req->ded_tlli.l_ded_tlli = 32;
    susp_req->ded_tlli.o_ded_tlli = 0;
    ccd_codeByte (susp_req->ded_tlli.b_ded_tlli, 0,  8,
                  (UBYTE)(rr_data->gprs_data.tlli >> 24));
    ccd_codeByte (susp_req->ded_tlli.b_ded_tlli, 8,  8,
                  (UBYTE)(rr_data->gprs_data.tlli >> 16));
    ccd_codeByte (susp_req->ded_tlli.b_ded_tlli, 16, 8,
                  (UBYTE)(rr_data->gprs_data.tlli >> 8));
    ccd_codeByte (susp_req->ded_tlli.b_ded_tlli, 24, 8,
                  (UBYTE) rr_data->gprs_data.tlli);


    switch(rr_data->ms_data.establish_cause)
    {
      case ESTCS_SERV_REQ_BY_MM:
        susp_req->susp_cause = SUSP_C_LU;
        break;
      case ESTCS_EMRG_CAL:
      case ESTCS_CAL_REEST:
      case ESTCS_MOB_ORIG_SPCH_CAL_BY_CC:
      case ESTCS_MOB_ORIG_DATA_CAL_BY_CC:
      case ESTCS_MOB_ORIG_DATA_CAL_BY_CC_HR_SUFF:
      case ESTCS_PAGING:
        susp_req->susp_cause = SUSP_C_CALL;
        break;
      case ESTCS_MOB_ORIG_CAL_BY_SS_SMS:
        susp_req->susp_cause = SUSP_C_SMS; /* SUSP_C_SS */
        break;
      default:
        break;
    }

    memcpy(susp_req->rout_area_id.mcc,rr_data->gprs_data.current_rai.plmn.mcc, SIZE_MCC);
    memcpy(susp_req->rout_area_id.mnc,rr_data->gprs_data.current_rai.plmn.mnc, SIZE_MNC);
    if (susp_req->rout_area_id.mnc[2] EQ 0x0f)
      susp_req->rout_area_id.c_mnc = 2;
    else
      susp_req->rout_area_id.c_mnc = SIZE_MNC;

    susp_req->rout_area_id.rac    = rr_data->gprs_data.current_rai.rac;
    susp_req->rout_area_id.lac    = rr_data->gprs_data.current_rai.lac;

    rr_data->gprs_data.gprs_resump  = GPRS_RESUMPTION_NOT_ACK;
    /*
     * send to layer 2
     */
    for_dat_data_req (dl_data_req);
  }

}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : gprs_rrgrr_stop_task                |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_STOP_TASK_REQ received from GRR.
            This primitive indicates to the RR that a specific task on RR side
            should be stopped.
  IN      :
  OUT     :

*/

void gprs_rrgrr_stop_task( T_RRGRR_STOP_TASK_REQ *stop_task)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("gprs_rrgrr_stop_task");

  switch(stop_task->ctrl_task)
  {
    case RR_TASK_1:
      {
        switch(GET_STATE(STATE_GPRS))
        {
          case GPRS_PAM_BCCH:
            rr_data->start_cell_reselection = TRUE;
            TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection);
            if(stop_task->task.v_stop_ccch NEQ INVALID_MSG)
            {
              att_build_idle_req(SC_INDEX, MODE_PACKET_TRANSFER);
              TIMERSTOP(T3126);
              SET_STATE(STATE_GPRS, GPRS_PTM_BCCH);
              SET_STATE(STATE_DAT,  DAT_IDLE);
              SET_STATE(STATE_ATT,  ATT_IDLE);
              {
               PALLOC(stop_cnf, RRGRR_STOP_TASK_CNF);
               PSENDX(GRR, stop_cnf);
              }
            }
            break;
          case GPRS_PIM_BCCH:
            if(stop_task->task.v_stop_ccch NEQ INVALID_MSG)
            {
              /*
                * XXX we still have a problem if the search terminates
                * and we want to select to the HPLMN cell just in the moment
                * after we have sent the IA_DOWNLINK_IND but before receiving
                * the STOP_TASK_REQ. But we should not stop the search
                * before, because maybe the IA_DOWNLINK was not actually
                * addressing us.
                */

              if (rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI)
              {
                /*inform MM and stop everything*/
                /*
                 * send Please Retry to the MMI
                 */
                rr_data->sc_data.found_entries = 0;
                att_code_rr_abort_ind (RRCS_ABORT_CEL_SEL_FAIL);
              }
              att_build_idle_req(SC_INDEX, MODE_PACKET_TRANSFER);
              SET_STATE(STATE_GPRS, GPRS_PTM_BCCH);
              SET_STATE(STATE_DAT,  DAT_IDLE);
              SET_STATE(STATE_ATT,  ATT_IDLE);
              {
                PALLOC(stop_cnf, RRGRR_STOP_TASK_CNF);
                PSENDX(GRR, stop_cnf);
              }
            }
            /*
             * If a search is active in idle this is set to false
             * it is also set to false on sending the IA_DL to GRR
             * If the IA_DL is for us we abort the search and enter TBF
             * that means that the start_cr flag is always set to true
             * If the IA_DL is not for us then the start_cr flag should only be
             * reset if no search is ongoing.
             */
            if (rr_data->ms_data.req_mm_service NEQ FUNC_NET_SRCH_BY_MMI)
           {
              rr_data->start_cell_reselection = TRUE;
              TRACE_EVENT_P1("start_cell_reselection %d", rr_data->start_cell_reselection);
            }
            break;
          default:
            break;
        }
      }
      break;
    case LEAVE_PIM_PBCCH:
      {
        TRACE_EVENT("LEAVE PIM");
        /* stop CCCH reading if running */
        /* SET_STATE(STATE_DAT, DAT_NULL);  avoid reacting to crossing prim */
        /* stop CBCH reading if running */
        /* stop active ncell procedures */
        if (rr_data->ms_data.req_mm_service EQ FUNC_NET_SRCH_BY_MMI)
        {
          /*inform MM and stop everything*/
          /*
           * send Please Retry to the MMI
           */
          rr_data->sc_data.found_entries = 0;
          att_code_rr_abort_ind (RRCS_ABORT_CEL_SEL_FAIL);
        }
        {
          PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
          mph_mon_ctrl_req->action = LEAVING_PIM_PBCCH;
          PSENDX (PL, mph_mon_ctrl_req);
        }
        {
          PALLOC(stop_cnf, RRGRR_STOP_TASK_CNF);
          PSENDX(GRR, stop_cnf);
        }
        /* XXX stop PLMN scan ?         */
      }
    break;
    case LEAVE_PAM_PBCCH:
      {
        PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
        TRACE_EVENT("LEAVE PAM");
        mph_mon_ctrl_req->action = LEAVING_PAM_PBCCH;
        PSENDX (PL, mph_mon_ctrl_req);
        {
          PALLOC(stop_cnf, RRGRR_STOP_TASK_CNF);
          PSENDX(GRR, stop_cnf);
        }
      }
    break;
    case LEAVE_PTM_PBCCH:

    {
      PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
      TRACE_EVENT("LEAVE PTM");
      mph_mon_ctrl_req->action = LEAVING_PTM_PBCCH;
      PSENDX (PL, mph_mon_ctrl_req);

      {
        PALLOC(stop_cnf, RRGRR_STOP_TASK_CNF);
        PSENDX(GRR, stop_cnf);
      }
    }
    break;
    default:
      break;

  }
  PFREE(stop_task);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_rrgrr_activate_req              |
+-----------------------------------------------------------------------------+

  PURPOSE : Process the primitive RRGRR_ACTIVATE_REQ received from GRR.
            This primitive activates RR. RR acts as if the MS is only
            GSM service mobile. Monitor CCCH and BCCH.
  IN      :
  OUT     :

*/

void dat_rrgrr_activate_req (T_RRGRR_ACTIVATE_REQ *act_req)
{
  GET_INSTANCE_DATA;
  TRACE_EVENT ("dat_rrgrr_activate_req ()");

  rr_data->gprs_data.gprs_suspend = act_req->susp_req;
  rr_data->gprs_data.rac          = act_req->rac;
  rr_data->gprs_data.gprs_resump  = GPRS_RESUMPTION_ACK;

  switch(GET_STATE(STATE_GPRS))
  {
    case GPRS_PIM_PBCCH:
    case GPRS_PAM_PBCCH:
    case GPRS_PTM_PBCCH:

       /* we need the parameters from GRR to make
        * a MO call
        */
      if(act_req->non_gprs.v_non_gprs)
      {
        handle_non_gprs_param(&act_req->non_gprs);
      }
      break;
  case GPRS_PIM_BCCH:
    /* nothing to do, just wait for MM to start with RR_ESTABLISH_REQ */
    /*SET_STATE(STATE_GPRS, GPRS_SUSPENDED_BCCH); do this on
      RR_ESTABLISH_REQ */
    break;
  case GPRS_PAM_BCCH:
  case GPRS_PTM_BCCH:
    /*
     * abort procedures we are doing for GPRS
     * and go back to idle mode to wait for the
     * RR_ESTABLISH_REQ
     */
    rr_data->gprs_data.page_mode = PAG_MODE_DEFAULT;
#ifdef REL99
#else
    att_return_to_idle();
#endif
    SET_STATE(STATE_GPRS, GPRS_PIM_BCCH);
#ifdef REL99
    att_return_to_idle();
#endif
    break;
  default:
    break;
  }

  PFREE (act_req);
}

/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_set_gprs_resump				  |
+-----------------------------------------------------------------------------+

  PURPOSE : Sets stored GPRS resumption value to the RR_RELEASE_IND primitive
			to send.
  IN      : Pointer to RR_RELEASE_IND primitive.
  OUT     :

*/

void dat_set_gprs_resump (T_RR_RELEASE_IND* rr_release_ind)
{
  GET_INSTANCE_DATA;
  rr_release_ind->gprs_resumption = rr_data->gprs_data.gprs_resump;
}



/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_gprs_set_suspended              |
+-----------------------------------------------------------------------------+

  PURPOSE : Sets state to GPRS_SUSPENDED_PBCCH or GPRS_SUSPENDED_BCCH
  IN      :
  OUT     :

*/


void dat_gprs_set_suspended(void)
{
  GET_INSTANCE_DATA;
  switch(GET_STATE(STATE_GPRS))
  {
    case GPRS_PIM_PBCCH:
    case GPRS_PAM_PBCCH:
    case GPRS_PTM_PBCCH:
      SET_STATE(STATE_GPRS, GPRS_SUSPENDED_PBCCH);
      break;
    case GPRS_PIM_BCCH:
    case GPRS_PAM_BCCH:
    case GPRS_PTM_BCCH:
      SET_STATE(STATE_GPRS, GPRS_SUSPENDED_BCCH);
      break;
    default:
      break;
  }
}

#ifdef REL99
/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (6147)     MODULE  : RR_GPRS                             |
| STATE   : code                ROUTINE : dat_gprs_set_suspended              |
+-----------------------------------------------------------------------------+

  PURPOSE : Sets state to GPRS_SUSPENDED_PBCCH or GPRS_SUSPENDED_BCCH
  IN      :
  OUT     :

*/
BOOL dat_gprs_cell_in_ptm(void)
{
  GET_INSTANCE_DATA;
  switch(GET_STATE(STATE_GPRS))
  {
    case GPRS_PTM_PBCCH:
    case GPRS_PTM_BCCH:
      return TRUE;
    default:
      return FALSE;  
  }
}
#endif

/*===========================================================================*/
/*
 *                                  L O C A L S
 */
/*===========================================================================*/
/*
+-----------------------------------------------------------------------------+
| PROJECT : GSM-GPRS (??6147)     MODULE  : RR_GPRS                           |
| STATE   : code                ROUTINE : get_r_bit                           |
+-----------------------------------------------------------------------------+

  PURPOSE : R-bit for the IA-prims
  IN      : access counter
  OUT     : r_bit

*/

static UBYTE get_r_bit (void)
{
  GET_INSTANCE_DATA;
  UBYTE r_bit;

  switch (rr_data->ms_data.access_counter)
  {
    case 0:
      r_bit = NOT_PRESENT_8BIT;
      break;
    case 1:
      r_bit = CHAN_REQ_SENT_ONCE;
      break;
    default:
      r_bit = CHAN_REQ_SENT_MORE;
      break;
  }
  return r_bit;
}

#endif /* GPRS */
#endif /* RR_DATG_C */