FreeCalypso > hg > fc-tourmaline
view src/g23m-gsm/alr2/alr_pch.c @ 287:3dee79757ae4
UI fw: load handheld audio mode on boot
We have now reached the point where use of audio mode config files
should be considered mandatory. In ACI usage we can tell users that
they need to perform an AT@AUL of some appropriate audio mode, but
in UI-enabled fw we really need to have the firmware load audio modes
on its own, so that correct audio config gets established when the
handset or development board runs on its own, without a connected host
computer.
Once have FC Venus with both main and headset audio channels and
headset plug insertion detection, our fw will need to automatically
load the handheld mode or the headset mode depending on the plug
insertion state. For now we load only the handheld mode, which has
been tuned for FC-HDS4 on FC Luna.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 13 Nov 2021 03:20:57 +0000 |
parents | 3a14ee9a9843 |
children |
line wrap: on
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