FreeCalypso > hg > fc-magnetite
view src/g23m-gsm/rr/rr_dats.c @ 478:5e39123540e6
hybrid fw: Openmoko-mimicking AT@BAND command implemented
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 14 Jun 2018 06:04:54 +0000 |
parents | 27a4235405c6 |
children |
line wrap: on
line source
/* +----------------------------------------------------------------------------- | Project : | Modul : +----------------------------------------------------------------------------- | Copyright 2002 Texas Instruments Berlin, AG | All rights reserved. | | This file is confidential and a trade secret of Texas | Instruments Berlin, AG | The receipt of or possession of this file does not convey | any rights to reproduce or disclose its contents or to | manufacture, use, or sell anything it may describe, in | whole, or in part, without the specific written consent of | Texas Instruments Berlin, AG. +----------------------------------------------------------------------------- | Purpose : This Modul defines the functions for the data transfer | capability of the module Radio Resource. +----------------------------------------------------------------------------- */ #ifndef RR_DATS_C #define RR_DATS_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 "em.h" #include "rr_em.h" /*==== EXPORT =====================================================*/ /*==== PRIVAT =====================================================*/ #define TDMA_FRAMES_PER_HYPERFRAME 2715648 #define QUARTER_BITS_PER_FRAME 5000 /*==== VARIABLES ==================================================*/ /*==== FUNCTIONS ==================================================*/ LOCAL BOOL dat_for_handover_mob_alloc(UBYTE *mob_alloc, T_LIST *hop_list_handover, T_VOID_STRUCT *mob_alloc_handover, T_DL_DATA_IND *dl_data_ind); LOCAL void dat_cr_data_multirate_conf(U8 v_multirate_conf, T_multirate_conf *multirate_conf); LOCAL void dat_dedicated_req_ch_type2(T_ch_type2 *ch_type2, T_chan_desc_before *chan_desc_before, T_LIST *hop_list_before); /* * ------------------------------------------------------------------- * SIGNAL Processing functions * ------------------------------------------------------------------- */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_att_cell_selected | +--------------------------------------------------------------------+ PURPOSE : Attachment process indicates that it has camped on a cell. Data transfer process changes the state and connections are possible. */ GLOBAL void dat_att_cell_selected (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("dat_att_cell_selected()"); SET_STATE (STATE_DAT, DAT_IDLE); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_att_null | +--------------------------------------------------------------------+ PURPOSE : Attachment process indicates loss of coverage and connections are not longer possible. */ GLOBAL void dat_att_null (void) { GET_INSTANCE_DATA; TRACE_FUNCTION ("dat_att_null()"); SET_STATE (STATE_DAT, DAT_NULL); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_assign_cmd | +--------------------------------------------------------------------+ PURPOSE : The function handles the reception of a channel assignment message. */ GLOBAL void dat_for_assign_cmd (T_DL_DATA_IND *dl_data_ind, T_D_ASSIGN_CMD *assign_cmd, T_LIST *hop_list_after, T_LIST *hop_list_before, T_LIST *cell_chan_desc) { GET_INSTANCE_DATA; UBYTE mob_alloc[65]; PALLOC (dedicated_req, MPH_DEDICATED_REQ); TRACE_FUNCTION ("dat_for_assign_cmd()"); switch (GET_STATE (STATE_DAT)) { case DAT_DEDICATED: if (rr_data->ms_data.error.cs) { TRACE_EVENT_P1 ("RRC cause = %02x", rr_data->ms_data.error.cs); } /* * dynamic configuration command : IHO * Lock the DUT to the cell it is already camping - * Ignore the Channel Assignment command message and send an * Assignment failure message to the network. */ if(rr_data->dyn_config.iho AND (rr_data->sc_data.ch_mode EQ CM_AMR)) { TRACE_EVENT("D_ASSIGN_CMD : IHO"); for_set_content_error (RRC_CHANNEL_MODE); } switch (rr_data->ms_data.error.cs) { /* case RRC_INVALID_MAN_INFO: this value is currently never set */ case RRC_COND_IE_ERROR: /* 0x64 */ { /* * If an mandatory info element error or a * conditional info element error has been detected, * a RR STATUS message is returned on the existing * connection before l2 is suspended */ dat_send_rr_status_msg(rr_data->ms_data.error.cs); PFREE (dedicated_req); PFREE (dl_data_ind); break ; } case RRC_INCORRECT_MSG: /* 0x5f */ { /* * If a structurally correct message has been detected, * containing erroneous data, an Assignment Failure message * is sent back. */ /* * If the ASSIGNMENT COMMAND is erroneous, then the * ASSIGNMENT FAILURE command is sent via a priority * DL_RECONNECT_REQ. This ensures DL will halt processing * anything in its buffer until it has sent this message * onto the nw. * */ for_suspend_layer_2 (); dat_send_assign_fail_msg(rr_data->ms_data.error.val); RR_EM_SET_ASSIGN_FAIL_CAUSE(rr_data->ms_data.error.val); PFREE (dedicated_req); PFREE (dl_data_ind); break; } default: /* * the initial check was successful and the * message is processed. * */ for_suspend_layer_2 (); /* * use data of the old cell if no new data * are inserted in the message */ rr_data->cr_data.ch_mode = rr_data->sc_data.ch_mode; rr_data->cr_data.ciph_on = rr_data->sc_data.ciph_on; rr_data->cr_data.algo = rr_data->sc_data.algo; rr_data->cr_data.cd.v_cell_chan_desc = rr_data->sc_data.cd.v_cell_chan_desc; memcpy (&rr_data->cr_data.cd.cell_chan_desc, &rr_data->sc_data.cd.cell_chan_desc, sizeof (T_LIST)); /* * if AMR is supported set the default values * to the current serving cell values. */ if(rr_data->sc_data.ch_mode EQ CM_AMR) { memcpy(&rr_data->cr_data.amr_conf, &rr_data->sc_data.amr_conf, sizeof (T_multirate_conf)); } else { /* * AMR is not supported, therefore set some dummy values. This is necessary because * the later Layer1 configuration must include an AMR configuration!! */ memset(&rr_data->cr_data.amr_conf, 0, sizeof (T_multirate_conf)); } if (assign_cmd->v_cell_chan_desc) { /* * If the message contains a cell channel description * use the new one. */ memcpy (&rr_data->cr_data.cd.cell_chan_desc, cell_chan_desc, sizeof (T_LIST)); rr_data->cr_data.cd.v_cell_chan_desc = WITH_CHANGED_CONTENT; } if (assign_cmd->v_chan_mode) /* * if the message contains a channel mode, use the new one. */ rr_data->cr_data.ch_mode = assign_cmd->chan_mode; /* * If AMR is signalled check if new multi-rate speech codec is part of the assignment cmd * otherwise use default values set earlier. */ /* Implements RR Clone findings #9 */ dat_cr_data_multirate_conf(assign_cmd->v_multirate_conf,&assign_cmd->multirate_conf); if (assign_cmd->v_ciph_mode_set) { /* * If ciphering is defined in the message, handle it. */ rr_data->cr_data.ciph_on = assign_cmd->ciph_mode_set.sc; rr_data->cr_data.algo = assign_cmd->ciph_mode_set.algo_ident; if (rr_data->cr_data.ciph_on EQ CIPH_ON AND rr_data->sc_data.ciph_received EQ FALSE) { /* * if ciphering is not active, but set in the message * this is a failure and the configuration is aborted. * Instead the reconnection on the old channel is started. */ dat_send_assign_fail_msg(RRC_PROT_UNSPECIFIED); RR_EM_SET_ASSIGN_FAIL_CAUSE(RRC_PROT_UNSPECIFIED); PFREE (dedicated_req); PFREE (dl_data_ind); return; } } if (assign_cmd->chan_desc.hop EQ 1 AND assign_cmd->v_mob_alloc_after) { if (rr_data->cr_data.cd.v_cell_chan_desc EQ NO_CONTENT) { /* * If the new channel needs hopping, but there is no * cell channel description available, the configuration * is aborted due to a conditional error. * Instead the reconnection on the old channel is started. */ dat_send_assign_fail_msg(RRC_NO_CELL_ALLOC); RR_EM_SET_ASSIGN_FAIL_CAUSE(RRC_NO_CELL_ALLOC); PFREE (dedicated_req); PFREE (dl_data_ind); return; } /* * if the message contains a mobile allocation, * build a list of 1-bits from the bitmap. */ att_bits_to_byte (mob_alloc, assign_cmd->mob_alloc_after.c_mac, assign_cmd->mob_alloc_after.mac); /* * create a hopping list from mobile allocation and cell channel * description */ if(!srv_create_chan_mob_alloc (&rr_data->cr_data.cd.cell_chan_desc, hop_list_after, mob_alloc)) { dat_send_assign_fail_msg(RRC_FREQ_NOT_IMPL); RR_EM_SET_ASSIGN_FAIL_CAUSE(RRC_FREQ_NOT_IMPL); PFREE (dedicated_req); PFREE (dl_data_ind); return; } } /* * clean primitive to layer 1 */ memset (dedicated_req, 0, sizeof (T_MPH_DEDICATED_REQ)); dedicated_req->mod = MODE_CHAN_ASSIGN; rr_data->cr_data.chan_desc = assign_cmd->chan_desc; /* * Set Channel Type */ dedicated_req->ch_type.ch = assign_cmd->chan_desc.chan_type; dedicated_req->ch_type.tn = assign_cmd->chan_desc.tn; dedicated_req->ch_type.tsc = assign_cmd->chan_desc.tsc; dedicated_req->ch_type.h = assign_cmd->chan_desc.hop; if (assign_cmd->chan_desc.hop EQ H_NO) { dedicated_req->ch_type.arfcn = assign_cmd->chan_desc.arfcn; } else { dedicated_req->ch_type.maio = assign_cmd->chan_desc.maio; dedicated_req->ch_type.hsn = assign_cmd->chan_desc.hsn; /* CSI-LLD section:4.1.1.11 * This function Updates the black list with the MA list received * inthe assignment command */ cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,hop_list_after); srv_create_list (hop_list_after, dedicated_req->ch_type.ma, MAX_MA_CHANNELS, TRUE, 0); } /* * set initial power */ dedicated_req->tr_para.power = assign_cmd->pow_cmd.pow; /* * set starting time if available. */ if (assign_cmd->v_start_time) { dedicated_req->start.v_start = TRUE; dedicated_req->start.t1 = assign_cmd->start_time.t1; dedicated_req->start.t2 = assign_cmd->start_time.t2; dedicated_req->start.t3 = assign_cmd->start_time.t3; } /* * Setting of before starting time elements ! */ if (assign_cmd->v_chan_desc_before EQ FALSE) dedicated_req->ch_type2.ch = NOT_PRESENT_8BIT; else { if (assign_cmd->v_mob_alloc_before) { att_bits_to_byte (mob_alloc, assign_cmd->mob_alloc_before.c_mac, assign_cmd->mob_alloc_before.mac); if(!srv_create_chan_mob_alloc (&rr_data->cr_data.cd.cell_chan_desc, hop_list_before, mob_alloc)) { dat_send_assign_fail_msg(RRC_FREQ_NOT_IMPL); RR_EM_SET_ASSIGN_FAIL_CAUSE( RRC_FREQ_NOT_IMPL); PFREE (dedicated_req); PFREE (dl_data_ind); return; } } dat_dedicated_req_ch_type2(&dedicated_req->ch_type2, &assign_cmd->chan_desc_before, hop_list_before ); } /* * set dtx depending on the channel type (halfrate or fullrate) */ if (dedicated_req->ch_type.ch EQ 2 OR dedicated_req->ch_type.ch EQ 3) dedicated_req->tr_para.dtx = rr_data->sc_data.cd.dtx = rr_data->sc_data.cd.dtx_half; else dedicated_req->tr_para.dtx = rr_data->sc_data.cd.dtx = rr_data->sc_data.cd.dtx_full; dedicated_req->arfcn = rr_data->nc_data[SC_INDEX].arfcn; dedicated_req->tr_para.rlt = rr_data->sc_data.cd.cell_options.rlt; dedicated_req->tr_para.pwrc = rr_data->sc_data.cd.cell_options.pow_ctrl; dedicated_req->tr_para.mode = rr_data->cr_data.ch_mode; /* * Set multi-rate speech codec */ dedicated_req->amr_conf.nscb = rr_data->cr_data.amr_conf.nscb; dedicated_req->amr_conf.icmi = rr_data->cr_data.amr_conf.icmi; dedicated_req->amr_conf.st_mode = rr_data->cr_data.amr_conf.st_mode; dedicated_req->amr_conf.acs = rr_data->cr_data.amr_conf.set_amr; /* * valid flag for the threshold and hystersis values. amr_conf.c_cod_prop * defines the number of threshold and hystersis values. */ dedicated_req->amr_conf.v_cod_prop = rr_data->cr_data.amr_conf.v_cod_prop; if(dedicated_req->amr_conf.v_cod_prop) { int i; dedicated_req->amr_conf.c_cod_prop = rr_data->cr_data.amr_conf.c_cod_prop; for(i=0; i<dedicated_req->amr_conf.c_cod_prop; i++) memcpy(&dedicated_req->amr_conf.cod_prop[i], &rr_data->cr_data.amr_conf.cod_prop[i], sizeof(T_cod_prop)); } if (rr_data->cr_data.ciph_on) { /* * set cipher parameter if available. */ dedicated_req->ciph.stat = rr_data->cr_data.ciph_on; dedicated_req->ciph.algo = rr_data->cr_data.algo; memcpy (dedicated_req->ciph.kc, rr_data->ms_data.kc, KC_STRING_SIZE); } RR_EM_GET_HOPPING_CHANNEL (dedicated_req->ch_type.ma, dedicated_req->ch_type2.ma, dedicated_req->start.v_start,dedicated_req->ch_type2.maio); EM_ASSIGNMENT_RECEIVED; /* * configure layer 1 */ SET_STATE (STATE_DAT, DAT_CHAN_ASS); PSENDX (PL, dedicated_req); PFREE (dl_data_ind); return; } break; default: PFREE (dedicated_req); PFREE (dl_data_ind); break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_chan_mod | +--------------------------------------------------------------------+ PURPOSE : The function handles a received channel mode modify message. */ GLOBAL void dat_for_chan_mod (T_DL_DATA_IND *dl_data_ind, T_D_CHAN_MOD *chan_mod) { GET_INSTANCE_DATA; MCAST (chan_mod_ack, U_CHAN_MOD_ACK); TRACE_FUNCTION ("dat_for_chan_mod()"); if (rr_data->ms_data.error.cs EQ 0) { /* * the check in the formatter indicates no problems * store new channel mode. */ rr_data->sc_data.ch_mode = chan_mod->chan_mode; /* * the channel mode modify message contains a multi-rate configuration IEI */ if( chan_mod->v_multirate_conf AND (chan_mod->chan_mode EQ CM_AMR) ) { int i; rr_data->sc_data.amr_conf.mr_vers = chan_mod->multirate_conf.mr_vers; rr_data->sc_data.amr_conf.nscb = chan_mod->multirate_conf.nscb; rr_data->sc_data.amr_conf.icmi = chan_mod->multirate_conf.icmi; rr_data->sc_data.amr_conf.st_mode = chan_mod->multirate_conf.st_mode; rr_data->sc_data.amr_conf.set_amr = chan_mod->multirate_conf.set_amr; rr_data->sc_data.amr_conf.v_cod_prop = chan_mod->multirate_conf.v_cod_prop; if(rr_data->sc_data.amr_conf.v_cod_prop) { rr_data->sc_data.amr_conf.c_cod_prop = chan_mod->multirate_conf.c_cod_prop; for (i=0; i< rr_data->sc_data.amr_conf.c_cod_prop; i++) memcpy(&rr_data->sc_data.amr_conf.cod_prop[i], &chan_mod->multirate_conf.cod_prop[i], sizeof(T_cod_prop)); } } /* * configure layer 1 */ dat_code_mph_chan_mode_req (chan_mod); EM_CHANNEL_MODE_MODIFY; /* * indicate new channel mode to MM */ dat_code_channel_mode_to_mm (); } { /* * build the answer to the network * (channel mode modify acknowledge message) */ PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_CHAN_MOD_ACK); /* * set channel type and SAPI */ dat_code_prr_channel (&dl_data_req->ch_type, &dl_data_req->sapi, rr_data->sc_data.chan_desc.chan_type); chan_mod_ack->msg_type = U_CHAN_MOD_ACK; memcpy (&chan_mod_ack->chan_desc, &rr_data->sc_data.chan_desc, sizeof (T_chan_desc)); /* * set the current channel mode. if the new * channel mode is supported by the MS, the new * one is returned, else it is the previous one * and layer 1 was not re-configured. */ chan_mod_ack->chan_mode = rr_data->sc_data.ch_mode; for_dat_data_req (dl_data_req); EM_CHANNEL_MODE_MODIFY_ACK; } PFREE(dl_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_chan_rel | +--------------------------------------------------------------------+ PURPOSE : Reception of a channel release message. */ GLOBAL void dat_for_chan_rel (T_DL_DATA_IND *dl_data_ind, T_D_CHAN_REL *chan_rel) { GET_INSTANCE_DATA; TRACE_FUNCTION ("dat_for_chan_rel()"); if (GET_STATE (STATE_DAT) NEQ DAT_NULL) { /* * disconnect layer 2 link */ dat_disconnect_link (CAUSE_MAKE (DEFBY_STD, ORIGSIDE_NET, RR_ORIGINATING_ENTITY, chan_rel->rr_cause)); #ifdef GPRS if (chan_rel->v_gprs_resum) { rr_data->gprs_data.gprs_resump = chan_rel->gprs_resum.res_ack; } /* o if the element is not available but we have send a susp_req a resumption failure has occured (gprs_resump was already set on tx of the suspension request) o if the element is not present and we have not send a suspension request there is no resumption failure. o For Ericsson we have to do a RAU after every CS call even if the call started on a GSM-only cell and we did not send a suspension request */ else if(att_gprs_is_avail()) rr_data->gprs_data.gprs_resump = GPRS_RESUMPTION_NOT_ACK; #endif if (chan_rel->v_ba_range) { /* * convert RR_BA_RANGE to BCCH-LIST and * send it with RR SYNC IND to MM */ dat_code_prr_bcch_info (chan_rel->v_ba_range, &chan_rel->ba_range); } EM_CHANNEL_RELEASE; } PFREE (dl_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_class_enq | +--------------------------------------------------------------------+ PURPOSE : Reception of a classmark enquiry message. */ #ifdef REL99 GLOBAL void dat_for_class_enq (T_DL_DATA_IND *dl_data_ind, T_D_CLASS_ENQ *class_enq) #else GLOBAL void dat_for_class_enq (T_DL_DATA_IND *dl_data_ind) #endif { TRACE_FUNCTION ("dat_for_class_enq()"); if (dat_check_error_flag (SEND_RR_STATUS)) { /* * The syntax check indicates no problems, then * process the message. * * The MS returns a classmark change message. */ /* Implements RR Clone findings #15 */ #ifdef REL99 /*Perform checks on classmark enquiry mask IE, if present*/ if ((class_enq->v_class_enq_mask EQ FALSE) OR ((class_enq->v_class_enq_mask EQ TRUE) AND (class_enq->class_enq_mask.class_req EQ CLASS_CHANGE_REQ) ) ) #endif dat_class_chng_data_req(); } EM_CLASSMARK_ENQUIRY; PFREE (dl_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : send_mph_tch_loop_req | +--------------------------------------------------------------------+ PURPOSE : Send the L1 primitive for close TCH loop. */ static void send_mph_tch_loop_req(T_DL_DATA_IND * dl_data_ind, UBYTE loop_command) { /* * configure layer 1 */ PREUSE (dl_data_ind, loop_req, MPH_TCH_LOOP_REQ);/* T_MPH_TCH_LOOP_REQ */ loop_req->tch_loop = loop_command; PSENDX (PL, loop_req); } /* +-----------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : send_close_tch_loop_ack_to_nw | +-----------------------------------------------------------------------+ PURPOSE : Send the CLOSE TCH LOOP ACK message to the network. */ static void send_close_tch_loop_ack_to_nw(void) { GET_INSTANCE_DATA; /* * if the TCH loop is open and a TCH is assigned */ PALLOC_SDU (data_req, DL_DATA_REQ, 2*BITS_PER_BYTE); /* * set channel type and sapi for the response to the network */ dat_code_prr_channel (&data_req->ch_type, &data_req->sapi, rr_data->sc_data.chan_desc.chan_type); /* * code the message without CCD */ data_req->sdu.l_buf = 16; data_req->sdu.o_buf = ENCODE_OFFSET; data_req->sdu.buf [0] = 0; /*lint -e415 -e416 Likely access of out-of-bounds pointer*/ data_req->sdu.buf [1] = 0; data_req->sdu.buf [2] = 0; data_req->sdu.buf [3] = 0x0F; /* TI=0, PD = TST */ data_req->sdu.buf [4] = 0x01; /* MT = Close TCH Ack */ /*lint +e415 +e416 Likely access of out-of-bounds pointer*/ TRACE_EVENT ("DL_DATA_REQ (RR message)"); EM_TCH_LOOP_CLOSED; PSENDX (DL, data_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_close_loop_cmd | +--------------------------------------------------------------------+ PURPOSE : Reception of a TCH Close Loop Command message. */ static const UBYTE LOOP_TYPE [32] = { /* C B A Z Y */ 0x00, /* 0 0 0 0 0 -> Type A */ 0x01, /* 0 0 0 0 1 -> Type B */ 0x02, /* 0 0 0 1 0 -> Type C */ 0x02, /* 0 0 0 1 1 -> Type C */ 0x03, /* 0 0 1 0 0 -> Type D */ 0x03, /* 0 0 1 0 1 -> Type D */ 0x03, /* 0 0 1 1 0 -> Type D */ 0x03, /* 0 0 1 1 1 -> Type D */ 0x04, /* 0 1 0 0 0 -> Type E */ 0x04, /* 0 1 0 0 1 -> Type E */ 0x04, /* 0 1 0 1 0 -> Type E */ 0x04, /* 0 1 0 1 1 -> Type E */ 0x05, /* 0 1 1 0 0 -> Type F */ 0x05, /* 0 1 1 0 1 -> Type F */ 0x05, /* 0 1 1 1 0 -> Type F */ 0x05, /* 0 1 1 1 1 -> Type F */ 0xFF, /* 1 0 0 0 0 -> Not valid */ 0xFF, /* 1 0 0 0 1 -> Not valid */ 0xFF, /* 1 0 0 1 0 -> Not valid */ 0xFF, /* 1 0 0 1 1 -> Not valid */ 0xFF, /* 1 0 1 0 0 -> Not valid */ 0xFF, /* 1 0 1 0 1 -> Not valid */ 0xFF, /* 1 0 1 1 0 -> Not valid */ 0xFF, /* 1 0 1 1 1 -> Not valid */ 0xFF, /* 1 1 0 0 0 -> Not valid */ 0xFF, /* 1 1 0 0 1 -> Not valid */ 0xFF, /* 1 1 0 1 0 -> Not valid */ 0xFF, /* 1 1 0 1 1 -> Not valid */ 0x06, /* 1 1 1 0 0 -> Type I */ 0x06, /* 1 1 1 0 1 -> Type I */ 0x06, /* 1 1 1 1 0 -> Type I */ 0x06 /* 1 1 1 1 1 -> Type I */ }; GLOBAL void dat_for_close_loop_cmd (T_DL_DATA_IND * dl_data_ind, UBYTE subchannel) { GET_INSTANCE_DATA; UBYTE loop_command = NOT_PRESENT_8BIT; TRACE_FUNCTION ("dat_for_close_loop_cmd()"); if (dat_test_sim_available () OR !dat_check_sim_available () ) { /* * only if a test SIM card is inserted */ if ((rr_data->tch_loop_subch EQ NOT_PRESENT_8BIT) AND rr_data->sc_data.chan_desc.chan_type < CH_SDCCH_4_0) { switch ((loop_command = LOOP_TYPE [(subchannel>>1) & 0x1F])) { case TCH_LOOP_C: /* Loop C */ /* first send ACK msg, then activate L1 */ send_close_tch_loop_ack_to_nw(); /* * Delay to allow L1/HW to switch */ vsi_t_sleep (VSI_CALLER DELAY_CLOSE_TCH_LOOP_ACK); send_mph_tch_loop_req(dl_data_ind, loop_command); /* will be needed when TCH Open Loop Command will be received */ rr_data->tch_loop_subch = loop_command; break; case TCH_LOOP_I: /* Loop I */ if (rr_data->sc_data.ch_mode NEQ CM_AMR) { PFREE (dl_data_ind); break; } case TCH_LOOP_A: case TCH_LOOP_B: case TCH_LOOP_D: case TCH_LOOP_E: case TCH_LOOP_F: /* Loop A, B, D, E, F, I */ send_mph_tch_loop_req(dl_data_ind, loop_command); /* * Delay to allow L1/HW to switch */ vsi_t_sleep (VSI_CALLER DELAY_CLOSE_TCH_LOOP_ACK); send_close_tch_loop_ack_to_nw(); /* will be needed when TCH Open Loop Command will be received */ rr_data->tch_loop_subch = loop_command; break; default : TRACE_EVENT_P1("TCH_LOOP_CLOSE_CMD : wrong subchannel (%x)", subchannel); PFREE (dl_data_ind); break; } } else { PFREE (dl_data_ind); } } else { PFREE (dl_data_ind); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_test_interface | +--------------------------------------------------------------------+ PURPOSE : Reception of a Test-Interface message. */ GLOBAL void dat_for_test_interface (T_DL_DATA_IND * dl_data_ind, UBYTE tested_device) { TRACE_FUNCTION ("dat_for_test_interface()"); if (dat_test_sim_available ()) { /* * Only if a test SIM card is inserted * * then configure layer 1 */ PREUSE (dl_data_ind, dai_req, MPH_DAI_REQ); /* T_MPH_DAI_REQ */ dai_req->device = tested_device; EM_TEST_INTERFACE; PSENDX (PL, dai_req); } else { /* * else ignore the message */ PFREE (dl_data_ind); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_ciph_cmd | +--------------------------------------------------------------------+ PURPOSE : Reception of a cipher mode command message. */ GLOBAL void dat_for_ciph_cmd (T_DL_DATA_IND *dl_data_ind, T_D_CIPH_CMD *ciph_cmd) { GET_INSTANCE_DATA; TRACE_FUNCTION ("dat_for_cyph_cmd()"); if (dat_check_error_flag (SEND_RR_STATUS)) { /* * the check in the formatter was successful */ if ( ((rr_data->sc_data.ciph_on EQ CIPH_ON) AND (ciph_cmd->ciph_mode_set.sc EQ START_CIPH_YES)) OR ((ciph_cmd->ciph_mode_set.sc EQ START_CIPH_YES) AND (rr_data->dyn_config.nkc EQ 0 AND rr_data->ms_data.cksn > 6)) ) { /* * Respond with RR Status in 2 cases * * 1: if NW re-enables ciphering * 2: if network has enabled ciphering "and" no valid ciphering key * is available (and user specific handling of cksn is * disabled (nck==0)). * If network has not enabled ciphering, then ciphering key * value is not checked */ dat_send_rr_status_msg(RRC_PROT_UNSPECIFIED); } else { MCAST (ciph_comp, U_CIPH_COMP); PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_CIPH_COMP); /* * set channel type and SAPI for response to the network */ dat_code_prr_channel (&dl_data_req->ch_type, &dl_data_req->sapi, rr_data->sc_data.chan_desc.chan_type); /* * store cipher parameter */ rr_data->sc_data.ciph_on = ciph_cmd->ciph_mode_set.sc; rr_data->sc_data.algo = ciph_cmd->ciph_mode_set.algo_ident; rr_data->sc_data.ciph_received = TRUE; memcpy (rr_data->ms_data.kc, rr_data->ms_data.new_kc, KC_STRING_SIZE); /* * configure layer 1 */ if ( rr_data->ms_data.cksn <= 6 ) { dat_code_mph_ciphering_req (rr_data->sc_data.ciph_on, rr_data->sc_data.algo, rr_data->ms_data.kc); } else { dat_code_mph_ciphering_req (CIPH_OFF, 0, NULL); } if (ciph_cmd->ciph_res.cr EQ INC_IMEISV_YES) { /* * if the response shall contain the IMEI, fill it in. */ ciph_comp->v_mob_ident = TRUE; memcpy (&ciph_comp->mob_ident, &rr_data->ms_data.imei, sizeof (T_mob_ident)); } else { ciph_comp->v_mob_ident = FALSE; } ciph_comp->msg_type = U_CIPH_COMP; /* * send response to the network */ for_dat_data_req (dl_data_req); /* * Indicate changed ciphering mode to MM. * Any supression of ciphering information to MMI/ACI will * be done by the upper layers. */ dat_code_ciphering_to_mm (rr_data->sc_data.ciph_on); EM_CIPHERING_CMD; } } PFREE (dl_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_freq_redef | +--------------------------------------------------------------------+ PURPOSE : Reception of a frequency redefinition message. */ GLOBAL void dat_for_freq_redef (T_DL_DATA_IND *dl_data_ind, T_D_FREQ_REDEF *freq_redef, T_LIST *cell_chan_desc) { GET_INSTANCE_DATA; T_start start; T_LIST hop_list; UBYTE mob_alloc[65]; TRACE_FUNCTION ("dat_for_freq_redef()"); if (dat_check_error_flag (SEND_RR_STATUS)) { /* * the check in the formatter has passed */ memcpy (&rr_data->sc_data.chan_desc, &freq_redef->chan_desc, sizeof (T_chan_desc)); /* * convert the mobile allocation from the message format * to a list of 1-bit positions to build the hopping list. */ att_bits_to_byte (mob_alloc, freq_redef->mob_alloc.c_mac, freq_redef->mob_alloc.mac); dat_set_last_used_channel (&rr_data->sc_data.chan_desc); if (freq_redef->v_cell_chan_desc) { /* * if the message contains a new cell channel description * copy the new one, else use the old one. */ srv_copy_list (&rr_data->sc_data.cd.cell_chan_desc, cell_chan_desc, sizeof (T_LIST)); rr_data->sc_data.cd.v_cell_chan_desc = WITH_CONTENT; } if (rr_data->sc_data.cd.v_cell_chan_desc NEQ NO_CONTENT) { /* * create the hopping list from cell channel description and * mobile allocation. */ if(! srv_create_chan_mob_alloc (&rr_data->sc_data.cd.cell_chan_desc, &hop_list, mob_alloc)) { U32 st = 51*((26 + freq_redef->start_time.t3 - freq_redef->start_time.t2 )%26) + freq_redef->start_time.t3 + 1326*freq_redef->start_time.t1; U32 ct = dl_data_ind->fn%STARTING_TIME_INTERVAL; #if defined(_SIMULATION_) TRACE_EVENT_WIN_P5 ("D_FREQ_REDEF: t1=%u t2=%u t3=%u, st=%u, ct=%u", freq_redef->start_time.t1, freq_redef->start_time.t2, freq_redef->start_time.t3, st, ct); TRACE_EVENT_WIN_P2 ("D_FREQ_REDEF: (st-ct) %u <= %u ?", ((STARTING_TIME_INTERVAL + st - ct)%STARTING_TIME_INTERVAL), STARTING_TIME_INTERVAL1); #endif if(((STARTING_TIME_INTERVAL + st - ct)%STARTING_TIME_INTERVAL) <= STARTING_TIME_INTERVAL1) { /*XXX this should only be done if the starting time has not yet expired */ dat_send_rr_status_msg(RRC_FREQ_NOT_IMPL); } else { /* * 3GPP TS 04.18, section 3.4.5.1 * Frequency redefinition procedure, abnormal cases: * If the mobile station receives a FREQUENCY REDEFINITION message * with a Mobile Allocation IE indexing frequencies that are not all * in one band and a Starting Time IE indicating a time that has * elapsed, then the mobile station shall locally abort the radio * connection and, if permitted, attempt Call Re-establishment. * * Inform MM about a radio link failure and start cell reselection. * It would be possible to create a new cause but RLF does exactly * what is needed and this is really 'some kind of' RLF. */ rr_data->net_lost = TRUE; att_code_rr_abort_ind (RRCS_ABORT_RAD_LNK_FAIL); att_stop_dedicated(); } } else { /* * copy start time for the new hopping list */ start.v_start = TRUE; start.t1 = freq_redef->start_time.t1; start.t2 = freq_redef->start_time.t2; start.t3 = freq_redef->start_time.t3; /* * configure layer 1 with the new hopping list */ dat_code_mph_freq_redef_req (&start, &hop_list); } } } PFREE (dl_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_handov_cmd | +--------------------------------------------------------------------+ PURPOSE : Reception of a handover command message. */ GLOBAL void dat_for_handov_cmd (T_DL_DATA_IND *dl_data_ind, T_D_HANDOV_CMD *handov_cmd, T_LIST *cell_chan_desc, T_LIST *hop_list_after, T_LIST *hop_list_before) { GET_INSTANCE_DATA; UBYTE mob_alloc [65]; TRACE_FUNCTION ("dat_for_handov_cmd()"); rr_data->dyn_config.fho = 0; /* * dynamic configuration command : IHO * Lock the DUT to the cell it is already camping - * Ignore the Handover command message and send an * Handover failure message to the network. */ if(rr_data->dyn_config.iho AND (rr_data->sc_data.ch_mode EQ CM_AMR)) { TRACE_EVENT("D_HANDOV_CMD : IHO"); for_set_content_error (RRC_CHANNEL_MODE); } switch (rr_data->ms_data.error.cs) { /* * in case of mandatory info element error, * the message is returned immediately. */ /* case RRC_INVALID_MAN_INFO: this value is currently never set */ case RRC_COND_IE_ERROR: { /* * build a RR status message. */ dat_send_rr_status_msg(rr_data->ms_data.error.cs); PFREE (dl_data_ind); break; } case RRC_INCORRECT_MSG: { /* * If a structurally correct message has been detected, * containing erroneous data, an Assignment Failure message * is sent back. */ /* * Even though it's not possible to go onto the new channel * we still need to suspend the current link and send the * HANDOVER FAILURE command via a priority DL_RECONNECT_REQ. * This ensures DL will halt processing anything in its * buffer until it has sent this message onto the nw */ for_suspend_layer_2 (); dat_send_handov_fail_msg(rr_data->ms_data.error.val); RR_EM_SET_HANDOVER_FAIL_CAUSE(rr_data->ms_data.error.val); PFREE (dl_data_ind); break; } default: /* * the message check has passed. * first of all suspend current layer 2 link */ TRACE_EVENT_P1 ("HO:default (%02x)", rr_data->ms_data.error.cs); for_suspend_layer_2 (); /* * set for the optional information elements * of the handover message the default value * to the current serving cell value. */ rr_data->cr_data.ch_mode = rr_data->sc_data.ch_mode; rr_data->cr_data.ciph_on = rr_data->sc_data.ciph_on; rr_data->cr_data.algo = rr_data->sc_data.algo; rr_data->cr_data.cd.v_cell_chan_desc = rr_data->sc_data.cd.v_cell_chan_desc; memcpy (&rr_data->cr_data.cd.cell_chan_desc, &rr_data->sc_data.cd.cell_chan_desc, sizeof (T_LIST)); /* * if AMR is supported set the default values * to the current serving cell values. */ if(rr_data->sc_data.ch_mode EQ CM_AMR) { memcpy(&rr_data->cr_data.amr_conf, &rr_data->sc_data.amr_conf, sizeof (T_multirate_conf)); } else { /* * AMR is not supported, therefore set some dummy values. This is necessary because * the later Layer1 configuration must include an AMR configuration!! */ memset(&rr_data->cr_data.amr_conf, 0, sizeof (T_multirate_conf)); } /* * set BSIC, BCCH channel number and channel description from * the handover command. */ rr_data->nc_data[CR_INDEX].bsic = (handov_cmd->cell_desc.ncc << 3) + handov_cmd->cell_desc.bcc; rr_data->nc_data[CR_INDEX].arfcn = handov_cmd->cell_desc.bcch_arfcn_lo + (handov_cmd->cell_desc.bcch_arfcn_hi << 8); memcpy (&rr_data->cr_data.chan_desc, &handov_cmd->chan_desc_after, sizeof (T_chan_desc)); if (handov_cmd->v_synch_ind) { /* * store the Handover synchronisation information if available. */ memcpy (&rr_data->ms_data.ho_type, &handov_cmd->synch_ind, sizeof (T_synch_ind)); } else { /* * else set the values to the default values. */ rr_data->ms_data.ho_type.rot = TIME_DIFF_NO; rr_data->ms_data.ho_type.nci = TRUE; rr_data->ms_data.ho_type.si = SYI_NON_SYNCH; } if (rr_data->ms_data.ho_type.si EQ SYI_PSEUDO_SYNCH AND ! rr_data->ms_data.classmark2.ps) { /* * if the handover requests a pseudo synchronized handover * and the mobile does not support this, a handover failure * message is send and the procedure is aborted with * reconnection to the old channel. */ dat_send_handov_fail_msg(RRC_INCORRECT_MSG); RR_EM_SET_HANDOVER_FAIL_CAUSE(RRC_INCORRECT_MSG); PFREE (dl_data_ind); return; } else { if (handov_cmd->v_cell_chan_desc) { /* * if the handover command contains a new cell channel description * copy the new list. */ srv_copy_list (&rr_data->cr_data.cd.cell_chan_desc, cell_chan_desc, sizeof (T_LIST)); rr_data->cr_data.cd.v_cell_chan_desc = WITH_CHANGED_CONTENT; } if (handov_cmd->v_chan_mode) { /* * store a new channel mode if available. */ rr_data->cr_data.ch_mode = handov_cmd->chan_mode; } /* * If AMR is signalled check if new multi-rate speech codec is part of the handover cmd * otherwise use default values set earlier. If AMR is not signalled use the dummy values * instead either set earlier. */ /* Implements RR Clone findings #9 */ dat_cr_data_multirate_conf(handov_cmd->v_multirate_conf, &handov_cmd->multirate_conf); if (handov_cmd->v_ciph_mode_set) { /* * if the message contains cipher mode parameter * copy the parameters */ rr_data->cr_data.ciph_on = handov_cmd->ciph_mode_set.sc; rr_data->cr_data.algo = handov_cmd->ciph_mode_set.algo_ident; /* * if ciphering is already enabled and the handover command * requests ciphering again, the procedure is aborted with * a handover failure message. */ if (rr_data->cr_data.ciph_on EQ CIPH_ON AND rr_data->sc_data.ciph_received EQ FALSE) { dat_send_handov_fail_msg(RRC_PROT_UNSPECIFIED); RR_EM_SET_HANDOVER_FAIL_CAUSE(RRC_PROT_UNSPECIFIED); PFREE (dl_data_ind); return; } } if(handov_cmd->v_mob_alloc_after) { if(dat_for_handover_mob_alloc(mob_alloc, hop_list_after, (T_VOID_STRUCT *) &handov_cmd->mob_alloc_after,dl_data_ind)) return; } if(handov_cmd->v_mob_alloc_before) { if(dat_for_handover_mob_alloc(mob_alloc, hop_list_before, (T_VOID_STRUCT *) &handov_cmd->mob_alloc_before,dl_data_ind)) return; } /* * Handover resets a SAPI 3 connection for SMS */ SET_STATE (STATE_SAPI_3, SMS_IDLE); PFREE (dl_data_ind); { /* * All Parameters are checked * Now the handover is started */ PALLOC (dedicated_req, MPH_DEDICATED_REQ); memset (dedicated_req, 0, sizeof (T_MPH_DEDICATED_REQ)); if (handov_cmd->v_start_time) { /* * copy starting time if available. */ dedicated_req->start.v_start = TRUE; dedicated_req->start.t1 = handov_cmd->start_time.t1; dedicated_req->start.t2 = handov_cmd->start_time.t2; dedicated_req->start.t3 = handov_cmd->start_time.t3; } /* * Calculate observed time difference */ { UBYTE i1; ULONG fn_offset; rr_data->sc_data.observed_ta = 0; for (i1 = 0; i1< rr_data->ms_data.measurement_report.ncells.no_of_ncells; i1++) { /* * find the handover cell inn the neighbourcells of the last measurement report */ if (rr_data->nc_data[CR_INDEX].arfcn EQ rr_data->ms_data.measurement_report.ncells.arfcn[i1]) { /* * According to 05.10 OTD is defined as the timing difference * between BTS0 and BTS1 ( system time in BTS 0 minus that of * BTS 1..), with BTS1 as the new cell (neighbour cell, HO * Target cell) and BTS0 and the current cell (serving cell) */ fn_offset = (HYPERFRAME - rr_data->ms_data.measurement_report.ncells.frame_offset[i1]) % HYPERFRAME; /* * calculate the observed time difference from the relative * time difference of neighbourcell and serving cell * (given by time_alignment and frame offset) and the observed * time difference of the serving cell (coming from timing advance * in layer 1 header of the downlink SACCH messages). */ /* * A.1.3 of 3GPP TS 05.10 * after successful handover, either synchronized, * non-synchronized or pseudo-synchronized, the MS shall provide * to BTS 1 the value of OTD + t0 in the "HANDOVER COMPLETE" * message. * * NOTE : measurement_report.otd is the TA sent by the * network in downlink SACCH. TA is roundtrip propogation delay in bit periods. * t0 denotes the "one way" line of sight propagation delay between * the MS and BTS 0, in "half bits". * t0 = measurement_report.otd * 2 / 2. */ rr_data->sc_data.observed_ta = ( (rr_data->ms_data.measurement_report.ncells.time_alignmt[i1] + fn_offset* QUARTER_BITS_PER_FRAME)/2 + rr_data->ms_data.measurement_report.otd ) % 2097152; } } } dedicated_req->ho_param.ho_nci = rr_data->ms_data.ho_type.nci; /* * Set the handover mode */ switch (rr_data->ms_data.ho_type.si) { case SYI_NON_SYNCH: /* * asynchronous handover */ dedicated_req->mod = MODE_ASYNC_HANDOVER; break; case SYI_NORM_SYNCH: /* * synchronous handover */ rr_data->sc_data.new_ta = rr_data->ms_data.measurement_report.otd/2; att_set_tim_advance_info(); dedicated_req->mod = MODE_SYNC_HANDOVER; break; case SYI_PRE_SYNCH: /* * pre-synchronized handover */ dedicated_req->mod = MODE_PRE_SYNC_HANDOVER; if (handov_cmd->v_time_advance) /* * if the handover command contains a new timing advance */ dedicated_req->tr_para.tav = handov_cmd->time_advance.ta; else /* * else set the default value 1 */ dedicated_req->tr_para.tav = 1; rr_data->sc_data.new_ta = dedicated_req->tr_para.tav * 2; att_set_tim_advance_info(); break; case SYI_PSEUDO_SYNCH: /* * pseudo-synchronized handover */ dedicated_req->mod = MODE_PSEUDO_SYNC_HANDOVER; dedicated_req->tr_para.tav = handov_cmd->time_diff; rr_data->sc_data.new_ta = dedicated_req->tr_para.tav; att_set_tim_advance_info(); break; } /* * Set Channel Type */ dedicated_req->ch_type.ch = handov_cmd->chan_desc_after.chan_type; dedicated_req->ch_type.tn = handov_cmd->chan_desc_after.tn; dedicated_req->ch_type.tsc = handov_cmd->chan_desc_after.tsc; dedicated_req->ch_type.h = handov_cmd->chan_desc_after.hop; if (handov_cmd->chan_desc_after.hop EQ H_NO) dedicated_req->ch_type.arfcn = handov_cmd->chan_desc_after.arfcn; else { dedicated_req->ch_type.maio = handov_cmd->chan_desc_after.maio; dedicated_req->ch_type.hsn = handov_cmd->chan_desc_after.hsn; /* CSI-LLD section:4.1.1.11 * This function Updates the black list with the MA list received * in the handover command */ cs_remove_BA_MA_from_black_list(rr_data->cs_data.region , hop_list_after); srv_create_list (hop_list_after, dedicated_req->ch_type.ma, MAX_MA_CHANNELS, TRUE, 0); } dedicated_req->bsic = rr_data->nc_data[CR_INDEX].bsic & 0x3F; dedicated_req->arfcn = rr_data->nc_data[CR_INDEX].arfcn; dedicated_req->ho_param.ho_ref = handov_cmd->handov_ref; dedicated_req->ho_param.ho_pow = handov_cmd->pow_cmd_access.pow; dedicated_req->ho_param.ho_acc_type = handov_cmd->pow_cmd_access.atc; dedicated_req->tr_para.mode = rr_data->cr_data.ch_mode; /* * Set multi-rate speech codec */ dedicated_req->amr_conf.nscb = rr_data->cr_data.amr_conf.nscb; dedicated_req->amr_conf.icmi = rr_data->cr_data.amr_conf.icmi; dedicated_req->amr_conf.st_mode = rr_data->cr_data.amr_conf.st_mode; dedicated_req->amr_conf.acs = rr_data->cr_data.amr_conf.set_amr; /* * valid flag for the threshold and hystersis values. amr_conf.c_cod_prop * defines the number of threshold and hystersis values. */ dedicated_req->amr_conf.v_cod_prop = rr_data->cr_data.amr_conf.v_cod_prop; if(dedicated_req->amr_conf.v_cod_prop) { int i; dedicated_req->amr_conf.c_cod_prop = rr_data->cr_data.amr_conf.c_cod_prop; for(i=0; i<dedicated_req->amr_conf.c_cod_prop; i++) memcpy(&dedicated_req->amr_conf.cod_prop[i], &rr_data->cr_data.amr_conf.cod_prop[i], sizeof(T_cod_prop)); } /* * Set Channel Type before starting time */ if (handov_cmd->v_chan_desc_before EQ FALSE) dedicated_req->ch_type2.ch = NOT_PRESENT_8BIT; else { /* Implements RR Clone findings #22 */ dat_dedicated_req_ch_type2(&dedicated_req->ch_type2, &handov_cmd->chan_desc_before, hop_list_before); } if (rr_data->cr_data.ciph_on) { /* * set cipher parameter */ dedicated_req->ciph.stat = rr_data->cr_data.ciph_on; dedicated_req->ciph.algo = rr_data->cr_data.algo; memcpy (dedicated_req->ciph.kc, rr_data->ms_data.kc, KC_STRING_SIZE); } /* * clear neighbourcell lists for the new cell. */ srv_clear_list (&rr_data->sc_data.cd.ncell_list); srv_clear_list (&rr_data->sc_data.five_ter_list); att_clean_buf (IND_ALL_DEDI_SI); rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS; SET_STATE (STATE_DAT, DAT_HANDOVER); #if defined (REL99) && defined (TI_PS_FF_EMR) /*clear EMR parameters also, if present*/ if (rr_data->sc_data.enh_para_status EQ ENH_PARA_DEDICATED ) { /*discard the enhanced para that were related to BA(SACCH) before HO*/ rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE; memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS); for_set_default_emr_data(&rr_data->sc_data.emr_data_current); /*Indicate to ALR that enhanced para are invalid*/ attf_send_enh_para_to_alr(rr_data->sc_data.emr_data_current.rep_type, &rr_data->sc_data.emr_data_current.enh_para); } #endif RR_EM_GET_HOPPING_CHANNEL (dedicated_req->ch_type.ma, dedicated_req->ch_type2.ma, dedicated_req->start.v_start,dedicated_req->ch_type2.maio); EM_HANDOVER_CMD; #if defined FF_EOTD if ( rr_data->eotd_req_id NEQ NOT_PRESENT_16BIT ) { PALLOC (rrlc_error_ind, RRLC_ERROR_IND); rrlc_error_ind->cause = LCS_HANDOVER; rr_data->eotd_req_id = NOT_PRESENT_16BIT; PSENDX (LC, rrlc_error_ind); } #endif /* FF_EOTD */ /* * configure layer 1. */ PSENDX (PL, dedicated_req); } } /* else */ } /* switch */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : stop_rach_and_enter_idle | +--------------------------------------------------------------------+ PURPOSE : Invalid frequency list received during Immediate Assignment procedure. The sending of Channel Request messages is stopped and Idle Mode entered. */ LOCAL void stop_rach_and_enter_idle(void) { PALLOC (mph_random_access_req, MPH_RANDOM_ACCESS_REQ); TRACE_ERROR ("invalid frequencies (Frequency Hopping)"); TIMERSTOP (T3122); TIMERSTOP (T3126); /* * Stop sending Random Burst */ memset (&mph_random_access_req->send_mode, 0, sizeof (T_send_mode)); PSENDX (PL, mph_random_access_req); dat_send_release_ind (RRCS_INVALID_HOP_FREQ); /*SET_STATE (STATE_DAT, DAT_IDLE); att_build_idle_req (SC_INDEX, MODE_CELL_SELECTION);*/ #ifdef GPRS att_start_cell_reselection_gprs (CELL_RESELECTION_RACH); #else att_start_cell_reselection (CELL_RESELECTION_RACH); #endif } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_imm_assign | +--------------------------------------------------------------------+ PURPOSE : Reception of an immediate assignment message. */ GLOBAL void dat_for_imm_assign (T_MPH_UNITDATA_IND *mph_unitdata_ind, T_D_IMM_ASSIGN *imm_assign) { GET_INSTANCE_DATA; T_SC_DATA *rrd = &rr_data->sc_data; T_start start; UBYTE mob_alloc [65]; T_LIST hop_list_bef; T_LIST hop_list_after; UBYTE maio; T_IA_REST ia_rest; UBYTE index = 0; TRACE_FUNCTION ("dat_for_imm_assign()"); switch (GET_STATE (STATE_DAT)) { #ifdef GPRS case DAT_IDLE: TRACE_EVENT("check dl idle"); dat_check_imm_assign_pch (mph_unitdata_ind, imm_assign); break; #endif case DAT_IMM_ASS: if (dat_check_error_flag (SEND_NO_RR_STATUS)) { #ifdef GPRS TRACE_EVENT("check dl pa"); if(GET_STATE(STATE_GPRS) EQ GPRS_PAM_BCCH AND dat_check_imm_assign_pch(mph_unitdata_ind, imm_assign)) return; #endif if (dat_compare_request_ref (&imm_assign->req_ref, &index)) { /* * the request reference in the immediate assignment * message matches to one of the last three channel * request messages. */ TRACE_EVENT("matched"); /* * check the channel description */ if(imm_assign->v_chan_desc) for_check_channel_descr (&imm_assign->chan_desc); /* was channel description ok? */ if(!dat_check_error_flag (SEND_NO_RR_STATUS)) return; #ifdef GPRS if(dat_check_gprs_imm_ass (mph_unitdata_ind, imm_assign, index)) return; #endif if (imm_assign->v_chan_desc) { if (imm_assign->chan_desc.hop AND imm_assign->mob_alloc.c_mac) { TRACE_EVENT ("create mob alloc (after st)"); /* * if the message contains a mobile allocation * build a hopping list together with the cell * channel description of system information * type 1 message. */ att_bits_to_byte (mob_alloc, imm_assign->mob_alloc.c_mac, imm_assign->mob_alloc.mac); if( rrd->cd.v_cell_chan_desc EQ NO_CONTENT OR !srv_create_chan_mob_alloc (&rrd->cd.cell_chan_desc, &hop_list_after, mob_alloc)) { stop_rach_and_enter_idle(); return; } } else { /* * else clear the hopping list */ srv_clear_list (&hop_list_after); } } else { TRACE_EVENT("IMM ASS discarded: neither sent to GRR nor channel description found"); return; /* for non-packet access we need a channel description */ } TRACE_EVENT("now get started"); if (imm_assign->v_start_time) { /* * if the message contains a starting time, * store the starting time. */ start.v_start = TRUE; start.t1 = imm_assign->start_time.t1; start.t2 = imm_assign->start_time.t2; start.t3 = imm_assign->start_time.t3; } else { /* * clear the starting time. */ memset (&start, 0, sizeof (T_start)); } /* * decode IA Rest Octet */ memset (&ia_rest, 0, sizeof (T_IA_REST)); ia_rest.ia_p = imm_assign->ia_rest_oct.flag_2bit; ia_rest.ia_maio = imm_assign->ia_rest_oct.ia_freq_par.maio; ia_rest.c_ia_mac = imm_assign->ia_rest_oct.ia_freq_par.c_mac; if (ia_rest.c_ia_mac > 9) ia_rest.c_ia_mac = 9; memcpy (ia_rest.ia_mac, &imm_assign->ia_rest_oct.ia_freq_par.mac, ia_rest.c_ia_mac); if (imm_assign->v_start_time AND imm_assign->chan_desc.hop AND ia_rest.ia_p EQ 2) { /* * calculate frequency list before starting time */ TRACE_EVENT("create mob alloc (before st)"); maio = ia_rest.ia_maio; att_bits_to_byte (mob_alloc, ia_rest.c_ia_mac, ia_rest.ia_mac); if(rrd->cd.v_cell_chan_desc EQ NO_CONTENT OR !srv_create_chan_mob_alloc (&rrd->cd.cell_chan_desc, &hop_list_bef, mob_alloc)) { stop_rach_and_enter_idle(); return; } } else { maio = 0; srv_clear_list (&hop_list_bef); } /* * stop T3122 and T3126 if they are running. */ TIMERSTOP (T3122); TIMERSTOP (T3126); SET_STATE (STATE_DAT, DAT_IMM_ASS_1); /* * store channel description */ memcpy (&rrd->chan_desc, &imm_assign->chan_desc, sizeof (T_chan_desc)); /* * the initial channel mode is always signalling only */ rrd->ch_mode = MODE_SIG_ONLY; /* * set the timing advance */ rrd->new_ta = imm_assign->time_advance.ta; att_set_tim_advance_info(); dat_set_last_used_channel (&rrd->chan_desc); /* * configure layer 1 */ dat_code_mph_imm_assign_req (&start, rr_data->nc_data[SC_INDEX].select_para.ms_txpwr_max_cch, maio, &hop_list_after, &hop_list_bef); } EM_IMMEDIATE_ASSIGNMENT; } break; default: break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_imm_assign_ext | +--------------------------------------------------------------------+ PURPOSE : Reception of the immediate assignment extended message. */ GLOBAL void dat_for_imm_assign_ext (T_MPH_UNITDATA_IND *mph_unitdata_ind, T_D_IMM_ASSIGN_EXT *imm_assign_ext) { GET_INSTANCE_DATA; USHORT i; T_start start; UBYTE mob_alloc [65]; T_SC_DATA *rrd = &rr_data->sc_data; T_LIST hop_list_after; T_LIST hop_list_bef; UBYTE index; T_chan_desc *p_chan_desc; TRACE_FUNCTION ("dat_for_imm_assign_ext()"); switch (GET_STATE (STATE_DAT)) { case DAT_IMM_ASS: if (dat_check_error_flag (SEND_NO_RR_STATUS)) { /* * the message check in the formatter has passed */ for (i=0; i<2; i++) { /* * the immediate assignment extended message contains * two request references. */ if (dat_compare_request_ref ((i EQ 0) ? &imm_assign_ext->req_ref : (T_req_ref *)&imm_assign_ext->req_ref_2, &index)) { #ifdef GPRS dat_check_imm_ass_ext (mph_unitdata_ind,(UBYTE)(i+1)); #endif /* * check channel description */ if(i EQ 0) p_chan_desc = &imm_assign_ext->chan_desc; else p_chan_desc = (T_chan_desc *)&imm_assign_ext->chan_desc_2; for_check_channel_descr (p_chan_desc); if (!dat_check_error_flag (SEND_NO_RR_STATUS)) return; /* * the request reference in the immediate assignment * extended message matches to one of the last three * channel request messages. */ if (imm_assign_ext->mob_alloc.c_mac AND p_chan_desc->hop) { /* * if the message contains a mobile allocation and * the mobile shall hop * build a frequency hopping list together with * the cell channel description of system information * type 1 message. */ att_bits_to_byte (mob_alloc, imm_assign_ext->mob_alloc.c_mac, imm_assign_ext->mob_alloc.mac); if(rrd->cd.v_cell_chan_desc EQ NO_CONTENT OR ! srv_create_chan_mob_alloc (&rr_data->sc_data.cd.cell_chan_desc, &hop_list_after, mob_alloc)) { stop_rach_and_enter_idle(); return; } } else { /* * else clear frequency hopping list */ srv_clear_list (&hop_list_after); } /* * stop T3122 and T3126 if they are running. */ TIMERSTOP (T3122); TIMERSTOP (T3126); /* * store channel description */ memcpy (&rrd->chan_desc, p_chan_desc, sizeof (T_chan_desc)); /* * the initial channel mode is ever signalling only */ rrd->ch_mode = MODE_SIG_ONLY; /* * store the new timing advance */ rrd->new_ta = (i EQ 0) ? imm_assign_ext->time_advance.ta : imm_assign_ext->time_advance_2.ta; att_set_tim_advance_info(); dat_set_last_used_channel (&rrd->chan_desc); if (imm_assign_ext->v_start_time) { /* * copy starting time if available */ start.v_start = TRUE; start.t1 = imm_assign_ext->start_time.t1; start.t2 = imm_assign_ext->start_time.t2; start.t3 = imm_assign_ext->start_time.t3; } else memset (&start, 0, sizeof (T_start)); srv_clear_list (&hop_list_bef); SET_STATE (STATE_DAT, DAT_IMM_ASS_1); /* * configure layer 1. */ dat_code_mph_imm_assign_req (&start, rr_data->nc_data[SC_INDEX].select_para.ms_txpwr_max_cch, 0, &hop_list_after, &hop_list_bef); EM_IMMEDIATE_ASSIGNMENT_EXT; return; } } } break; default: break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_imm_assign_rej | +--------------------------------------------------------------------+ PURPOSE : Reception of an immediate assignment reject message. */ GLOBAL void dat_for_imm_assign_rej (T_D_IMM_ASSIGN_REJ *imm_assign_rej) { GET_INSTANCE_DATA; UBYTE index; TRACE_FUNCTION ("dat_for_imm_assign_rej()"); switch (GET_STATE (STATE_DAT)) { case DAT_IMM_ASS: if (dat_check_error_flag (SEND_NO_RR_STATUS)) { /* * the message has passed the checks in the formatter. */ if (! IS_TIMER_ACTIVE(T3122)) { /* * Only if T3122 is not running, that means there is no * immediate assignment reject message taken in account * before. */ BOOL result = FALSE; UBYTE t3122 = 0; if (dat_compare_request_ref (&imm_assign_rej->req_ref, &index)) { /* * if the request reference matches to one of the last * three channel requests, set the result of TRUE and * store the timer value. This is checked for the up to * four request references in the message. */ result = TRUE; t3122 = imm_assign_rej->t3122; } else if (dat_compare_request_ref ((T_req_ref *)&imm_assign_rej->req_ref_2, &index)) { result = TRUE; t3122 = imm_assign_rej->t3122_2; } else if (dat_compare_request_ref ((T_req_ref *)&imm_assign_rej->req_ref_3, &index)) { result = TRUE; t3122 = imm_assign_rej->t3122_3; } else if (dat_compare_request_ref ((T_req_ref *)&imm_assign_rej->req_ref_4, &index)) { result = TRUE; t3122 = imm_assign_rej->t3122_4; } if (result) { /* * a request reference has matched */ #ifdef GPRS if (dat_check_imm_ass_rej (t3122) EQ FALSE) #endif if (t3122 NEQ 0) { /* * start T3122 if a value is defined */ TIMERSTART (T3122, T3122_VALUE(t3122)); } TRACE_EVENT("set rej_rec"); rr_data->imm_ass_rej_rec = TRUE; rr_data->ms_data.all_conf_received = TRUE; /* * Start T3126 if the timer is not running yet. */ /* Implements Measure#32: Row 217,218 */ (IS_TIMER_ACTIVE(T3126)) ? TRACE_TIMER ( "T3126 re-start") : TRACE_TIMER ( "T3126 start"); if (! IS_TIMER_ACTIVE(T3126)) { TIMERSTART (T3126, T3126_VALUE); /* * Stop sending Random Burst */ { PALLOC (mph_random_access_req, MPH_RANDOM_ACCESS_REQ); memset (&mph_random_access_req->send_mode, 0, sizeof (T_send_mode)); PSENDX (PL, mph_random_access_req); } } } EM_IMMEDIATE_ASSIGNMENT_REJECT; } } break; default: break; } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_ext_meas_order | +--------------------------------------------------------------------+ PURPOSE : Reception of an extended measurement order message. */ GLOBAL void dat_for_ext_meas_order (T_D_EXT_MEAS_ORDER *ext_meas_order) { GET_INSTANCE_DATA; UBYTE new_seq; T_LIST *chan_list; PALLOC (mph_emo_req, MPH_EMO_REQ); TRACE_FUNCTION ("dat_for_ext_meas_order()"); /* * Decode EMO: new_seq */ ccd_decodeByte (ext_meas_order->ext_meas_freq.b_ext_meas_freq, (USHORT)(ext_meas_order->ext_meas_freq.o_ext_meas_freq+3), 1, &new_seq); /* * Ignore EMO if EMO proc already running and new SEQ EQ current SEQ. */ if ( rr_data->emo_arfcn NEQ NULL AND rr_data->emo_seq EQ new_seq ) { PFREE ( mph_emo_req ); return; } /* * Decode and store EMO frequency list */ if ( rr_data->emo_arfcn EQ NULL ) { MALLOC ( rr_data->emo_arfcn, MAX_EMO_CHANNELS * sizeof (rr_data->emo_arfcn[0]) ); } rr_data->emo_seq = new_seq; MALLOC ( chan_list, sizeof ( T_LIST ) ); for_create_channel_list ( (T_f_range*) &ext_meas_order->ext_meas_freq, chan_list); /* * Function srv_create_list_dedicated ensures that the frequencies are sorted * and the number of frequencies are limited to 21 frequencies */ rr_data->c_emo_arfcn = srv_create_list (chan_list, rr_data->emo_arfcn, MAX_EMO_CHANNELS, FALSE, 0); MFREE ( chan_list ); memcpy ( &mph_emo_req->arfcn[0], &rr_data->emo_arfcn[0], rr_data->c_emo_arfcn * sizeof (rr_data->emo_arfcn[0]) ); mph_emo_req->c_arfcn = srv_remove_frequencies_in_array_gen ( &mph_emo_req->arfcn[0], rr_data->c_emo_arfcn ); /* * Create newBA_ID, save as currentBA_ID. */ rr_data->ba_id = RR_ALLOCATE_NEW_BA ( rr_data->ba_id ); mph_emo_req->ba_id = rr_data->ba_id; /* * EMOtime = 10 seconds and request PL to perform extended measurement. */ TIMERSTART (TIM_EXT_MEAS, 10000); PSENDX (PL, mph_emo_req); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_mph_emo_meas_ind | +--------------------------------------------------------------------+ PURPOSE : Measurement report for the Extended Measurment procedure has been received. */ GLOBAL void dat_mph_emo_meas_ind (T_MPH_EMO_MEAS_IND *mph_emo_meas_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("att_mph_emo_meas_ind()"); switch (GET_STATE (STATE_DAT)) { case DAT_DEDICATED: if ( rr_data->emo_arfcn NEQ NULL AND mph_emo_meas_ind->ba_id EQ rr_data->ba_id ) { dat_code_ext_meas_report (mph_emo_meas_ind); dat_emo_stop ( TRUE ); } else { /* * Build an invalid measurement reports */ MCAST (meas, U_MEAS_REP); PALLOC_MSG (dl_unitdata_req, DL_UNITDATA_REQ, U_MEAS_REP); memset (&dl_unitdata_req->sdu.buf[0], 0, dl_unitdata_req->sdu.o_buf / BITS_PER_BYTE); memset (meas, 0, sizeof (T_U_MEAS_REP)); meas->msg_type = U_MEAS_REP; meas->meas_result.meas_valid = 1; for_dat_unitdata_req (dl_unitdata_req); } break; default: break; } PFREE (mph_emo_meas_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_emo_stop | +--------------------------------------------------------------------+ PURPOSE : Stop the Extended Measurement Order procedure. */ GLOBAL void dat_emo_stop (BOOL send_ncell_req ) { GET_INSTANCE_DATA; if ( rr_data->emo_arfcn NEQ NULL ) { MFREE (rr_data->emo_arfcn); rr_data->emo_arfcn = NULL; /* restore the neighbour cell description which was used prior EMO */ if ( send_ncell_req AND (rr_data->sc_data.cd.sys_info_read & (SYS_INFO_5_READ | SYS_INFO_5BIS_READ | SYS_INFO_5TER_READ) ) ) att_code_mph_ncell_req_dedicated(); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_l3_data_ind | +--------------------------------------------------------------------+ PURPOSE : Reception of a layer 3 message for upper layers. */ GLOBAL void dat_for_l3_data_ind (T_DL_DATA_IND *dl_data_ind) { GET_INSTANCE_DATA; /* RR_DATA_IND is not the same as DL_DATA_IND anymore because of the new * member fn (frame number) of T_DL_DATA_IND which is not contained in * T_RR_DATA_IND. */ PALLOC_SDU(rr_data_ind, RR_DATA_IND, (USHORT)(dl_data_ind->sdu.l_buf+dl_data_ind->sdu.o_buf)); TRACE_FUNCTION ("dat_for_l3_data_ind()"); if (dl_data_ind->sapi EQ SAPI_3) { /* * if it is a SMS message, this is implicitly an * indication for an established SAPI 3 link */ SET_STATE (STATE_SAPI_3, SMS_ESTABLISHED); } rr_data_ind->sdu.l_buf = dl_data_ind->sdu.l_buf; rr_data_ind->sdu.o_buf = dl_data_ind->sdu.o_buf; memcpy(rr_data_ind->sdu.buf, dl_data_ind->sdu.buf, (dl_data_ind->sdu.l_buf+dl_data_ind->sdu.o_buf)>>3); PFREE (dl_data_ind); /* * forward the message to MM for distribution */ PSENDX (MM, rr_data_ind); } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_FOR | | STATE : code ROUTINE : dat_for_open_loop_cmd | +--------------------------------------------------------------------+ PURPOSE : Reception of a TCH OPEN LOOP COMMAND message. */ GLOBAL void dat_for_open_loop_cmd (T_DL_DATA_IND *dl_data_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION ("dat_for_open_loop_cmd()"); if (dat_test_sim_available () OR !dat_check_sim_available () ) { /* * only if a test SIM card is inserted */ if (rr_data->tch_loop_subch NEQ NOT_PRESENT_8BIT) { /* * A TCH Loop must be closed before, then * open in layer 1. */ PREUSE (dl_data_ind, loop_req, MPH_TCH_LOOP_REQ); loop_req->tch_loop = NOT_PRESENT_8BIT; PSENDX (PL, loop_req); if(rr_data->tch_loop_subch EQ TCH_LOOP_C) { /* only TCH_LOOP_C is acknowledged */ PALLOC_SDU (data_req, DL_DATA_REQ, 3*BITS_PER_BYTE); /* * set channel type and SAPI for answer */ dat_code_prr_channel (&data_req->ch_type, &data_req->sapi, rr_data->sc_data.chan_desc.chan_type); TRACE_EVENT_P1 ( "Value of tch_loop_subch %x", rr_data->tch_loop_subch); /* * do not use CCD for the response */ data_req->sdu.l_buf = 24; data_req->sdu.o_buf = ENCODE_OFFSET; /*lint -e415 -e416 Likely access of out-of-bounds pointer*/ data_req->sdu.buf [0] = 0; data_req->sdu.buf [1] = 0; data_req->sdu.buf [2] = 0; data_req->sdu.buf [3] = 0x0F; /* TI=0, PD = TST */ data_req->sdu.buf [4] = 0x06; /* MT = Open Loop Cmd */ data_req->sdu.buf [5] = 0x81; /* IE acknowledge */ /*lint +e415 +e416 Likely access of out-of-bounds pointer*/ TRACE_EVENT ("DL_DATA_REQ (RR message)"); EM_TCH_LOOP_OPEN; PSENDX (DL, data_req); } /* tch loop "open" */ rr_data->tch_loop_subch = NOT_PRESENT_8BIT; } else { PFREE (dl_data_ind); } } else { PFREE (dl_data_ind); } } #if defined FF_EOTD /* +------------------------------------------------------------------------------ | Function : rr_applic_rx_init +------------------------------------------------------------------------------ | Description : Initialize the data structures related to | Application Information Transfer | Reference: 3GPP TS 04.18, 3.4.21.3 | | Parameters : The downlink (RX) part of the APDU structure. | +------------------------------------------------------------------------------ */ GLOBAL void rr_applic_rx_init ( T_APPLIC_RX *applic_rx) { applic_rx->state = SAI_NULL; if ( applic_rx->rrrrlp_data_ind NEQ NULL ) { PFREE ( applic_rx->rrrrlp_data_ind ) } applic_rx->rrrrlp_data_ind = NULL; #ifdef REL99 /* Send RRLP procedure stop indication to MM*/ { PALLOC (rr_rrlp_stop_ind, RR_RRLP_STOP_IND); PSENDX (MM, rr_rrlp_stop_ind); } #endif TIMERSTOP ( TAPDU ); } /* +------------------------------------------------------------------------------ | Function : rr_applic_rx_msg_store +------------------------------------------------------------------------------ | Description : Store the first segment of an APDU. | Reference: 3GPP TS 04.18, 3.4.21.3.2 | | Parameters : The first part of the APDU. | +------------------------------------------------------------------------------ */ LOCAL void rr_applic_rx_msg_store ( T_B_APPLIC_INFO *b_applic_info ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; T_apdu_data *apdu_data = &b_applic_info->apdu_data; UBYTE size = apdu_data->c_apdu_info; T_sdu *sdu; PALLOC_SDU ( rrrrlp_data_ind, RRRRLP_DATA_IND, (USHORT)(size * BITS_PER_BYTE) ); if ( applic_rx->rrrrlp_data_ind NEQ NULL ) { TRACE_EVENT_P1 ( "APPLIC: non empty store message found", 0 ); PFREE ( applic_rx->rrrrlp_data_ind ); } applic_rx->rrrrlp_data_ind = rrrrlp_data_ind; sdu = &applic_rx->rrrrlp_data_ind->sdu; memcpy ( &sdu->buf[0], apdu_data->apdu_info, size ); sdu->l_buf = size * BITS_PER_BYTE; sdu->o_buf = 0; } /* +------------------------------------------------------------------------------ | Function : rr_applic_rx_msg_append +------------------------------------------------------------------------------ | Description : Append segments to the APDU. | Reference: 3GPP TS 04.18, 3.4.21.3.2 | | Parameters : APDU segment to be appended. | +------------------------------------------------------------------------------ */ LOCAL int rr_applic_rx_msg_append ( T_B_APPLIC_INFO *b_applic_info ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; T_apdu_data *apdu_data = &b_applic_info->apdu_data; T_sdu *sdu = &applic_rx->rrrrlp_data_ind->sdu; /* current APDU */ T_sdu *sdu2; /* new APDU */ USHORT size_cur = (USHORT)(sdu->l_buf/BITS_PER_BYTE); /* Current size of stored APDU */ USHORT size_inf = (USHORT)apdu_data->c_apdu_info; /* size of new APDU INFOrmation */ USHORT size_tot = (USHORT)(size_cur + size_inf); /* total APDU size after append */ if ( size_tot <= MAX_APDU_SIZE*BITS_PER_BYTE ) /*lint !e648 !e650/ Overflow caused by alternative defines, not applicable to target*/ { PALLOC_SDU ( rrrrlp_data_ind, RRRRLP_DATA_IND, (USHORT)(size_tot * BITS_PER_BYTE) ); sdu2 = &rrrrlp_data_ind->sdu; memcpy ( &sdu2->buf[ 0 ], &sdu->buf [0], size_cur ); memcpy ( &sdu2->buf[size_cur], &apdu_data->apdu_info[0], size_inf ); sdu2->l_buf = (USHORT)(size_tot * BITS_PER_BYTE); sdu2->o_buf = 0; PFREE ( applic_rx->rrrrlp_data_ind ); applic_rx->rrrrlp_data_ind = rrrrlp_data_ind; return TRUE; } else { return FALSE; } } /* +------------------------------------------------------------------------------ | Function : rr_applic_rx_msg_send +------------------------------------------------------------------------------ | Description : Send the re-segmented APDU to RRRRLP. | Reference: 3GPP TS 04.18, 3.4.21.3.2 | | Parameters : The C/R bit of the last APDU segment received. | +------------------------------------------------------------------------------ */ LOCAL void rr_applic_rx_msg_send ( UBYTE cr ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; T_RRRRLP_DATA_IND *rrrrlp_data_ind = applic_rx->rrrrlp_data_ind; rrrrlp_data_ind->cr = cr; PSENDX ( RRLP, rrrrlp_data_ind ); applic_rx->rrrrlp_data_ind = NULL; applic_rx->state = SAI_NULL; TIMERSTOP ( TAPDU ); } /* +------------------------------------------------------------------------------ | Function : dat_for_applic_info_rrlp_rx_null +------------------------------------------------------------------------------ | Description : Received the first segment of an APDU. | Reference: 3GPP TS 04.18, 3.4.21.3.2 | | Parameters : b_applic_info: The first segment of an APDU. | seg: the combinbed APDU control flags | +------------------------------------------------------------------------------ */ LOCAL void dat_for_applic_info_rrlp_rx_null ( T_B_APPLIC_INFO * b_applic_info, UBYTE seg ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; TRACE_ASSERT ( applic_rx->rrrrlp_data_ind EQ NULL ); switch ( seg ) { case FIRST_SEG | LAST_SEG : /* Allowed, simple case. Forward segment and stay in state SAI_NULL */ rr_applic_rx_msg_store ( b_applic_info ); #ifdef REL99 /* Send RRLP procedure start indication to MM*/ { PALLOC (rr_rrlp_start_ind, RR_RRLP_START_IND); PSENDX (MM, rr_rrlp_start_ind); } #endif rr_applic_rx_msg_send ( b_applic_info->apdu_flags.c_r ); break; case FIRST_SEG | NOT_LAST_SEG: /* Allowed, standard case of APDU segmentation. */ /* Check length of this segment -> L2 frame must be 251 bytes, otherwise protocol error as described in 3GPP 04.18, section 3.4.21.3.3 a) */ if ( b_applic_info->apdu_data.c_apdu_info EQ APDU_FULL_L2_FRAME ) { /* store this segment, start de-segmentation */ rr_applic_rx_msg_store ( b_applic_info ); TIMERSTART ( TAPDU, 2500 /* milli seconds */ ); /* 3GPP TS 04.18, 3.4.21.3.2 */ applic_rx->state = SAI_SEGM; #ifdef REL99 /* Send RRLP procedure start indication to MM*/ { PALLOC (rr_rrlp_start_ind, RR_RRLP_START_IND); PSENDX (MM, rr_rrlp_start_ind); } #endif } else { /* Protocol error occured, remain in state SAI_NULL, discard segment (cf 3.4.21.3.3, last clause). */ } break; case NOT_FIRST_SEG | LAST_SEG : case NOT_FIRST_SEG | NOT_LAST_SEG: /* Not allowed. Protocol error as described in 3GPP 04.18, section 3.4.21.3.3 c), discard segment as described in last sentence of 3.4.21.3.3 */ break; default: TRACE_EVENT_P1 ("unexpected 'default:' seg=%d", seg ); break; } } /* +------------------------------------------------------------------------------ | Function : dat_for_applic_info_rrlp_rx_segm +------------------------------------------------------------------------------ | Description : Received second and subsequent segments of an APDU. | Reference: 3GPP TS 04.18, 3.4.21.3.2 | | Parameters : b_applic_info: A segment of an APDU. | seg: the combinbed APDU control flags | +------------------------------------------------------------------------------ */ LOCAL void dat_for_applic_info_rrlp_rx_segm ( T_B_APPLIC_INFO * b_applic_info, UBYTE seg ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; TRACE_ASSERT ( applic_rx->rrrrlp_data_ind NEQ NULL ); switch ( seg ) { case FIRST_SEG | LAST_SEG : case FIRST_SEG | NOT_LAST_SEG: /* Abnormal case, refer to 3GPP TS 04.18, 3.4.21.3.3 b), clause 2 */ /* Discard any partially reassembed APDU, enter state SAI_NULL */ rr_applic_rx_init ( applic_rx ); /* Now (re-)use the current segment, refer to 3GPP TS 04.18, 3.4.21.3.3: "...reprocess any received APDU or APDU segment that caused the error... " */ dat_for_applic_info_rrlp_rx_null ( b_applic_info, seg ); break; case NOT_FIRST_SEG | LAST_SEG : /* Normal case, end of re-segmentation, TAPDU stop, send the message to the application entity. Enter state SAI_NULL. */ if ( rr_applic_rx_msg_append ( b_applic_info ) EQ FALSE ) rr_applic_rx_init ( applic_rx ); else rr_applic_rx_msg_send ( b_applic_info->apdu_flags.c_r ); break; case NOT_FIRST_SEG | NOT_LAST_SEG: /* Normal case, re-segmetation is still ongoing. If 'append' operation fails, then return to state SAI_NULL. */ if ( rr_applic_rx_msg_append ( b_applic_info ) EQ FALSE ) rr_applic_rx_init ( applic_rx ); break; default: break; } } /* +------------------------------------------------------------------------------ | Function : dat_for_applic_info_rrlp +------------------------------------------------------------------------------ | Description : Application Information Transfer (RX) for RRRLP | Reference: 3GPP TS 04.18, 3.4.21.3 | | Parameters : b_applic_info: Segment of an APDU. | +------------------------------------------------------------------------------ */ LOCAL void dat_for_applic_info_rrlp ( T_B_APPLIC_INFO * b_applic_info ) { GET_INSTANCE_DATA; T_APPLIC_RX *applic_rx = &rr_data->applic_rx; UBYTE seg = ((b_applic_info->apdu_flags.f_seg << 1) | (b_applic_info->apdu_flags.l_seg ) ) & 0x03; switch ( applic_rx->state ) { case SAI_NULL : dat_for_applic_info_rrlp_rx_null ( b_applic_info, seg ); break; case SAI_SEGM : dat_for_applic_info_rrlp_rx_segm ( b_applic_info, seg ); break; default: break; } } /* +------------------------------------------------------------------------------ | Function : dat_for_applic_info +------------------------------------------------------------------------------ | Description : Main entry point for Application Information Transfer (RX) | Reference: 3GPP TS 04.18, 3.4.21.3 | | Parameters : b_applic_info: Segment of an APDU. | +------------------------------------------------------------------------------ */ GLOBAL void dat_for_applic_info ( T_B_APPLIC_INFO * b_applic_info ) { /* * handle RRLP, all other protocols are not supported */ if ( b_applic_info->apdu_id.protoc_ident EQ RRLP_LCS ) { dat_for_applic_info_rrlp ( b_applic_info ); } else { TRACE_EVENT_P1 ( "unsupported protocol %x", b_applic_info->apdu_id.protoc_ident ); } } #endif /* FF_EOTD */ /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_for_handover_mob_alloc | +--------------------------------------------------------------------+ PURPOSE : This function generates a frequency hopping list for handover */ LOCAL BOOL dat_for_handover_mob_alloc(UBYTE *mob_alloc, T_LIST *hop_list_handover, T_VOID_STRUCT *mob_alloc_handover, T_DL_DATA_IND *dl_data_ind) { GET_INSTANCE_DATA; TRACE_FUNCTION("dat_for_handover_mob_alloc()"); /* * the handover command contains a mobile allocation. * Convert the bitmap to a list of the 1-bits in the * bitmap for generating a frequency hopping list. */ att_bits_to_byte (mob_alloc, ((T_mob_alloc *)mob_alloc_handover)->c_mac, ((T_mob_alloc *)mob_alloc_handover)->mac); /* * Now create the frequency hopping list */ if(!srv_create_chan_mob_alloc (&rr_data->cr_data.cd.cell_chan_desc, hop_list_handover, mob_alloc)) { dat_send_handov_fail_msg(RRC_FREQ_NOT_IMPL); RR_EM_SET_HANDOVER_FAIL_CAUSE(RRC_FREQ_NOT_IMPL); PFREE (dl_data_ind); return TRUE; } return FALSE; } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_cr_data_multirate_conf | +--------------------------------------------------------------------+ PURPOSE : This function extracts the multirate configuration and stores it in the rr_data. */ LOCAL void dat_cr_data_multirate_conf(U8 v_multirate_conf, T_multirate_conf *multirate_conf) { GET_INSTANCE_DATA; TRACE_FUNCTION("dat_cr_data_multirate_conf()"); if(rr_data->cr_data.ch_mode EQ CM_AMR) { if (v_multirate_conf) { /* * store a new multi-rate speech codec if available. */ UBYTE i; rr_data->cr_data.amr_conf.mr_vers = multirate_conf->mr_vers; rr_data->cr_data.amr_conf.nscb = multirate_conf->nscb; rr_data->cr_data.amr_conf.icmi = multirate_conf->icmi; rr_data->cr_data.amr_conf.st_mode = multirate_conf->st_mode; rr_data->cr_data.amr_conf.set_amr = multirate_conf->set_amr; /* * valid flag for the threshold and hystersis values. multirate_conf.c_cod_prop * defines the number of threshold and hystersis values. */ rr_data->cr_data.amr_conf.v_cod_prop = multirate_conf->v_cod_prop; if(rr_data->cr_data.amr_conf.v_cod_prop) { rr_data->cr_data.amr_conf.c_cod_prop = multirate_conf->c_cod_prop; for (i=0; i< multirate_conf->c_cod_prop; i++) memcpy(&rr_data->cr_data.amr_conf.cod_prop[i], &multirate_conf->cod_prop[i], sizeof(T_cod_prop)); } /* if(rr_data->cr_data.amr_conf.v_cod_prop) */ } /* if (assign_cmd->v_multirate_conf) */ } /* if (rr_data->cr_data.ch_mode EQ CM_AMR) */ } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_class_chng_data_req | +--------------------------------------------------------------------+ PURPOSE : This function forms a peer CLASSMARK CHANGE request */ GLOBAL void dat_class_chng_data_req(void) { GET_INSTANCE_DATA; TRACE_FUNCTION("dat_class_chng_data_req()"); /* * The syntax check indicates no problems, then * process the message. * * The MS returns a classmark change message. */ { MCAST (class_chng, U_CLASS_CHNG);/* T_U_CLASS_CHNG */ PALLOC_MSG (dl_data_req, DL_DATA_REQ, U_CLASS_CHNG); /* * set channel type and sapi */ dat_code_prr_channel (&dl_data_req->ch_type, &dl_data_req->sapi, rr_data->sc_data.chan_desc.chan_type); class_chng->msg_type = U_CLASS_CHNG; class_chng->mob_class_2 = rr_data->ms_data.classmark2; class_chng->mob_class_2.rf_pow_cap = att_get_power (); class_chng->mob_class_3 = rr_data->ms_data.classmark3; class_chng->v_mob_class_3 = rr_data->ms_data.classmark2.class3; for_dat_data_req (dl_data_req); } } /* +--------------------------------------------------------------------+ | PROJECT : GSM-PS (6147) MODULE : RR_DAT | | STATE : code ROUTINE : dat_dedicated_req_ch_type2 | +--------------------------------------------------------------------+ PURPOSE : This function extracts the channle type from the channel description IE . */ LOCAL void dat_dedicated_req_ch_type2(T_ch_type2 *ch_type2, T_chan_desc_before *chan_desc_before, T_LIST *hop_list_before) { GET_INSTANCE_DATA; TRACE_FUNCTION("dat_dedicated_req_ch_type2()"); ch_type2->ch = chan_desc_before->chan_type; ch_type2->tn = chan_desc_before->tn; ch_type2->tsc = chan_desc_before->tsc; ch_type2->h = chan_desc_before->hop; if(ch_type2->h EQ H_NO) ch_type2->arfcn = chan_desc_before->arfcn; else { ch_type2->maio = chan_desc_before->maio; ch_type2->hsn = chan_desc_before->hsn; /* CSI-LLD section:4.1.1.11 * This function Updates the black list with the MA list received * in the assignment command */ cs_remove_BA_MA_from_black_list(rr_data->cs_data.region,hop_list_before); srv_create_list (hop_list_before, ch_type2->ma, MAX_MA_CHANNELS, TRUE, 0); } } #if defined (REL99) && defined (TI_PS_FF_EMR) /* +------------------------------------------------------------------------------ | Function : dat_for_meas_inf +------------------------------------------------------------------------------ | Description : Processing of measurement information message is done in this function. | All possible errors, if present, are detected and an error free MI-message | instance is decoded and data base updated with the enhanced measurement parameters. | Parameters : MI-message pointer | +------------------------------------------------------------------------------ */ GLOBAL BOOL dat_for_meas_inf (T_D_MEAS_INF *p_mi) { GET_INSTANCE_DATA; T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current; T_rr_enh_para *p_temp = &rr_data->sc_data.emr_data_temp; BOOL send_enh_para = FALSE; T_gprs_rep_prio *p_rep = NULL; T_gprs_bsic *p_bl = NULL; #if defined (TI_PS_FF_RTD) AND defined (REL99) UBYTE i,j; #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ /* Step 1: Check if we received right BA_IND */ if( (rr_data->sc_data.ba_list_ded EQ TRUE) AND (p_mi->ba_ind NEQ rr_data->sc_data.ba_index ) ) { rr_data->sc_data.ba_list_ded = FALSE; rr_data->sc_data.ba_index = p_mi->ba_ind ; srv_clear_list (&rr_data->sc_data.cd.ncell_list); #ifdef TI_PS_FF_REL4 srv_clear_list (&rr_data->sc_data.cd.multiband_ncell_list); #else srv_clear_list (&rr_data->sc_data.five_ter_list); #endif att_clean_buf (IND_ALL_DEDI_SI); rr_data->sc_data.cd.sys_info_read &= ~ALL_DEDI_SYS_INFOS; TRACE_EVENT("Flushed off the entire dedicated mode BA-LIST as the BA-IND got changed"); } /* Step 2: Check report type. IMPORTANT ASSUMPTION: We will not process the other parameters if report type is Normal*/ if( p_mi->report_type NEQ ENHANCED_MEAS ) { /*check whether there are enhanced parameters and BA list, already. If present then it means that report type is changing from Enhanced to Normal*/ if ( p_cur->is_data_valid EQ TRUE ) { for_set_default_emr_data(p_cur); return TRUE; /*send enh para update to indicate change in report type*/ } else return send_enh_para; } /* Step 3: Check if we already have enh_para in current or temp and if there is change in parameters or continuation of reception*/ if(p_temp->is_data_valid EQ FALSE ) { /*This means we were not in the process of receiving. Check whether there is already information in current and if so, is there change in mp_change_mark*/ if( (p_cur->is_data_valid EQ TRUE ) AND (p_cur->mp_change_mark EQ p_mi->mp_cm ) ) { TRACE_EVENT("No change in Enhanced measurement parameters -ignore "); return send_enh_para; } /* This means there's either a change in MP change mark or receiving EMP for first time */ /* Decode rest of the parameters*/ p_temp->is_data_valid = TRUE; rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE; p_temp->enh_para.ncc_permitted = rr_data->sc_data.cd.ncc_permitted; } /*Note :If different values occur for the same parameter in different instances of a message, the instance with the highest index shall be used (sec.3.4.1.2.1, 4.18)*/ if ( (p_mi->mi_idx > rr_data->sc_data.prev_highest_index ) OR (rr_data->sc_data.prev_highest_index EQ NOT_PRESENT_8BIT) ) { p_temp->enh_para.rep_rate = p_mi->rep_rate; p_temp->enh_para.inv_bsic_enabled = p_mi->inv_bsic_rep; p_temp->mp_change_mark = p_mi->mp_cm; p_temp->msg_count = p_mi->mi_c; p_temp->rep_type = p_mi->report_type; if (p_mi->v_emp EQ TRUE ) /* This is updation of parameters other than BSIC list*/ { dat_update_emr_rep_para(&p_mi->emp,&p_temp->enh_para); } rr_data->sc_data.prev_highest_index = p_mi->mi_idx; } #if defined (TI_PS_FF_RTD) AND defined (REL99) if(p_mi->v_rtdd) dat_update_rtd_data(p_mi,p_temp); #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ /*Get relevant parameters to pass to BSIC and report priority list handler*/ if(p_mi->v_gprs_rep_prio EQ TRUE) p_rep = &p_mi->gprs_rep_prio; if( p_mi->v_gprs_bsic EQ TRUE) p_bl = &p_mi->gprs_bsic; if (for_dat_process_common_emr_data(p_rep,p_bl,p_mi->mi_idx, rr_data->sc_data.ba_list_ded) ) { rr_data->sc_data.enh_para_status = ENH_PARA_DEDICATED; if ( rr_data->sc_data.ba_list_ded EQ TRUE) send_enh_para = TRUE; } #if defined (TI_PS_FF_RTD) AND defined (REL99) if(p_mi->v_rtdd) { /* reset the temporary storage to RTD value not available */ for(j = 0;j < MAX_NR_OF_NCELL; j++ ) { p_temp->enh_para.enh_cell_list[j].v_rtd = FALSE; for(i = 0;i < MAX_NUM_OF_RTD_VALUES; i++) p_temp->enh_para.enh_cell_list[j].rtd[i]= RTD_NOT_AVAILABLE; }/*for*/ }/*if*/ #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */ return send_enh_para; } #endif #endif