FreeCalypso > hg > fc-tourmaline
view src/g23m-gsm/rr/rr_attp.c @ 303:f76436d19a7a default tip
!GPRS config: fix long-standing AT+COPS chance hanging bug
There has been a long-standing bug in FreeCalypso going back years:
sometimes in the AT command bring-up sequence of an ACI-only MS,
the AT+COPS command would produce only a power scan followed by
cessation of protocol stack activity (only L1 ADC traces), instead
of the expected network search sequence. This behaviour was seen
in different FC firmware versions going back to Citrine, and seemed
to follow some law of chance, not reliably repeatable.
This bug has been tracked down and found to be specific to !GPRS
configuration, stemming from our TCS2/TCS3 hybrid and reconstruction
of !GPRS support that was bitrotten in TCS3.2/LoCosto version.
ACI module psa_mms.c, needed only for !GPRS, was missing in the TCS3
version and had to be pulled from TCS2 - but as it turns out,
there is a new field in the MMR_REG_REQ primitive that needs to be
set correctly, and that psa_mms.c module is the place where this
initialization needed to be added.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 08 Jun 2023 08:23:37 +0000 |
parents | fa8dc04885d8 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This module defines the functions for the attachment | capability of the module Radio Resource. +----------------------------------------------------------------------------- */ #ifndef RR_ATTP_C #define RR_ATTP_C #define ENTITY_RR /*==== INCLUDES ===================================================*/ #include <string.h> #include <stdlib.h> #include <stddef.h> /* offsetof */ #include "typedefs.h" #include "pcm.h" #include "pconst.cdg" #include "mconst.cdg" #include "message.h" #include "ccdapi.h" #include "vsi.h" #include "custom.h" #include "gsm.h" #include "prim.h" #include "cnf_rr.h" #include "tok.h" #include "rr.h" #include "rr_em.h" #include "cl_shrd.h" #if defined (_SIMULATION_) #include <stdio.h> #endif /*==== EXPORT =====================================================*/ /*==== PRIVATE =====================================================*/ /*==== PROTOTYPES =================================================*/ LOCAL void att_align_sc_meas (T_MPH_MEASUREMENT_IND * mph_meas_ind, UBYTE index); /*==== VARIABLES ==================================================*/ /* * ------------------------------------------------------------------- * PRIMITIVE Processing functions * ------------------------------------------------------------------- */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_error_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MPH_ERROR_IND received from PL. */ #define MAX_ERROR_CS 9 #define MAX_ERROR_IDLE 4 GLOBAL void att_mph_error_ind (T_MPH_ERROR_IND *mph_error_ind) { GET_INSTANCE_DATA; UBYTE index; TRACE_FUNCTION ("att_mph_error_ind()"); switch (GET_STATE (STATE_ATT)) { case ATT_CS2: /* * during cell selection */ switch (mph_error_ind->cs) { case CS_BCCH_READ_ERROR: /* * BCCH read error */ rr_data->bcch_error++; if (rr_data->bcch_error EQ MAX_ERROR_CS) { /* * maximum of BCCH read errors reached * start next sync request if possible */ rr_data->bcch_error = 0; srv_clear_list (&rr_data->cr_data.cd.ncell_list); if (cs_sync_next ()) { SET_STATE (STATE_ATT, ATT_CS1); } break; } break; case CS_DOWN_LINK_FAIL: /* * downlink failure, * layer 1 has received too many undecodable paging messages * that means the synchronisation to the BS is lost */ TRACE_EVENT ("downlink failure"); EM_DOWNLINK_FAILURE; /* * stop the controlling timer */ TIMERSTOP (T_RESELECT); /* * start cell selection, actually its questionable * if this ever happens, maybe except for the primitive crossing * case */ /*XY:n don't inform GRR, but call start_cs anyway */ #ifdef GPRS att_start_cell_selection_gprs ((UBYTE)(rr_data->sc_data.mm_started),FULL_SEARCH_MODE); #else att_start_cell_selection (rr_data->sc_data.mm_started, CS_NOT_PARALLEL,FULL_SEARCH_MODE); #endif break; } break; case ATT_CS3: /* * during cell reselection */ switch (mph_error_ind->cs) { case CS_BCCH_READ_ERROR: /* * BCCH read error */ rr_data->bcch_error++; TRACE_EVENT_P2 ("bcch_error=%u (%u)", rr_data->bcch_error, MAX_ERROR_CS); if (rr_data->bcch_error EQ MAX_ERROR_CS) { /* * the maximum of read errors is reached * try the next cell for cell reselection */ #ifdef GPRS if(rr_data->gprs_data.cr_pbcch_active EQ TRUE) { att_cell_reselection_gprs_failed(); } else { #endif rr_data->bcch_error = 0; rr_data->pag_rec = FALSE; srv_clear_stored_prim (MPH_PAGING_IND); att_continue_cell_reselect (); #ifdef GPRS } #endif } break; case CS_DOWN_LINK_FAIL: /* * downlink failure, * layer 1 has received too many undecodable paging messages * that means the synchronisation to the BS is lost */ TRACE_EVENT ("downlink failure"); EM_DOWNLINK_FAILURE; /* * try the next candidate for the cell reselection */ att_continue_cell_reselect () ; break; case CS_NC_SYNC_FAILED: /* * Cell has no valid synchronization information */ TRACE_EVENT ("No Valid Sync info"); /* * try the next candidate for the cell reselection */ att_continue_cell_reselect () ; break; } break; case ATT_DEDICATED: /* * during dedicated mode */ switch (mph_error_ind->cs) { case CS_RADIO_LINK_FAIL: /* * radio link failure. * That means layer 1 has received too many * undecodable SACCH blocks in the downlink * The synchronisation to the BS is lost. */ TRACE_EVENT ("radio link failure"); /* * dynamic configuration command : IHO * Lock the DUT to the cell it is already camping - * Ignore the Radio Link Failures. */ if(rr_data->dyn_config.iho AND (rr_data->sc_data.ch_mode EQ CM_AMR)) { TRACE_EVENT("MPH_ERROR_IND : IHO"); } else { EM_RADIO_LINK_FAILURE; rr_data->net_lost = TRUE; /* * Inform MM about the radio link failure and * start cell reslection */ att_code_rr_abort_ind (RRCS_ABORT_RAD_LNK_FAIL); att_stop_dedicated(); } break; } break; case ATT_IDLE: case ATT_CON_EST: /* * during idle mode or connection establishment */ switch (mph_error_ind->cs) { case CS_BCCH_READ_ERROR: /* * A BCCH read error has occured. * It is checked whether the BCCH reading * is done for a PLMN search activity * originated by RR, else it is ignored. */ index = att_get_index (mph_error_ind->arfcn); if (index EQ CR_INDEX) { rr_data->bcch_error++; if (rr_data->bcch_error EQ MAX_ERROR_IDLE) { /* * if the maximum of read errors is reached * the next cell is tried. */ rr_data->bcch_error = 0; TIMERSTOP (T_RESELECT); srv_clear_list (&rr_data->cr_data.cd.ncell_list); cs_sync_next (); } break; } break; case CS_DOWN_LINK_FAIL: /* * downlink failure */ TRACE_EVENT ("downlink failure"); EM_DOWNLINK_FAILURE; rr_data->net_lost = TRUE; if(GET_STATE (STATE_ATT) EQ ATT_CON_EST) { switch (rr_data->ms_data.establish_cause) { #ifdef GPRS case ESTCS_GPRS_1P: case ESTCS_GPRS_SB: case ESTCS_GPRS_PAGING: SET_STATE(STATE_GPRS, GPRS_PIM_BCCH); break; case ESTCS_PAGING: dat_rr_release_ind(RRCS_ABNORM_UNSPEC, 0); #else case ESTCS_PAGING: #endif break; default: dat_rr_release_ind(RRCS_ABNORM_UNSPEC, 0); break; } } /* * Only start reselection, if isnīt any PLMN search active */ if (rr_data->start_cell_reselection) { /*XY:n inform GRR, and wait for CR_RSP should only happen in PIM_BCCH */ #ifdef GPRS att_start_cell_reselection_gprs (CELL_RESELECTION); #else att_start_cell_reselection (CELL_RESELECTION); #endif } break; } break; default: break; } PFREE (mph_error_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_sync_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MPH_SYNC_IND received from PL. */ GLOBAL void att_mph_sync_ind (T_MPH_SYNC_IND *mph_sync_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_mph_sync_ind()"); switch (GET_STATE (STATE_ATT)) { case ATT_CS2: case ATT_CS3: if (mph_sync_ind->cs EQ CS_SYS_INFO_1_NOT_NEEDED) { /* * layer 1 indicates that system information message type 1 * is not available. Update the bitmap of the read messages. */ att_set_sys_info_read (SYS_INFO_1_READ, CR_INDEX); } #ifdef GPRS else if(mph_sync_ind->cs EQ CS_SCELL_IS_SYNCED) { if(rr_data->gprs_data.cr_pbcch_active) { PALLOC(sync_ind, RRGRR_SYNC_IND); sync_ind->sync_res = SYNC_OK; PSENDX(GRR, sync_ind); SET_STATE(STATE_GPRS,GPRS_PIM_PBCCH); rr_data->gprs_data.cr_pbcch_active = FALSE; rr_data->nc_data[CR_INDEX].arfcn = NOT_PRESENT_16BIT; SET_STATE (STATE_ATT, ATT_IDLE); } } #endif break; #ifdef GPRS case ATT_IDLE: { T_GPRS_DATA *gprs_data = &rr_data->gprs_data; T_RRGRR_EXT_MEAS_REQ *rrgrr_ext_meas_req = gprs_data->rrgrr_ext_meas_req; T_RRGRR_EXT_MEAS_CNF *rrgrr_ext_meas_cnf = gprs_data->rrgrr_ext_meas_cnf; if ( mph_sync_ind->cs EQ CS_STOP_PLMN_SEARCH AND rrgrr_ext_meas_req NEQ NULL ) { rrgrr_ext_meas_cnf->call_ref = rrgrr_ext_meas_req->call_ref; if ( gprs_data->ext_meas_ctrl & EXT_MEAS_RESET ) rrgrr_ext_meas_cnf->xmeas_cause = EXT_MEAS_RESET; else rrgrr_ext_meas_cnf->xmeas_cause = EXT_MEAS_OK; att_ext_meas_end(FALSE); SET_STATE (STATE_CELL_SEL, CS_IDLE); PSENDX ( GRR, rrgrr_ext_meas_cnf ); } } break; #endif default: break; } PFREE (mph_sync_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_measurement_ind | +--------------------------------------------------------------------+ PURPOSE : Process MPH_MEASUREMENT_IND received from layer 1. */ GLOBAL void att_mph_measurement_ind (T_MPH_MEASUREMENT_IND *mph_measurement_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_mph_measurement_ind()"); /* * Defines the time in frame numbers from the last measurements. */ rr_data->ms_data.fn_offset = (ULONG)mph_measurement_ind->fn_offset; switch (GET_STATE (STATE_ATT)) { case ATT_CS2: /* * FTA problem with 20.19 testcase * This function is used to eliminate poor serving cell * RX level values due to spurious measurements. */ #if defined(_SIMULATION_) TRACE_EVENT_WIN_P5 ("ATT_CS2: MPH_MEASUREMENT_IND[%u] rx=%d %svalid (NC%u[%u])", mph_measurement_ind->arfcn, mph_measurement_ind->rx_lev_full, mph_measurement_ind->valid ? "" : "in", SC_INDEX, rr_data->nc_data[SC_INDEX].arfcn); #endif att_align_sc_meas (mph_measurement_ind, SC_INDEX); break; case ATT_CS3: /* * clear the barrier for the candidate if exists and * update the fieldstrength value */ #if defined(_SIMULATION_) TRACE_EVENT_WIN_P5 ("ATT_CS3: MPH_MEASUREMENT_IND[%u] rx=%d %svalid (NC%u[%u])", mph_measurement_ind->arfcn, mph_measurement_ind->rx_lev_full, mph_measurement_ind->valid ? "" : "in", CR_INDEX, rr_data->nc_data[CR_INDEX].arfcn); #endif reset_tnnn (CR_INDEX); // rr_data->nc_data[CR_INDEX].rxlev = mph_measurement_ind->rx_lev_full; att_align_sc_meas (mph_measurement_ind, CR_INDEX); break; case ATT_DEDICATED: if (mph_measurement_ind->valid) { /* * if the measurement report is valid, store it * for later use (building of measurement message * and ranking of cells if coming back to idle mode). */ memcpy (&rr_data->ms_data.measurement_report, mph_measurement_ind, sizeof (T_MPH_MEASUREMENT_IND)); /*Store most recently received timing advance for SC*/ rr_data->sc_data.new_ta = rr_data->ms_data.measurement_report.otd/2; att_set_tim_advance_info(); /* * This function is used to eliminate poor serving cell * RX level values due to spurious measurements. */ att_align_sc_meas (mph_measurement_ind, SC_INDEX); /* * Set fieldstrength in dedicated mode, use rxlev sub due to DTX */ #ifdef FF_PS_RSSI RX_SetValue (mph_measurement_ind->rx_lev_sub, mph_measurement_ind->rx_qual_sub, RX_ACCE_UNAVAILABLE); #else RX_SetValue (mph_measurement_ind->rx_lev_sub); #endif } reset_tnnn (SC_INDEX); /* * increase power on time to delete forbidden * location area list after 12 hours */ att_increase_power_on_time ((USHORT)(rr_data->ms_data.fn_offset / PERIOD_1_SEC)); /* * build the uplink SACCH message Measurement Report */ #if defined (REL99) && defined (TI_PS_FF_EMR) if ( ((rr_data->sc_data.enh_para_status EQ ENH_PARA_IDLE) OR (rr_data->sc_data.enh_para_status EQ ENH_PARA_DEDICATED)) AND rr_data->sc_data.emr_data_current.rep_type EQ REP_TYPE_ENH ) dat_code_enh_measure_report (mph_measurement_ind); else #endif dat_code_measure_report (mph_measurement_ind); break; case ATT_IDLE: #ifdef GPRS #if defined (REL99) && defined (TI_PS_FF_EMR) rr_data->sc_data.emr_data_current.scale_used_last = mph_measurement_ind->scale_used; #endif if(att_check_sync_results(mph_measurement_ind)) return; #endif /* * special trick for FTA testcase 20.7. * The first paging is delayed until the * first measurement from layer 1 arrives. */ rr_data->first_meas_received = TRUE; /* * two dynamic configs to perform * fast or slow cell reselection in the lab */ if (rr_data->dyn_config.fcr) mph_measurement_ind->rx_lev_full = 0; if (rr_data->dyn_config.scr) { rr_data->dyn_config.scr++; if (rr_data->dyn_config.scr < mph_measurement_ind->rx_lev_full) mph_measurement_ind->rx_lev_full -= rr_data->dyn_config.scr; else mph_measurement_ind->rx_lev_full = 0; } if (mph_measurement_ind->valid) { /* * if the measurement report from layer 1 is valid * * set RX value */ #ifdef FF_PS_RSSI RX_SetValue (mph_measurement_ind->rx_lev_full, mph_measurement_ind->rx_qual_full, rr_data->nc_data[SC_INDEX].select_para.rxlev_access_min); #else RX_SetValue (mph_measurement_ind->rx_lev_full); #endif /* * store the measurement report for later use, remove * bad neighbourcells and analyze the data from layer 1 * (remove cells which are not inside the report, * store new cells, update counter etc.). */ mph_measurement_ind->rx_lev_sub = mph_measurement_ind->rx_lev_full; memcpy (&rr_data->ms_data.measurement_report, mph_measurement_ind, sizeof (T_MPH_MEASUREMENT_IND)); /* L1 always report BCCH RXLev as Zero in Idle mode, so copy * BCCH RXLev as receivied level (rx_lev_full) on BCCH * This will be used when we go into dedicated mode * And comback to Idle mode within 480MS Or * Dedicated mode was very-short duration and * RR didn't receive any valid measurement report into * dedicate mode. If we don't do this Cell-Reselction * will fail as rr_data->nc_data[SC_INDEX].rxlev will be zero * Because it is assigned as bcch_rxlev_of_sc of measurement_report * in function att_build_back_from_dedicated. */ rr_data->ms_data.measurement_report.bcch_rxlev_of_sc = mph_measurement_ind->rx_lev_full; att_remove_bad_ncell (mph_measurement_ind); att_analyze_measure_report (mph_measurement_ind); if( rr_data->c_ncell_bcch EQ NOT_INITIALISED ) rr_data->c_ncell_bcch = mph_measurement_ind->ncells.no_of_ncells; if( (rr_data->c_ncell_bcch EQ 0) AND (rr_data->resel_pending EQ TRUE) ) { PFREE (mph_measurement_ind); #ifdef GPRS att_start_cell_reselection_gprs(CELL_RESELECTION_RACH); #else att_start_cell_reselection(CELL_RESELECTION_RACH); #endif rr_data->resel_pending = FALSE; rr_data->c_ncell_bcch = NOT_INITIALISED; return; } /* * check whether a paging has been stored before receiving * the measurement from layer 1. */ if (rr_data->pag_rec) { srv_use_stored_prim (); rr_data->pag_rec = FALSE; } /* * delay cell reselection if network search is still ongoing * or RR initiated plmn search has started. */ att_check_reselect_decision (rr_data->start_cell_reselection); /* * increase power on time to delete forbidden * location area list after 12 hours */ att_increase_power_on_time ((USHORT)(rr_data->ms_data.fn_offset / PERIOD_1_SEC)); } break; case ATT_CON_EST: /* * Measurements from layer 1 during connection establishment */ if (mph_measurement_ind->valid) { /* * store the measurement report for later use, remove * bad neighbourcells and analyze the data from layer 1 * (remove cells which are not inside the report, * store new cells, update counter etc.). */ mph_measurement_ind->rx_lev_sub = mph_measurement_ind->rx_lev_full; memcpy (&rr_data->ms_data.measurement_report, mph_measurement_ind, sizeof (T_MPH_MEASUREMENT_IND)); /* L1 always report BCCH RXLev as Zero in Connection Establishment mode, so copy * BCCH RXLev as receivied level (rx_lev_full). * This will be used when we go into dedicated mode * And comback to Idle mode within 480MS Or * Dedicated mode was very-short duration and * RR didn't receive any valid measurement report into * dedicate mode. If we don't do this Cell-Reselction * will fail as rr_data->nc_data[SC_INDEX].rxlev will be zero * Because it is assigned as bcch_rxlev_of_sc of measurement_report * in function att_build_back_from_dedicated. */ rr_data->ms_data.measurement_report.bcch_rxlev_of_sc = mph_measurement_ind->rx_lev_full; att_remove_bad_ncell (mph_measurement_ind); att_analyze_measure_report (mph_measurement_ind); /* * make a cell reselection decision, but do not start it. */ att_check_reselect_decision (FALSE); /* * increase power on time to delete forbidden * location area list after 12 hours */ att_increase_power_on_time ((USHORT)(rr_data->ms_data.fn_offset / PERIOD_1_SEC)); } break; default: break; } PFREE (mph_measurement_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_rr_activate_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_ACTIVATE_REQ received from MM. */ GLOBAL void att_rr_activate_req (T_RR_ACTIVATE_REQ *rr_activate_req) { GET_INSTANCE_DATA; #ifdef GPRS T_loc_area_ident * lai = &rr_data->nc_data[SC_INDEX].lai; #endif /* GPRS */ TRACE_FUNCTION ("att_rr_activate_req()"); /* * set cell test operation */ rr_data->cell_test_operation = rr_activate_req->cell_test; rr_data->cs_data.check_hplmn = rr_activate_req->check_hplmn; TRACE_EVENT_P1 ( "Cell Test Operation =%d", rr_data->cell_test_operation ); switch (GET_STATE (STATE_ATT)) { case ATT_NULL: #ifdef GPRS if(rr_activate_req->gprs_indication AND rr_data->gprs_data.start_proc EQ START_PROC_NOTHING) { att_set_gprs_indication(rr_activate_req->gprs_indication); att_rrgrr_cr_ind(CR_NORMAL); rr_data->gprs_data.start_proc = START_PROC_ACTIVATE_REQ; if ( srv_check_stored_prim (RR_ACTIVATE_REQ) ) srv_clear_stored_prim(RR_ACTIVATE_REQ); if( !srv_store_prim ((T_PRIM *)D2P(rr_activate_req)) ) { /* * primitive already in queue or storing failed */ PFREE (rr_activate_req); } /* on CR_RSP use_stored_prim is called */ } else att_handle_rr_act_req (TRUE, rr_activate_req); #else att_handle_rr_act_req (TRUE, rr_activate_req); #endif break; case ATT_CS_INIT: #ifdef GPRS if(rr_activate_req->gprs_indication AND rr_data->gprs_data.start_proc EQ START_PROC_NOTHING) { TRACE_EVENT("Activating GPRS in ATT_CS_INIT"); att_set_gprs_indication(rr_activate_req->gprs_indication); att_rrgrr_cr_ind(CR_NORMAL); rr_data->gprs_data.start_proc = START_PROC_ACTIVATE_REQ; /* go ahead for storing the activate_req message */ } else { #endif att_handle_rr_act_req (FALSE, rr_activate_req); break; #ifdef GPRS } #endif /*lint -fallthrough*/ case ATT_CS1: if ( GET_STATE (STATE_CELL_SEL) EQ CS_IDLE_ACTIVE ) { #ifdef GPRS if(rr_activate_req->gprs_indication AND rr_data->gprs_data.start_proc EQ START_PROC_NOTHING AND rr_data->ms_data.req_mm_service EQ FUNC_LIM_SERV_ST_SRCH) { TRACE_EVENT("Activating GPRS in ATT_CS1"); att_set_gprs_indication(rr_activate_req->gprs_indication); att_rrgrr_cr_ind(CR_NORMAL); rr_data->gprs_data.start_proc = START_PROC_ACTIVATE_REQ; /* go ahead for storing the activate_req message */ } else { #endif att_handle_rr_act_req (FALSE, rr_activate_req); return; #ifdef GPRS } #endif } /*lint -fallthrough*/ case ATT_CS3: case ATT_DEDICATED: /* * store rr activate request during cell reselection and while dedicated * only store the latest instance of an ACTIVATE_REQ */ if ( srv_check_stored_prim (RR_ACTIVATE_REQ) ) srv_clear_stored_prim(RR_ACTIVATE_REQ); if( !srv_store_prim ((T_PRIM *)D2P(rr_activate_req)) ) { /* * primitive already in queue or storing failed */ PFREE (rr_activate_req); } break; case ATT_CS2: case ATT_NO_SERVICE: case ATT_IDLE: case ATT_CON_EST: #ifdef GPRS if(rr_activate_req->gprs_indication AND rr_activate_req->op.func NEQ FUNC_NET_SRCH_BY_MMI AND rr_data->gprs_data.start_proc EQ START_PROC_NOTHING) { if( ( rr_data->ms_data.operation_mode EQ ( (rr_activate_req->op.ts << 7) + (rr_activate_req->op.m << 6) + (rr_activate_req->op.sim_ins << 5) ) ) AND ( rr_data->ms_data.req_mm_service EQ rr_activate_req->op.func) AND ( GET_STATE(STATE_GPRS) EQ GPRS_NULL) AND ( rr_data->nc_data[SC_INDEX].si13_loc_ind NEQ SI13_NOT_PRESENT ) AND (GET_STATE(STATE_ATT) EQ ATT_IDLE ) AND (dat_plmn_equal_req ( lai->mcc, lai->mnc, rr_activate_req->plmn.mcc, rr_activate_req->plmn.mnc) ) ) { TRACE_EVENT("gprs activation - cell reselection to same cell"); rr_data->gprs_data.start_proc = START_PROC_GPRS_ACT; rr_data->sc_data.selection_type = CELL_RESELECTION_ON_GPRS_ACT; att_set_gprs_indication(rr_activate_req->gprs_indication); PFREE (rr_activate_req); } else { rr_data->gprs_data.start_proc = START_PROC_ACTIVATE_REQ; att_set_gprs_indication(rr_activate_req->gprs_indication); /* on CR_RSP use_stored_prim is called */ if ( srv_check_stored_prim (RR_ACTIVATE_REQ) ) srv_clear_stored_prim(RR_ACTIVATE_REQ); if( !srv_store_prim ((T_PRIM *)D2P(rr_activate_req)) ) { /* * primitive already in queue or storing failed */ PFREE (rr_activate_req); } } att_rrgrr_cr_ind(CR_NORMAL); } else if (rr_activate_req->op.func EQ FUNC_NET_SRCH_BY_MMI AND (GET_STATE(STATE_GPRS) EQ GPRS_PTM_BCCH OR GET_STATE(STATE_GPRS) EQ GPRS_PTM_PBCCH OR GET_STATE(STATE_GPRS) EQ GPRS_PAM_BCCH OR GET_STATE(STATE_GPRS) EQ GPRS_PAM_PBCCH )) { rr_data->gprs_data.start_proc = START_PROC_NOTHING; /* * send Please Retry to the MMI instead of * storing the primitive */ rr_data->sc_data.found_entries = 0; att_code_rr_abort_ind(RRCS_ABORT_PTM); PFREE (rr_activate_req); } else if (rr_activate_req->op.func EQ FUNC_NET_SRCH_BY_MMI) { /* this is a parallel search, don't inform GRR */ rr_data->gprs_data.start_proc = START_PROC_NOTHING; att_handle_rr_act_req (FALSE, rr_activate_req); } else if( (rr_activate_req->gprs_indication EQ FALSE) AND (rr_activate_req->op.func NEQ FUNC_NET_SRCH_BY_MMI) AND (GET_STATE(STATE_ATT) EQ ATT_IDLE ) AND (rr_data->ms_data.req_mm_service EQ rr_activate_req->op.func) AND ( rr_data->ms_data.operation_mode EQ ((rr_activate_req->op.ts << 7)+(rr_activate_req->op.m << 6)+(rr_activate_req->op.sim_ins << 5)) ) AND (GET_STATE(STATE_GPRS) EQ GPRS_PIM_BCCH) ) { att_set_gprs_indication(rr_activate_req->gprs_indication); att_set_sys_info_read(SYS_INFO_13_READ, SC_INDEX); att_build_idle_req(SC_INDEX, MODE_SYS_INFO_CHANGE); att_code_rr_act_cnf(); PFREE(rr_activate_req); } else /* called after, the CR_RSP is received or if GPRS is not activated */ att_handle_rr_act_req (FALSE, rr_activate_req); #else att_handle_rr_act_req (FALSE, rr_activate_req); #endif break; default: PFREE (rr_activate_req); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_rr_deactivate_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_DEACTIVATE_REQ received from MM. */ GLOBAL void att_rr_deactivate_req (T_RR_DEACTIVATE_REQ *rr_deactivate_req) { GET_INSTANCE_DATA; UBYTE tim_idx; PREUSE (rr_deactivate_req, mph_deactivate_req, MPH_DEACTIVATE_REQ); TRACE_FUNCTION ("att_rr_deactivate_req()"); EM_DEACTIVATION; #if defined(_SIMULATION_FFS_) if(!dat_test_sim_available()) { /* store the white list from RAM to FFS */ if(rr_data->ms_data.rr_service EQ FULL_SERVICE) { cs_store_white_list(); } /* store the Black list from RAM to FFS */ cs_store_black_list(); } #endif /* * stop any timer which might be running */ for (tim_idx = 0; tim_idx < NUM_OF_RR_TIMERS; tim_idx++) TIMERSTOP (tim_idx); /* * reset process states and initialize the * gsm related data. */ dat_att_null (); att_init_gsm_data (); #ifdef GPRS gprs_init_gprs_data(); #endif cs_init_process(); SET_STATE (STATE_ATT, ATT_NULL); /* * deactivate layer 1 */ PSENDX (PL, mph_deactivate_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_rr_sync_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_SYNC_REQ received from MM. */ GLOBAL void att_rr_sync_req (T_RR_SYNC_REQ *rr_sync_req) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_rr_sync_req()"); TRACE_EVENT_P2 ("RR_SYNC_REQ cs=%x att st=%u", rr_sync_req->synccs, GET_STATE (STATE_ATT)); if ((rr_sync_req->synccs NEQ NOT_PRESENT_16BIT) AND (rr_sync_req->synccs NEQ SYNCCS_LAI_ALLOW)) { rr_data->mode_after_dedi = MODE_CELL_RESELECTION; TRACE_EVENT ("rr_sync_req: MODE_CELL_RESELECTION"); #if defined(DL_TRACE_ENABLED) { sprintf (dl_trace_buf, "sync_req cs=%04x ->mode=%u #%u:%s", rr_sync_req->synccs, rr_data->mode_after_dedi, __LINE__, __FILE10__); DL_OFFLINE_TRACE (dl_trace_buf); } #endif /* DL_TRACE_ENABLED */ } if (rr_sync_req->kcv.v_kc) { /* * change of cipher parameter */ memcpy (rr_data->ms_data.new_kc, &rr_sync_req->kcv.kc, KC_STRING_SIZE); rr_data->ms_data.cksn = rr_sync_req->cksn; }/*if v_kc*/ if (rr_sync_req->tmsi_struct.v_mid) { /* * change of TMSI (a new value is defined) */ rr_data->ms_data.tmsi_available = TRUE; rr_data->ms_data.tmsi_binary = rr_sync_req->tmsi_struct.tmsi_dig; /* * forward the new TMSI to layer 1 */ att_mph_identity_req (); }/* if v_mid*/ if (rr_sync_req->op.v_op) { /* * change of the operation mode, typically * change from automatic to manual mode */ rr_data->ms_data.operation_mode = (rr_sync_req->op.ts << SHIFT_FOR_SIM_TYPE) + (rr_sync_req->op.m << SHIFT_FOR_SEARCH_OFFSET) + (rr_sync_req->op.sim_ins << SHIFT_FOR_SIM_INSERTED); att_set_func (rr_sync_req->op.func); switch (GET_STATE (STATE_ATT)) { case ATT_NO_SERVICE: case ATT_IDLE: case ATT_CON_EST: /* * changes from automatic to manual mode and vice versa * may lead to start or stop of HPLMN search. */ if (rr_data->ms_data.rr_service EQ FULL_SERVICE) att_start_registration_timer (); break; default: break; }/*STATE_ATT*/ }/*if v_op*/ switch (GET_STATE (STATE_ATT)) { case ATT_CS1: switch (rr_sync_req->synccs) { case SYNCCS_TMSI_CKSN_KC_INVAL: case SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG: /* * store the primitive during cell selection (power measurements) */ if (!srv_store_prim ((T_PRIM *)D2P(rr_sync_req))) { PFREE (rr_sync_req); }/*if*/ return; default: break; }/*synccs*/ break; case ATT_CS2: switch (rr_sync_req->synccs) { case SYNCCS_TMSI_CKSN_KC_INVAL: case SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG: /* * location updating reject or authentication * failure indicates that a new start of the cell * selection is needed. */ TIMERSTOP (T_RESELECT); /*XY:n don't inform GRR , but call start_cs anyway */ #ifdef GPRS att_start_cell_selection_gprs (RR_ORIGINATED,FULL_SEARCH_MODE); #else att_start_cell_selection (RR_ORIGINATED, CS_NOT_PARALLEL,FULL_SEARCH_MODE); #endif break; default: break; }/*synccs*/ break; case ATT_CS3: case ATT_DEDICATED: case ATT_NO_SERVICE: case ATT_IDLE: case ATT_CON_EST: switch (rr_sync_req->synccs) { case SYNCCS_TMSI_CKSN_KC_INVAL: /* * clear TMSI, CKSN and KC */ att_clear_reg_without_imsi (); break; case SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG: /* * clear TMSI, IMSI, CKSN and KC */ att_clear_registration_data (); break; default: break; }/*synccs*/ break; default: break;/*state*/ }/*STATE_ATT*/ switch (rr_sync_req->synccs) { case SYNCCS_EPLMN_LIST: /* * If sync info contains an EPLMN list * then this is copied regardless of state. * When EPLMN is not available stored EPLMN * is marked as invalid. */ att_copy_eplmn_list(&rr_sync_req->eq_plmn_list); break; case SYNCCS_LAI_ALLOW: /* Store Last Registered PLMN data from the white list */ rr_data->cs_data.last_reg_plmn.v_plmn = V_PLMN_PRES; memcpy (rr_data->cs_data.last_reg_plmn.mcc, rr_data->cs_data.white_list.last_sc_lac.mcc, SIZE_MCC); memcpy (rr_data->cs_data.last_reg_plmn.mnc, rr_data->cs_data.white_list.last_sc_lac.mnc, SIZE_MNC); TRACE_EVENT("LRPLMN copied from white list"); /* * successful end of location updating request, * remove lai from forbidden list if stored */ att_rem_lai_from_forb_list (&rr_sync_req->plmn, rr_sync_req->lac); break; case SYNCCS_LAI_NOT_ALLOW: /* * location updating reject, lai must be added to the * forbidden lai list. */ att_add_to_forb_list (FORBIDDEN_LIST_NORMAL, &rr_sync_req->plmn, rr_sync_req->lac); /* Specifications 24.008 (section 4.4.4.7) - * # 12: (Location Area not allowed); * The MS shall perform a cell selection when back to the MM IDLE state * according to 3GPP TS 03.22 and 3GPP TS 25.304. */ rr_data->ms_data.req_mm_service = FUNC_NET_SRCH_BY_MMI; att_start_cell_selection (RR_ORIGINATED, CS_PARALLEL,NORMAL_SEARCH_MODE); break; case SYNCCS_LAI_NOT_ALLOW_FOR_ROAMING: /* * location updating reject, lai must be added to the * forbidden lai list for roaming. */ att_add_to_forb_list (FORBIDDEN_LIST_ROAMING, &rr_sync_req->plmn, rr_sync_req->lac); break; case SYNCCS_TMSI_INVAL: /* * TMSI is invalid. Clear in RR and inform layer 1 */ rr_data->ms_data.tmsi_available = FALSE; att_mph_identity_req (); break; case SYNCCS_LIMITED_SERVICE: /* Plmn received matches with LRPLMN, flush LRPLMN */ if (rr_sync_req->plmn.v_plmn EQ V_PLMN_PRES) { if(!memcmp(rr_sync_req->plmn.mcc, rr_data->cs_data.last_reg_plmn.mcc, SIZE_MCC) AND !memcmp(rr_sync_req->plmn.mnc, rr_data->cs_data.last_reg_plmn.mnc, SIZE_MNC) ) { rr_data->cs_data.last_reg_plmn.v_plmn = V_PLMN_NOT_PRES; TRACE_EVENT ("LRPLMN Cleared"); } } /* * Indication to RR that only limited service * is possible due to location updating reject cause */ rr_data->ms_data.rr_service = LIMITED_SERVICE; TRACE_EVENT_P7 ("CLEAR plmn, (old MCC/MNC=%x%x%x/%x%x%x) #%u", rr_data->ms_data.plmn.mcc[0], rr_data->ms_data.plmn.mcc[1], rr_data->ms_data.plmn.mcc[2], rr_data->ms_data.plmn.mnc[0], rr_data->ms_data.plmn.mnc[1], rr_data->ms_data.plmn.mnc[2], __LINE__); memset (&rr_data->ms_data.plmn, 0, sizeof (T_plmn)); att_set_rr_service_info(); switch (GET_STATE (STATE_ATT)) { case ATT_NO_SERVICE: case ATT_IDLE: case ATT_CON_EST: att_start_registration_timer(); break; default: break; }/*STATE_ATT*/ #ifdef GPRS if(att_gprs_is_avail()) { /*XY: inform GRR, and wait for CR_RSP */ /* att_rrgrr_cr_ind(CR_NORMAL); */ /* rr_data->gprs_data.start_proc = START_PROC_ENTER_LIMITED; */ /* * During cell reselection, we should not send the primitive * RRGRR_GPRS_SI13_IND to GRR to inform Limited Service. * As this primitive is also used to mark the end of cell reselection. */ if( GET_STATE(STATE_ATT) NEQ ATT_CS3) att_signal_gprs_support(); /* action will follow after cr_rsp */ } #endif break; case SYNCCS_ACCC: rr_data->ms_data.access_classes = rr_sync_req->accc; break; /* SIM's access class by SAT changed */ default: if(!rr_sync_req->op.v_op OR !rr_sync_req->kcv.v_kc OR !rr_sync_req->tmsi_struct.v_mid) TRACE_ERROR ("Unexpected sync event"); break; }/*synccs*/ PFREE (rr_sync_req); }/*att_rr_sync_reg*/ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_meas_rep_cnf | +--------------------------------------------------------------------+ PURPOSE : Process the primitive mph_meas_rep_cnf from ALR. */ #ifdef GPRS GLOBAL void att_mph_meas_rep_cnf(T_MPH_MEAS_REP_CNF* mph_meas_rep_cnf) { UBYTE count; PALLOC(rrgrr_meas_rep_cnf, RRGRR_MEAS_REP_CNF); TRACE_FUNCTION("rrgrr_meas_rep_cnf()"); /*lint -e661 (Possible access of out-of-bounds pointer (26 beyond end of data) by operator '[') */ /*lint -e662 (Possible creation of out-of-bounds pointer (26 beyond end of data) by operator '[') */ for(count=0;count<RRGRR_MEAS_REP_LIST_SIZE;count++) { rrgrr_meas_rep_cnf->meas_res[count].arfcn = mph_meas_rep_cnf->meas_rep[count].arfcn; rrgrr_meas_rep_cnf->meas_res[count].bsic = mph_meas_rep_cnf->meas_rep[count].bsic; rrgrr_meas_rep_cnf->meas_res[count].rxlev = mph_meas_rep_cnf->meas_rep[count].rx_lev; } PFREE(mph_meas_rep_cnf); PSENDX( GRR, rrgrr_meas_rep_cnf ); /*lint +e662 (Possible creation of out-of-bounds pointer (26 beyond end of data) by operator '[') */ /*lint +e661 (Possible access of out-of-bounds pointer (26 beyond end of data) by operator '[') */ } #endif /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_meas_order_cnf | +--------------------------------------------------------------------+ PURPOSE : */ GLOBAL void att_mph_meas_order_cnf (T_MPH_MEAS_ORDER_CNF* meas) { PFREE(meas); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_align_sc_meas | +--------------------------------------------------------------------+ PURPOSE : index == SC_INDEX: In this case the function is used to eliminate poor serving cell RX level values due to spurious measurements. This function is related to FTA test case 20.19. index == CR_INDEX: In this case the function is used to set the right aligned level of a delayed measurement report during cell reselection (ATT_CS3) to the cell with the CR_INDEX. */ LOCAL void att_align_sc_meas (T_MPH_MEASUREMENT_IND * mph_meas_ind, UBYTE index) { GET_INSTANCE_DATA; UBYTE i; TRACE_FUNCTION ("att_align_sc_meas()"); if (mph_meas_ind->valid) { if (rr_data->nc_data[index].arfcn EQ mph_meas_ind->arfcn) { /* * update the serving cell or cr cell fieldstrength */ #if defined(_SIMULATION_) TRACE_EVENT_WIN_P3 ("att_align_sc_meas(idx=%u): SC/CR=[%u], rx=%d", index, mph_meas_ind->arfcn, mph_meas_ind->rx_lev_full); #endif rr_data->nc_data[index].rxlev = mph_meas_ind->rx_lev_full; } else { /* * check all neighbourcells */ for (i=0;i<mph_meas_ind->ncells.no_of_ncells;i++) { /* * if the cell is also inside the neighbourcells, take * this fieldstrength value. */ if (mph_meas_ind->ncells.arfcn[i] EQ rr_data->nc_data[index].arfcn) { #if defined(_SIMULATION_) TRACE_EVENT_WIN_P3 ("att_align_sc_meas(idx=%u): nc[%u] found, rx=%d", index, mph_meas_ind->ncells.arfcn[i], mph_meas_ind->ncells.rx_lev[i]); #endif rr_data->nc_data[index].rxlev = mph_meas_ind->ncells.rx_lev[i]; return; } } } } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_rr_sync_hplmn_req | +--------------------------------------------------------------------+ PURPOSE : Process the primitive RR_SYNC_HPLMN_REQ received from MM. */ GLOBAL void att_rr_sync_hplmn_req (T_RR_SYNC_HPLMN_REQ *rr_sync_hplmn_req) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_rr_sync_hplmn_req()"); memcpy (&rr_data->ms_data.ahplmn, &rr_sync_hplmn_req->plmn, sizeof (T_plmn)); rr_data->ms_data.v_eq_plmn = FALSE; memset(&rr_data->ms_data.eq_plmn_list, 0xFF, SIZE_EPLMN); PFREE(rr_sync_hplmn_req); } #if defined FF_EOTD /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_ATT | | STATE : code ROUTINE : att_mph_ncell_pos_ind | +--------------------------------------------------------------------+ PURPOSE : Process the primitive MPH_NCELL_POS_IND received from PL. */ GLOBAL void att_mph_ncell_pos_ind (T_MPH_NCELL_POS_IND *mph_ncell_pos_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_mph_ncell_pos_ind()"); if ( mph_ncell_pos_ind->eotd_res EQ EOTD_SUCC ) { /* Forward input primitive to LC adding some parameters */ T_loc_area_ident *loc_area_ident; T_NC_DATA *sc; int i,n; PALLOC (rrlc_meas_ind, RRLC_MEAS_IND); sc = &rr_data->nc_data[SC_INDEX]; loc_area_ident = &sc->lai; memcpy ( &rrlc_meas_ind->mcc[0], &loc_area_ident->mcc[0], 3 * sizeof rrlc_meas_ind->mcc[0]); memcpy ( &rrlc_meas_ind->mnc[0], &loc_area_ident->mnc[0], 3 * sizeof rrlc_meas_ind->mnc[0]); rrlc_meas_ind->lac = loc_area_ident->lac; rrlc_meas_ind->cell_id = sc->cell_id; rrlc_meas_ind->req_id = mph_ncell_pos_ind->req_id; rrlc_meas_ind->tav = mph_ncell_pos_ind->ta; rrlc_meas_ind->fn = mph_ncell_pos_ind->fn; rrlc_meas_ind->eotd_sc_res = mph_ncell_pos_ind->eotd_sc_res; rrlc_meas_ind->eotd_sc_res1 = mph_ncell_pos_ind->eotd_sc_res1; n = rrlc_meas_ind->c_eotd_nc_res = mph_ncell_pos_ind->c_eotd_nc_res; for ( i = 0; i < n; ++i ) rrlc_meas_ind->eotd_nc_res[i] = mph_ncell_pos_ind->eotd_nc_res[i]; if ( GET_STATE (STATE_ATT) EQ ATT_DEDICATED #ifdef GPRS OR (GET_STATE (STATE_ATT) EQ ATT_IDLE AND GET_STATE(STATE_GPRS) EQ GPRS_PTM_BCCH AND GET_STATE(STATE_GPRS) EQ GPRS_PTM_PBCCH ) #endif ) rrlc_meas_ind->eotd_mode = EOTD_DEDIC; else rrlc_meas_ind->eotd_mode = EOTD_IDLE; /* * If this is a response to an explicit position measurement request, * then reset the flag which enables handover indications to LC. */ if ( rr_data->eotd_req_id NEQ NOT_PRESENT_16BIT AND rr_data->eotd_req_id EQ mph_ncell_pos_ind->req_id ) rr_data->eotd_req_id = NOT_PRESENT_16BIT; PSENDX (LC, rrlc_meas_ind); } else { PALLOC (rrlc_error_ind, RRLC_ERROR_IND); rrlc_error_ind->cause = LCS_WRONG_BTS; /* exact cause is unclear, assume wrong BTS */ PSENDX (LC, rrlc_error_ind); } PFREE(mph_ncell_pos_ind); } #endif /* FF_EOTD */ #ifdef TI_PS_FF_QUAD_BAND_SUPPORT GLOBAL void att_mph_init_rr_ind(T_MPH_INIT_RR_IND* mph_init_rr_ind) { GET_INSTANCE_DATA; UBYTE freq_bands; T_rf_power *rfp = &rr_data->ms_data.rf_cap.rf_power; TRACE_FUNCTION ("att_mph_init_rr_ind()"); rr_csf_get_freq_bands (&freq_bands); if (mph_init_rr_ind->freq_bands NEQ freq_bands) { TRACE_EVENT_P2 ("FFS data %x, doesn't match L1 compilation flag %x", freq_bands, mph_init_rr_ind->freq_bands); TRACE_ERROR ("FFS data doesn't match L1 compilation flag"); TRACE_ASSERT (freq_bands NEQ mph_init_rr_ind->freq_bands); } if (rfp->pow_class4[IDX_PWRCLASS_900].pow_class NEQ mph_init_rr_ind->pclass_900 OR rfp->pow_class4[IDX_PWRCLASS_850].pow_class NEQ mph_init_rr_ind->pclass_850 OR rfp->pow_class4[IDX_PWRCLASS_1800].pow_class NEQ mph_init_rr_ind->pclass_1800 OR rfp->pow_class4[IDX_PWRCLASS_1900].pow_class NEQ mph_init_rr_ind->pclass_1900) { TRACE_EVENT ("FFS Power Class info doesn't match L1 Powe Class info"); TRACE_ERROR ("FFS Power Class info doesn't match L1 Powe Class info"); TRACE_ASSERT (mph_init_rr_ind->pclass_900 NEQ rfp->pow_class4[IDX_PWRCLASS_900].pow_class); } PFREE(mph_init_rr_ind); } #endif #endif