line source
/*
+-----------------------------------------------------------------------------
| Project : GSM-PS
| Modul : ALR_PCH
+-----------------------------------------------------------------------------
| Copyright 2002 Texas Instruments Berlin, AG
| All rights reserved.
|
| This file is confidential and a trade secret of Texas
| Instruments Berlin, AG
| The receipt of or possession of this file does not convey
| any rights to reproduce or disclose its contents or to
| manufacture, use, or sell anything it may describe, in
| whole, or in part, without the specific written consent of
| Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
| Purpose : This Modul defines the SDL process PCH_Control.
+-----------------------------------------------------------------------------
*/
#ifndef ALR_PCH_C
#define ALR_PCH_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"
#ifdef GPRS
#include "alr_gprs.h"
#endif
#include "alr.h"
#include "alr_em.h"
/*==== EXPORT =====================================================*/
/*==== PRIVAT =====================================================*/
/*==== VARIABLES ==================================================*/
UBYTE page_mode_before_hplmn_search = PGM_NORMAL;
/*==== CONSTANTS ==================================================*/
#define IMSI_ODD_FLAG 8
#define IMSI_EVEN_FLAG 0
#define IDENT_TYPE_MON 0
#define IDENT_TYPE_IMSI 1
#define IDENT_TYPE_IMEI 2
#define IDENT_TYPE_IMEISV 3
#define IDENT_TYPE_TMSI 4
#define END_MARK 0xF0
/*==== FUNCTIONS ==================================================*/
#define TRACING
#if defined (TRACING)
#define ALR_TRACE_PCH(a) ALR_TRACE(a)
#else
#define ALR_TRACE_PCH(a)
#endif
#ifdef TRACING
#define ALR_TRACE_PCH_CONFIG(b,a,c,t,p,m) \
TRACE_EVENT_P6 ("MFRMS: %d AG_RES: %d COMB: %d GRP: %d PGRP: %d PI: %d",b,a,c,t,p,m)
#define ALR_TRACE_PCH_PGM(p,x) \
TRACE_EVENT_P2 ("new_pgm: %d cur_pgm: %d",p,x)
#define ALR_TRACE_PCH_IMSI() \
{ for (i=0; i<alr_data->pch_data.imsi[0]+1;i++) { \
TRACE_EVENT_P2 ("imsi[%d]=%x",i,alr_data->pch_data.imsi[i]);} }
#else
#define ALR_TRACE_PCH_CONFIG(b,a,c,t,p,m)
#define ALR_TRACE_PCH_PGM(p,x)
#define ALR_TRACE_PCH_IMSI()
#endif
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_init |
+--------------------------------------------------------------------+
PURPOSE : Initialize PCH Control Process.
*/
GLOBAL void pch_init (void)
{
alr_data->pch_data.saved_page_mode = PGM_REORG;
alr_data->pch_data.reorg_bcch_reading = FALSE;
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_start |
+--------------------------------------------------------------------+
PURPOSE : Process signal pch_start from SDL process
Main_Control.
*/
static const UBYTE PAG_BLOCK_TABLE [2][8] =
{
/* not combined ccch */
9,8,7,6,5,4,3,2,
/* combined ccch */
3,2,1,1,1,1,1,1
};
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_configure |
+--------------------------------------------------------------------+
PURPOSE : Configutes L1 for paging.
*/
GLOBAL void pch_configure (T_MPH_IDLE_REQ *idle, UBYTE page_mode)
{
UBYTE pag_blocks_per_mfr;
if(idle NEQ NULL)
{
alr_data->pch_data.dlt = idle->dlt;
alr_data->pch_data.act_dlt = idle->dlt;
ALR_EM_SET_EM_ACT_DLT;
pag_blocks_per_mfr = PAG_BLOCK_TABLE [idle->comb_ccch][idle->bs_ag_blocks_res];
/*
* pl_idle.bs_pa_mfrms has a range from 2-9.
* MPH_IDLE_REQ codes them from 0-7
*/
alr_data->pch_data.pl_idle.bs_pa_mfrms = (UBYTE)(idle->bs_pa_mfrms + 2);
alr_data->pch_data.pl_idle.bs_ag_blks_res = idle->bs_ag_blocks_res;
alr_data->pch_data.pl_idle.bcch_combined = idle->comb_ccch;
alr_data->pch_data.pl_idle.ccch_group = (UBYTE)(idle->tn / 2);
alr_data->pch_data.pl_idle.page_group = idle->pg;
alr_data->pch_data.pl_idle.page_block_index = (UBYTE)(idle->pg % pag_blocks_per_mfr);
ALR_TRACE_PCH_CONFIG(idle->bs_pa_mfrms+2, idle->bs_ag_blocks_res,
idle->comb_ccch, idle->tn/2, idle->pg,
idle->pg % pag_blocks_per_mfr);
}
/*
* During cell reselection reading of PCH is started hard coded with
* page mode PGM_REORG because of the lack of parameters to calculate
* the right paging group. Detection of SI3 during cell reselection
* triggers the function pch_config_resel() to reconfigure PCH reading,
* detection of a changed page mode during cell reselection is handled
* by function pch_check_page_mode_cr() which needs to know whether SI3
* is read
*/
if (GET_STATE (STATE_MA) EQ MA_CELL_RESELECTION)
alr_data->pch_data.si3_read = FALSE;
/* Ensure that L1 does not get initialised with PAGING EXTENDED */
switch( page_mode )
{
case SAVED_PGM:
if( alr_data->pch_data.saved_page_mode EQ PGM_EXTENDED )
{
alr_data->pch_data.saved_page_mode = PGM_REORG;
}
page_mode = alr_data->pch_data.saved_page_mode;
/*lint -fallthrough*/
default:
alr_data->pch_data.pl_idle.page_mode = page_mode;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_save_pgm |
+--------------------------------------------------------------------+
PURPOSE : Configure Paging
*/
GLOBAL void pch_save_pgm(UBYTE mode)
{
if(mode)
alr_data->pch_data.saved_page_mode = mode;
else
alr_data->pch_data.saved_page_mode = alr_data->pch_data.pl_idle.page_mode;
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_start_ccch_req |
+--------------------------------------------------------------------+
PURPOSE : Configure Paging
*/
GLOBAL void pch_start_ccch_req (void)
{
PALLOC(pl_idle, MPHC_START_CCCH_REQ);
memset(pl_idle, 0, sizeof(T_MPHC_START_CCCH_REQ));
ALR_EM_PAGE_MODE_CHANGE;
switch (alr_data->pch_data.pl_idle.page_mode)
{
case PGM_REORG:
ALR_TRACE_PCH ("config REORG");
/* dummy values */
pl_idle->bs_pa_mfrms = 2;
pl_idle->bs_ag_blks_res = 7;
pl_idle->bcch_combined = 0;
pl_idle->ccch_group = 0;
pl_idle->page_group = 0;
pl_idle->page_block_index = 0;
pl_idle->page_mode = PGM_REORG;
break;
case PGM_REORG_CS:
ALR_TRACE_PCH ("config REORG_CS");
memcpy (pl_idle, &alr_data->pch_data.pl_idle,
sizeof (T_MPHC_START_CCCH_REQ));
/*
* if the page_mode is PGM_REORG_CS then
* we have to change this to PGM_REORG
* before we send it to L1
*/
pl_idle->page_mode = PGM_REORG;
break;
case PGM_EXTENDED:
ALR_TRACE_PCH ("config EXT");
memcpy (pl_idle, &alr_data->pch_data.pl_idle,
sizeof (T_MPHC_START_CCCH_REQ));
pl_idle->page_mode = PGM_EXTENDED;
break;
case PGM_REORG_NC_SYNC:
/*this case is the same as the default - except for the TRACE*/
ALR_TRACE_PCH ("config PGM_REORG_NC_SYNC (NORMAL)");
memcpy (pl_idle, &alr_data->pch_data.pl_idle,
sizeof (T_MPHC_START_CCCH_REQ));
pl_idle->page_mode = PGM_NORMAL;
break;
default:
ALR_TRACE_PCH ("config NORMAL");
memcpy (pl_idle, &alr_data->pch_data.pl_idle,
sizeof (T_MPHC_START_CCCH_REQ));
pl_idle->page_mode = PGM_NORMAL;
break;
}
SET_STATE(STATE_PCH,PCH_ACTIVE);
ma_pch_start_ccch_req(pl_idle);
TRACE_EVENT_P1("reorg_bcch_reading = %d",alr_data->pch_data.reorg_bcch_reading);
if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR
alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS OR
alr_data->pch_data.reorg_bcch_reading EQ TRUE)
{ /*
* if we're going into reorg paging we also need to read the BCCH
* to read possibly changed channel configuration
* XXX but not at PGM_REORG_NC_SYNC (NORMAL)
*/
ma_scell_full_nbcch();
}
else
{ /*
* otherwise we stop the reading of the BCCH and start the periodic read.
* XXX but not if we have a PBCCH
*/
#ifdef GPRS
if(alr_data->gprs_data.pbcch EQ FALSE)
#endif
sc_start_periodic();
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_identity_req |
+--------------------------------------------------------------------+
PURPOSE : Get new mobile identity information from RR. Build IMSI
pattern and store TMSI.
*/
GLOBAL void pch_identity_req (T_MPH_IDENTITY_REQ *mph_identity_req)
{
UBYTE i;
/* the IMSI in the identity request is coded as a 15byte long array
and is stored for later usage in pch_data as the message representation
of the IMSI according to GSM4.08 10.5.1.4 */
if (mph_identity_req->mid.len_imsi EQ 0)
{
/*
* limited service, no paging
*/
memset (alr_data->pch_data.imsi, 0, IMSI_LEN);
alr_data->pch_data.v_tmsi = FALSE;
alr_data->pch_data.tmsi = 0L;
}
else
{
/*
* The IMSI is available
*/
/* store length */
alr_data->pch_data.imsi[0] = (UBYTE)((mph_identity_req->mid.len_imsi + 2) / 2);
if (mph_identity_req->mid.len_imsi & 1)
{
ALR_TRACE_PCH ("IMSI is odd");
/*
* odd number of digits
* first digit + odd flag + identity type IMSI
*/
alr_data->pch_data.imsi[1] = (UBYTE)((mph_identity_req->mid.imsi[0] << 4) +
IMSI_ODD_FLAG +
IDENT_TYPE_IMSI);
}
else
{
ALR_TRACE_PCH ("IMSI is even");
/*
* even number of digits
* first digit + even flag + identity type IMSI
*/
alr_data->pch_data.imsi[1] = (UBYTE)((mph_identity_req->mid.imsi[0] << 4) +
IMSI_EVEN_FLAG +
IDENT_TYPE_IMSI);
}
/*
* fill in the rest of digits
*/
for (i=1;i<mph_identity_req->mid.len_imsi;i++)
{
if (i & 1)
alr_data->pch_data.imsi[(i/2)+2] = (UBYTE)(END_MARK + mph_identity_req->mid.imsi[i]);
else
{
alr_data->pch_data.imsi[(i/2)+1] &= ~END_MARK; /* remove end mark */
alr_data->pch_data.imsi[(i/2)+1] = (UBYTE)(alr_data->pch_data.imsi[(i/2)+1] +
(mph_identity_req->mid.imsi[i] << 4));
}
}
alr_data->pch_data.imsi_mod_1000 = (SHORT)
( (mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-1] +
mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-2] * 10 +
mph_identity_req->mid.imsi[mph_identity_req->mid.len_imsi-3] * 100 ) % 1000);
ALR_TRACE_PCH_IMSI();
/*
* copy TMSI
*/
alr_data->pch_data.v_tmsi = mph_identity_req->mid.v_tmsi;
alr_data->pch_data.tmsi = mph_identity_req->mid.tmsi;
#ifdef GPRS
gprs_alr_store_ptmsi(mph_identity_req->mid.v_ptmsi,
mph_identity_req->mid.ptmsi);
gprs_alr_store_ptmsi2(mph_identity_req->mid.v_ptmsi2,
mph_identity_req->mid.ptmsi2);
#endif
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_increment_dlt |
+--------------------------------------------------------------------+
PURPOSE : Incrementation of downlink timeout counter after receiving
a valid PCH block.
*/
GLOBAL void pch_increment_dlt (void)
{
if (alr_data->pch_data.act_dlt <
alr_data->pch_data.dlt)
{
#if !defined NTRACE
trc_mon_counter_idle (alr_data->pch_data.act_dlt,
alr_data->pch_data.dlt);
#endif /* (!defined NTRACE) */
alr_data->pch_data.act_dlt++;
ALR_EM_SET_EM_ACT_DLT;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_decrement_dlt |
+--------------------------------------------------------------------+
PURPOSE : Decrementation of downlink timeout counter after receiving
an invalid PCH block.
*/
GLOBAL void pch_decrement_dlt (void)
{
if (alr_data->pch_data.act_dlt > 4)
{
#if !defined NTRACE
trc_mon_counter_idle (alr_data->pch_data.act_dlt,
alr_data->pch_data.dlt);
#endif /* (!defined NTRACE) */
alr_data->pch_data.act_dlt -= 4;
ALR_EM_SET_EM_ACT_DLT;
}
else
{
alr_data->pch_data.act_dlt = alr_data->pch_data.dlt;
#if !defined NTRACE
trc_mon_counter_idle (alr_data->pch_data.act_dlt,
alr_data->pch_data.dlt);
#endif
ALR_EM_SET_EM_ACT_DLT;
ALR_TRACE_PCH ("downlink fail");
ma_error_ind (CS_DOWN_LINK_FAIL, alr_data->serving_cell);
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_check_page_mode |
+--------------------------------------------------------------------+
PURPOSE : Check the page mode of an incoming unacknowledged
message.
*/
static const UBYTE PAGE_MODE_CHANGE [3][4] =
{
/* old mode = paging normal */
NONE, SWAP_TO_EXTEND, SWAP_TO_REORG, NONE,
/* old mode = extended paging */
SWAP_TO_NORMAL, NONE, SWAP_TO_REORG, NONE,
/* old mode = paging reorganisation */
SWAP_TO_NORMAL, SWAP_TO_EXTEND, NONE, NONE
};
GLOBAL void pch_check_page_mode (T_MPHC_DATA_IND *data_ind)
{
UBYTE page_mode;
UBYTE cur_page_mode = alr_data->pch_data.pl_idle.page_mode;
page_mode = (UBYTE)(data_ind->l2_frame.content [3] & 3);
ALR_TRACE_PCH_PGM(page_mode, alr_data->pch_data.pl_idle.page_mode);
/*if HPLMN search is going on and we should be in REORG, we are really
in REORG_NC_SYNC (NORMAL). Otherwise we cannot synchronize to the NC's*/
if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_NC_SYNC)
cur_page_mode = PGM_REORG;
if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS)
cur_page_mode = PGM_REORG;
switch (PAGE_MODE_CHANGE [cur_page_mode][page_mode])
{
case SWAP_TO_NORMAL:
ALR_TRACE_PCH ("SWAP_TO_NORMAL");
alr_data->pch_data.pl_idle.page_mode = PGM_NORMAL;
pch_start_ccch_req ();
break;
case SWAP_TO_EXTEND:
ALR_TRACE_PCH ("SWAP_TO_EXT");
alr_data->pch_data.pl_idle.page_mode = PGM_EXTENDED;
pch_start_ccch_req ();
break;
case SWAP_TO_REORG:
ALR_TRACE_PCH ("SWAP_TO_REORG");
alr_data->pch_data.reorg_bcch_reading = TRUE;
alr_data->pch_data.si_bitmap = 0;
alr_data->pch_data.pl_idle.page_mode = PGM_REORG_CS;
pch_start_ccch_req ();
break;
default:
break;
}
}
GLOBAL void pch_check_page_mode_cr (T_MPHC_DATA_IND *data_ind)
{
UBYTE page_mode;
UBYTE cur_page_mode = alr_data->pch_data.saved_page_mode;
UBYTE swap = TRUE;
page_mode = (UBYTE)(data_ind->l2_frame.content [3] & 3);
if(alr_data->pch_data.saved_page_mode EQ PGM_REORG_CS)
cur_page_mode = PGM_REORG;
switch (PAGE_MODE_CHANGE [cur_page_mode][page_mode])
{
case SWAP_TO_NORMAL:
ALR_TRACE_PCH ("CR:SWAP_TO_NORMAL");
alr_data->pch_data.saved_page_mode = PGM_NORMAL;
break;
case SWAP_TO_EXTEND:
ALR_TRACE_PCH ("CR:SWAP_TO_EXT");
alr_data->pch_data.saved_page_mode = PGM_EXTENDED;
break;
case SWAP_TO_REORG:
ALR_TRACE_PCH ("CR:SWAP_TO_REORG");
alr_data->pch_data.saved_page_mode = PGM_REORG_CS;
break;
default:
swap = FALSE;
break;
}
if (swap AND alr_data->pch_data.si3_read AND
alr_data->pch_data.last_start_ccch_req.bs_pa_mfrms NEQ NOT_PRESENT_8BIT)
{
PALLOC(pl_idle, MPHC_START_CCCH_REQ);
memcpy ( pl_idle,
&(alr_data->pch_data.last_start_ccch_req),
sizeof(T_MPHC_START_CCCH_REQ));
pl_idle->page_mode = alr_data->pch_data.saved_page_mode;
ma_pch_start_ccch_req (pl_idle);
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_check_pag_1 |
+--------------------------------------------------------------------+
PURPOSE : The function checks a paging request type 1 message.
*/
GLOBAL void pch_check_pag_1 (T_MPHC_DATA_IND *data_ind)
{
UBYTE *frame = data_ind->l2_frame.content;
ULONG tmsi;
UBYTE i;
UBYTE channel_needed;
UBYTE *frame_start = data_ind->l2_frame.content;
//ALR_TRACE_PCH ("p1");
/*
* Check only if IMSI available (len NEQ 0),
* ti and pd = 0x06 and
* l2 pseudolength is greater than 5 bytes
*/
if (alr_data->pch_data.imsi[0] AND
frame[1] EQ 0x06 AND
frame[0] > 0x15)
{
/*
* store channel needed type
*/
channel_needed = frame[3];
/*
* check type of identity for mobile identity 1
*/
switch (frame [5] & 7)
{
case 1:
//ALR_TRACE_PCH ("p1 IMSI");
/*
* IMSI
*/
if (!memcmp (alr_data->pch_data.imsi, &frame[4],
alr_data->pch_data.imsi[0]+1))
{
//ALR_TRACE_PCH ("p1 IMSI match");
/*
* IMSI matches
*/
#ifdef GPRS
if(!gprs_alr_check_packet_paging(frame_start,1))
#endif
ma_pch_paging_ind (1, (UBYTE)((channel_needed & 0x30)>>4));
#ifdef GPRS
else if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
ma_pch_paging_ind (ID_IMSI, CN_PACKET);
#endif
return;
}
break;
case 4:
//ALR_TRACE_PCH ("p1 TMSI");
/*
* TMSI
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<frame[4]-1;i++)
tmsi += frame[i+6] << ((8*(frame[4]-2-i)));
if (alr_data->pch_data.tmsi EQ tmsi)
{
//ALR_TRACE_PCH ("p1 TMSI match");
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0x30)>>4));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<frame[4]-1;i++)
tmsi += frame[i+6] << ((8*(frame[4]-2-i)));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
break;
}
/*
* check type of identity for mobile identity 2
* set frame pointer to start of mobile identity 2 (id tag)
* old frame pointer (frame) +
* offset pseudo length etc (4) +
* length mobile identity 1 (frame [4]) +
* plus 1 byte for length field
*/
frame = frame + 4 + frame[4] + 1;
if (frame[0] EQ 0x17)
{
/*
* mobile identity 2 is available
*/
switch (frame [2] & 7)
{
case 1:
//ALR_TRACE_PCH ("p1 IMSI2");
/*
* IMSI
*/
if (!memcmp (alr_data->pch_data.imsi, &frame[1],
alr_data->pch_data.imsi[0]+1))
{
//ALR_TRACE_PCH ("p1 IMSI2 match");
/*
* IMSI matches
*/
#ifdef GPRS
if(! gprs_alr_check_packet_paging(frame_start,2))
#endif
ma_pch_paging_ind (1, (UBYTE)((channel_needed & 0xC0)>>6));
#ifdef GPRS
else if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
ma_pch_paging_ind (ID_IMSI, CN_PACKET);
#endif
return;
}
break;
case 4:
// ALR_TRACE_PCH ("p1 TMSI2");
/*
* TMSI
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<frame[1]-1;i++)
tmsi += frame[i+3] << ((8*(frame[1]-2-i)));
if (alr_data->pch_data.tmsi EQ tmsi)
{
ALR_TRACE_PCH ("p1 IMSI2");
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0xC0)>>6));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<frame[4]-1;i++)
tmsi += frame[i+6] << ((8*(frame[4]-2-i)));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
break;
}
}
}
//ALR_TRACE_PCH("end p1");
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_check_pag_2 |
+--------------------------------------------------------------------+
PURPOSE : The function checks a paging request type 2 message.
*/
GLOBAL void pch_check_pag_2 (T_MPHC_DATA_IND *data_ind)
{
UBYTE *frame = data_ind->l2_frame.content;
ULONG tmsi;
UBYTE i;
UBYTE channel_needed;
/*
* Check only if IMSI available (len NEQ 0) and
* ti and pd = 0x06 and
* l2 pseudolength is greater than 5 bytes
*/
if (alr_data->pch_data.imsi[0] AND
frame[1] EQ 0x06 AND
frame[0] > 0x15)
{
/*
* store channel needed type
*/
channel_needed = frame[3];
/*
* check mobile identity 1 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+4] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0x30)>>4));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+4] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
/*
* check mobile identity 2 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+8] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0xC0)>>6));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+8] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
if (frame[12] EQ 0x17)
{
/*
* mobile identity 3 is available
* calculation of channel needed for
* mobile identity 3 from the rest octet.
*/
channel_needed = frame [ frame[13]+14 ];
if (channel_needed & 0x80)
channel_needed = (UBYTE)((channel_needed >> 5) & 3);
else
channel_needed = 0;
switch (frame [14] & 7)
{
case 1:
/*
* IMSI
*/
if (!memcmp (alr_data->pch_data.imsi, &frame[13],
alr_data->pch_data.imsi[0]+1))
{
/*
* IMSI matches
*/
#ifdef GPRS
if(! gprs_alr_check_packet_paging_2(frame,3))
#endif
ma_pch_paging_ind (1, (UBYTE) channel_needed);
#ifdef GPRS
else if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
ma_pch_paging_ind (ID_IMSI, CN_PACKET);
#endif
return;
}
break;
case 4:
/*
* TMSI
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<frame[13]-1;i++)
tmsi += frame[i+15] << ((8*(frame[13]-2-i)));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, channel_needed);
return;
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<frame[13]-1;i++)
tmsi += frame[i+15] << ((8*(frame[13]-2-i)));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
}
break;
}
}
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_check_pag_3 |
+--------------------------------------------------------------------+
PURPOSE : The function checks a paging request type 3 message.
*/
GLOBAL void pch_check_pag_3 (T_MPHC_DATA_IND *data_ind)
{
UBYTE *frame = data_ind->l2_frame.content;
ULONG tmsi;
UBYTE i;
UBYTE channel_needed;
/*
* Check only if IMSI available (len NEQ 0) and
* ti and pd = 0x06 and
* l2 pseudolength is greater than 5 bytes
*/
if (alr_data->pch_data.imsi[0] AND
frame[1] EQ 0x06 AND
frame[0] > 0x15)
{
/*
* store channel needed type
*/
channel_needed = frame[3];
/*
* check mobile identity 1 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+4] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0x30)>>4));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+4] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
/*
* check mobile identity 2 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+8] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)((channel_needed & 0xC0)>>6));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+8] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
/*
* calculation of channel needed for
* mobile identity 3 and 4 from the rest octet.
*/
channel_needed = frame [ 20 ];
if (channel_needed & 0x80)
channel_needed = (UBYTE)((channel_needed & 0x78) >> 3);
else
channel_needed = 0;
/*
* check mobile identity 3 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+12] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)(channel_needed >> 2));
return;
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+12] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
}
/*
* check mobile identity 4 only if TMSI is available
*/
if (alr_data->pch_data.v_tmsi)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+16] << (8*(3-i));
if (alr_data->pch_data.tmsi EQ tmsi)
{
/*
* TMSI matches
*/
ma_pch_paging_ind (4, (UBYTE)(channel_needed & 3));
return;
}
}
#ifdef GPRS
if(GET_STATE(STATE_MA) NEQ MA_CON_EST)
{
tmsi = 0L;
for (i=0;i<4;i++)
tmsi += frame[i+16] << (8*(3-i));
if(gprs_alr_check_ptmsi(tmsi)) return;
}
#endif
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_stop |
+--------------------------------------------------------------------+
PURPOSE : The function stops paging.
*/
GLOBAL void pch_stop(void)
{
if(GET_STATE(STATE_PCH) EQ PCH_ACTIVE)
{
SET_STATE(STATE_PCH,PCH_NULL);
if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR
alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS)
{
ALR_TRACE_PCH ("stop sc for pch");
ma_stop_scell_bcch_req();
}
ma_pch_stop();
}
}
/*used for S13 - to stop BCCH reading*/
GLOBAL UBYTE pch_mode_reorg(void)
{
if(alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG OR
alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_CS OR
alr_data->pch_data.pl_idle.page_mode EQ PGM_REORG_NC_SYNC)
return TRUE;
else
return FALSE;
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_no_of_paging_blocks |
+--------------------------------------------------------------------+
PURPOSE : The function configures the paging reading during cell
reselection when reveived a SI3
*/
LOCAL SHORT pch_no_of_paging_blocks (UBYTE ccch_conf,
UBYTE bs_ag_blks_res,
UBYTE bs_pa_mfrms)
{
/* in according to GSM 4.08 section 10.5.2.11, table 10.5.33 */
if (ccch_conf EQ COMB_CCCH_COMB)
{
/*
* combined CCCH,
*
* number of paging blocks = (3 - BS_AG_BLKS_RES) * BS_PA_MFRMS
*
* Maximum function only for security reasons, BCCH coding range is 0..7,
* but allowed is only 0..2.
*/
return (( (1 > (UBYTE)(3 - bs_ag_blks_res) ? 1 : (UBYTE)(3 - bs_ag_blks_res)) ) *
((UBYTE)(2 + bs_pa_mfrms)));
}
else
{
/*
* non-combined CCCH,
*
* number of paging blocks = (9 - BS_AG_BLKS_RES) * BS_PA_MFRMS
*/
return ((9 - bs_ag_blks_res) *
(2 + bs_pa_mfrms));
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : GSM-PS (6103) MODULE : ALR_PCH |
| STATE : code ROUTINE : pch_config_resel |
+--------------------------------------------------------------------+
PURPOSE : The function configures the L1 PCH reading during cell
reselection when reveived an SI3
*/
GLOBAL void pch_config_resel (T_MPHC_DATA_IND *data_ind)
{
UBYTE *p_ctrl = &(data_ind->l2_frame.content[SI_CONTENTS_MSG_T+8]);
UBYTE ccch_conf,
bs_ag_blks_res,
bs_pa_mfrms,
pg,
pag_blocks_per_mfr;
SHORT n, b;
PALLOC(pl_idle, MPHC_START_CCCH_REQ);
memset(pl_idle, 0, sizeof(T_MPHC_START_CCCH_REQ));
bs_ag_blks_res = (UBYTE)(((*p_ctrl) & 0x38) >> 3);
ccch_conf = (((*p_ctrl) & 0x07) EQ 0x01) ? COMB_CCCH_COMB : COMB_CCCH_NOT_COMB;
p_ctrl++;
bs_pa_mfrms = (UBYTE)(((*p_ctrl) & 0x07));
/* TRACE_EVENT_P5("pch_config_resel IE: %02x %02x bs_ag_blks_res=%u ccch_conf=%u bs_pa_mfrms=%u",
data_ind->l2_frame.content[SI_CONTENTS_MSG_T+8],
*p_ctrl,
bs_ag_blks_res,
ccch_conf,
bs_pa_mfrms);*/
n = pch_no_of_paging_blocks (ccch_conf, bs_ag_blks_res, bs_pa_mfrms);
b = ((ccch_conf / 2) + 1) * n;
pg = (UBYTE) ((alr_data->pch_data.imsi_mod_1000 % b) % n);
pag_blocks_per_mfr = PAG_BLOCK_TABLE [ccch_conf][bs_ag_blks_res];
pl_idle->bs_ag_blks_res = bs_ag_blks_res;
pl_idle->bs_pa_mfrms = (UBYTE)(bs_pa_mfrms + 2);
pl_idle->bcch_combined = ccch_conf;
pl_idle->ccch_group = (UBYTE) ((alr_data->pch_data.imsi_mod_1000 % b) / n);
pl_idle->page_group = pg;
pl_idle->page_block_index = (UBYTE)(pg % pag_blocks_per_mfr);
pl_idle->page_mode = (alr_data->pch_data.saved_page_mode EQ PGM_REORG_CS)
? PGM_REORG
: alr_data->pch_data.saved_page_mode;
/* TRACE_EVENT_P3("n=%u b=%u page_mode=%u", n, b, pl_idle->page_mode);*/
ma_pch_start_ccch_req(pl_idle);
alr_data->pch_data.si3_read = TRUE;
}
#endif