comparison g23m-gsm/rr/rr_forf.c @ 0:75a11d740a02

initial import of gsm-fw from freecalypso-sw rev 1033:5ab737ac3ad7
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 09 Jun 2016 00:02:41 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:75a11d740a02
1 /*
2 +-----------------------------------------------------------------------------
3 | Project :
4 | Modul :
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : Handling of Common Information Elements.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef RR_FORF_C
22 #define RR_FORF_C
23
24 #include "config.h"
25 #include "fixedconf.h"
26 #include "condat-features.h"
27
28 #define ENTITY_RR
29
30 /*==== INCLUDES ===================================================*/
31
32 #include <string.h>
33 #include <stdlib.h>
34 #include <stddef.h> /* offsetof */
35 #include "typedefs.h"
36 #include "pcm.h"
37 #include "pconst.cdg"
38 #include "mconst.cdg"
39 #include "message.h"
40 #include "ccdapi.h"
41 #include "vsi.h"
42 #include "custom.h"
43 #include "gsm.h"
44 #include "prim.h"
45 #include "cnf_rr.h"
46 #include "tok.h"
47 #include "rr.h"
48
49 /*==== EXPORT =====================================================*/
50
51 /*==== PRIVATE =====================================================*/
52 static BOOL for_create_delta_list (T_freq_chan_seq_after *delta_list,
53 T_LIST *hop_list);
54 static void for_decode_param (const T_W_PARAM *param,
55 SHORT *w,
56 T_f_range *cha,
57 USHORT initial_value);
58 static void for_decode_param_1024 (SHORT *w,
59 T_f_range *cha);
60 static USHORT for_get_generation (USHORT value);
61 static void for_decode_frequencies (SHORT original_range,
62 SHORT *w,
63 T_LIST *f,
64 SHORT offset);
65 static LONG for_modulo (LONG a,
66 LONG b);
67 static LONG for_smodulo (LONG a,
68 LONG b);
69 static void for_set_conditional_error (void);
70
71 #if defined (TI_PS_FF_EMR) AND defined (GPRS)
72 static void for_store_nc_para(T_nc_meas_para *p_nc,T_rr_enh_para *p_em);
73 #endif
74 LOCAL void for_frequency_list(T_freq_list *freq_list_starting_time_cmd,
75 T_f_range *freq_list_starting_time_para,
76 T_LIST *hop_list_starting_time);
77
78
79 LOCAL void for_decode_param_freq(USHORT range ,T_f_range *cha_list_descr,
80 T_LIST *cha_list);
81
82 /*==== GLOBAL VARIABLES ===========================================*/
83 /*==== VARIABLES ==================================================*/
84 /*==== FUNCTIONS ==================================================*/
85
86 /*
87 * -------------------------------------------------------------------
88 * Procedures
89 * -------------------------------------------------------------------
90 */
91 /*
92 +--------------------------------------------------------------------+
93 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
94 | STATE : code ROUTINE : for_check_ba_range |
95 +--------------------------------------------------------------------+
96
97 PURPOSE : The function checks the content of a ba range information
98 element which is used in the channel release message.
99
100 */
101
102 GLOBAL BOOL for_check_ba_range (T_ba_range *ba_range)
103 {
104 USHORT i = 0;
105 UBYTE bands_used;
106
107 TRACE_FUNCTION ("for_check_ba_range()");
108
109 /*
110 * for all ranges
111 */
112 for (i = 0; i < ba_range->c_freq_range; i++)
113 {
114 /*
115 * check the lower range boarder
116 */
117 bands_used = for_check_frequency (ba_range->freq_range[i].freq_lower);
118 if (bands_used <= INVALID_BAND_USED)
119 return FALSE;
120
121 /*
122 * check the upper range boarder
123 */
124 bands_used = for_check_frequency (ba_range->freq_range[i].freq_higher);
125 if (bands_used <= INVALID_BAND_USED)
126 return FALSE;
127 }
128 return TRUE;
129 }
130
131 /*
132 +--------------------------------------------------------------------+
133 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
134 | STATE : code ROUTINE : for_check_assign_cmd |
135 +--------------------------------------------------------------------+
136
137 PURPOSE : Content check of assignment command message.
138
139 */
140
141 typedef struct
142 {
143 UBYTE count_before;
144 UBYTE count_after;
145 T_LIST cell_chan_desc;
146 T_LIST hop_list_after;
147 T_LIST hop_list_before;
148 T_f_range freq_list_after;
149 T_f_range freq_list_before;
150 } T_ASSIGN_PARA;
151
152 GLOBAL void for_check_assign_cmd (T_DL_DATA_IND * dl_data_ind,
153 T_D_ASSIGN_CMD *assign_cmd)
154 {
155 GET_INSTANCE_DATA;
156 T_ASSIGN_PARA * a_para;
157 MALLOC (a_para, sizeof (T_ASSIGN_PARA));
158
159 a_para->count_before = 0;
160 a_para->count_after = 0;
161
162 TRACE_EVENT ("for_check_assign_cmd()");
163
164 /*
165 * initialize several lists for frequency hopping purposes
166 */
167 srv_clear_list (&a_para->cell_chan_desc);
168 srv_clear_list (&a_para->hop_list_after);
169 srv_clear_list (&a_para->hop_list_before);
170
171 /*
172 * check the channel description
173 */
174 for_check_channel_descr (&assign_cmd->chan_desc);
175
176 if (assign_cmd->v_cell_chan_desc)
177 {
178 /*
179 * if a cell channel description is inserted
180 * create the cell channel list and check it.
181 */
182 for_create_channel_list ((T_f_range *)&assign_cmd->cell_chan_desc,
183 &a_para->cell_chan_desc);
184 }
185
186 if (assign_cmd->chan_desc.hop AND assign_cmd->v_freq_list_after)
187 {
188 /*
189 * if the message contains a frequency list
190 */
191 /* Implements RR Clone findings #5 */
192 for_frequency_list(&assign_cmd->freq_list_after,
193 &a_para->freq_list_after,
194 &a_para->hop_list_after);
195 }
196
197 /*
198 * check the channel mode, if available.
199 */
200 if (assign_cmd->v_chan_mode)
201 for_check_channel_mode (assign_cmd->chan_mode);
202
203 /*
204 * if the message contains a channel mode information element which
205 * indicates AMR, check the multirate configuration information element.
206 * or if no channel mode is present but we have been using AMR before
207 * check the supplied mulitrate configuration
208 */
209 if ( ( assign_cmd->v_chan_mode AND (assign_cmd->chan_mode EQ CM_AMR)) OR
210 (!assign_cmd->v_chan_mode AND (rr_data->sc_data.ch_mode EQ CM_AMR))
211 )
212 {
213 if (assign_cmd->v_multirate_conf)
214 for_check_multirate_conf( &assign_cmd->multirate_conf, assign_cmd->chan_desc.chan_type);
215
216 /*
217 * check if during initial assignment the multirate configuration element is present
218 * otherwise remain on the current channel and use the old channel description.
219 */
220 if ( (rr_data->sc_data.ch_mode NEQ CM_AMR) AND (!assign_cmd->v_multirate_conf) )
221 for_set_content_error (RRC_CHANNEL_MODE);
222
223 /*
224 * If the assignment is related to an intra-cell handover from a multi-rate speech codec
225 * to a multi-rate speech codec, the MultiRate Configuration IE shall be included in the
226 * case of full rate to half rate. If not included in this case, the mobile station shall
227 * behave as if the MultiRate Configuration IE was inconsistent.
228 */
229 if ( rr_data->sc_data.ch_mode EQ CM_AMR AND
230 rr_data->sc_data.chan_desc.chan_type EQ TCH_F AND
231 assign_cmd->chan_mode EQ CM_AMR AND
232 (assign_cmd->chan_desc.chan_type EQ TCH_H_S0 OR
233 assign_cmd->chan_desc.chan_type EQ TCH_H_S1) AND
234 assign_cmd->v_multirate_conf EQ 0 )
235 {
236 for_set_content_error (RRC_CHANNEL_MODE);
237 }
238 }
239
240 /*
241 * check the cipher mode setting if available
242 */
243 if (assign_cmd->v_ciph_mode_set)
244 {
245 for_check_cipher_mode_set (&assign_cmd->ciph_mode_set);
246 }
247
248 a_para->count_after = assign_cmd->v_freq_list_after +
249 assign_cmd->v_mob_alloc_after;
250
251 if (assign_cmd->chan_desc.hop)
252 {
253 /*
254 * In case of frequency hopping, check whether more
255 * then one possibility is defined to build a frequency
256 * hopping list -> this means inconsistency and is
257 * a conditional error.
258 */
259 if (a_para->count_after NEQ 1)
260 {
261 for_set_conditional_error ();
262 }
263 }
264
265 if (assign_cmd->v_start_time)
266 {
267 /*
268 * If a starting time is present, some
269 * elements before starting time must be set.
270 */
271 a_para->count_before = assign_cmd->v_chan_desc_before +
272 assign_cmd->v_freq_list_before +
273 assign_cmd->v_mob_alloc_before +
274 assign_cmd->v_freq_chan_seq;
275
276 if (a_para->count_before NEQ 0 AND
277 assign_cmd->v_chan_desc_before EQ FALSE)
278 {
279 /*
280 * a frequency hopping definition is available,
281 * but no channel description before starting time.
282 * then use the channel description after starting time.
283 */
284 memcpy (&assign_cmd->chan_desc_before,
285 &assign_cmd->chan_desc,
286 sizeof (T_chan_desc));
287 assign_cmd->v_chan_desc_before = TRUE;
288 }
289
290 if (assign_cmd->v_chan_desc_before)
291 {
292 /*
293 * if a channel description before starting time
294 * is available.
295 */
296 if (assign_cmd->chan_desc_before.hop)
297 {
298 /*
299 * if the channel description before starting time
300 * uses a frequency hopping list, count the possible
301 * variants of building a frequency hopping list.
302 */
303 a_para->count_before = assign_cmd->v_freq_list_before +
304 assign_cmd->v_mob_alloc_before +
305 assign_cmd->v_freq_chan_seq;
306
307 switch (a_para->count_before)
308 {
309 /*
310 * no before elements to build a hopping list
311 */
312 case 0:
313 if (a_para->count_after EQ 1)
314 {
315 /*
316 * use the after starting time variant also
317 * for the before starting time frequency list.
318 */
319 memcpy (&assign_cmd->freq_list_before,
320 &assign_cmd->freq_list_after,
321 sizeof (T_freq_list));
322 assign_cmd->v_freq_list_before = assign_cmd->v_freq_list_after;
323 memcpy (&assign_cmd->mob_alloc_before,
324 &assign_cmd->mob_alloc_after,
325 sizeof (T_mob_alloc_after));
326 assign_cmd->v_mob_alloc_before = assign_cmd->v_mob_alloc_after;
327 }
328 else
329 {
330 /*
331 * A conditional error is detected. The channel description
332 * before starting time shall use frequency hopping, but no
333 * frequency hopping list can be created.
334 */
335 for_set_conditional_error ();
336 }
337 break;
338
339 case 1:
340 /*
341 * There is just one variant to build the frequency
342 * hopping list before starting time.
343 */
344 break;
345
346 default:
347 /*
348 * There are more then one variant to build the
349 * frequency hopping list before starting time.
350 * This is detected as a conditional error.
351 */
352 for_set_conditional_error ();
353 break;
354 }
355 }
356 else
357 { /* IEs are unnecessary */
358 assign_cmd->v_freq_list_before =
359 assign_cmd->v_mob_alloc_before =
360 assign_cmd->v_freq_chan_seq = 0;
361 }
362 }
363 }
364 else
365 { /* IEs are unnecessary */
366 assign_cmd->v_chan_desc_before =
367 assign_cmd->v_freq_list_before =
368 assign_cmd->v_mob_alloc_before =
369 assign_cmd->v_freq_chan_seq = 0;
370 }
371
372 if (assign_cmd->v_chan_desc_before)
373 {
374 /*
375 * check the channel description before starting time
376 * if available.
377 */
378 for_check_channel_descr ((T_chan_desc *)&assign_cmd->chan_desc_before);
379 }
380
381 if (assign_cmd->v_freq_list_before)
382 {
383
384 /* Implements RR Clone findings #5 */
385 for_frequency_list (&assign_cmd->freq_list_before,
386 &a_para->freq_list_after,
387 &a_para->hop_list_before);
388 }
389
390 if (assign_cmd->v_freq_chan_seq)
391 {
392 /*
393 * if a frequency channel sequence information element is
394 * available, build a frequency hopping list.
395 */
396 if (!for_create_delta_list ((T_freq_chan_seq_after *)
397 &assign_cmd->freq_chan_seq,
398 &a_para->hop_list_before))
399 {
400 /*
401 * set a content error if the frequency hopping list
402 * contains channel numbers which are not supported.
403 */
404 for_set_content_error (RRC_FREQ_NOT_IMPL);
405 }
406 }
407
408 /*
409 * configure layer 1 for the new channel
410 */
411 dat_for_assign_cmd (dl_data_ind, assign_cmd, &a_para->hop_list_after,
412 &a_para->hop_list_before, &a_para->cell_chan_desc);
413
414 /*
415 * de-allocate the dynamic memory
416 */
417 MFREE (a_para);
418 }
419
420 /*
421 +--------------------------------------------------------------------+
422 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
423 | STATE : code ROUTINE : for_check_cell_descr |
424 +--------------------------------------------------------------------+
425
426 PURPOSE : check the content of the information element cell
427 description.
428
429 */
430
431 GLOBAL void for_check_cell_descr (T_cell_desc *cell_desc)
432 {
433 USHORT bcch_arfcn;
434 UBYTE result;
435
436 TRACE_FUNCTION ("for_check_cell_desc()");
437
438 /*
439 * calculate the BCCH channel number
440 */
441 bcch_arfcn = (cell_desc->bcch_arfcn_hi << 8) +
442 cell_desc->bcch_arfcn_lo;
443
444 /*
445 * check the BCCH channel number.
446 * If the number is not a GSM channel number set the cause
447 * INCORRECT MESSAGE.
448 * If the number is a GSM channel number, but not supported
449 * by the mobile, set the cause FREQUENCY NOT IMPLEMENTED.
450 */
451 result = for_check_frequency (bcch_arfcn);
452 if (result EQ UNKNOWN_BAND_USED)
453 for_set_content_error (RRC_INCORRECT_MSG);
454 else if( result EQ INVALID_BAND_USED )
455 for_set_content_error (RRC_FREQ_NOT_IMPL);
456 }
457
458 /*
459 +--------------------------------------------------------------------+
460 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
461 | STATE : code ROUTINE : for_check_channel_descr |
462 +--------------------------------------------------------------------+
463
464 PURPOSE : check the content of the information element channel
465 description.
466
467 */
468
469 GLOBAL void for_check_channel_descr (T_chan_desc *chan_desc)
470 {
471 GET_INSTANCE_DATA;
472 BOOL result = TRUE;
473
474 TRACE_FUNCTION ("for_check_channel_descr()");
475
476 /*
477 * check the channel type
478 */
479 switch (chan_desc->chan_type)
480 {
481 case TCH_H_S0:
482 case TCH_H_S1:
483 /*
484 * TCH Halfrate channels
485 * check against the mobile capabilities in PCM
486 * (halfrate support)
487 */
488 if (FldGet(rr_data->mscap.chnMode, hrSup) EQ 0)
489 for_set_content_error (RRC_CHANNEL_MODE);
490 break;
491
492 default:
493 /*
494 * 1 (= TCH Fullrate) or 4..15 (= SDCCH)
495 * are allowed values. Any other value
496 * is not supported.
497 */
498 if ((chan_desc->chan_type EQ 0)
499 OR (chan_desc->chan_type > CH_SDCCH_8_7))
500 for_set_content_error (RRC_CHANNEL_MODE);
501 break;
502 }
503
504 if (chan_desc->hop EQ 0)
505 {
506 /*
507 * without frequency hopping.
508 * Then check the channel number of the channel
509 * description.
510 * If the number is not a GSM channel number set the cause
511 * INCORRECT MESSAGE.
512 * If the number is a GSM channel number, but not supported
513 * by the mobile, set the cause FREQUENCY NOT IMPLEMENTED.
514 */
515 result = for_check_frequency (chan_desc->arfcn);
516 if (result EQ UNKNOWN_BAND_USED)
517 for_set_content_error (RRC_INCORRECT_MSG);
518 else if (result EQ INVALID_BAND_USED)
519 for_set_content_error (RRC_FREQ_NOT_IMPL);
520 }
521 }
522
523 /*
524 +------------------------------------------------------------------------------
525 | Function : for_check_multirate_conf
526 +------------------------------------------------------------------------------
527 | Description : Set the new multi-rate speech codec elements
528 |
529 | Parameters : amr_conf - MultiRate configuration IEI
530 |
531 | Return : void
532 |
533 +------------------------------------------------------------------------------
534 */
535 GLOBAL void for_check_multirate_conf (T_multirate_conf * multirate_conf, UBYTE chan_type)
536 {
537 UBYTE acs = multirate_conf->set_amr;
538 UBYTE i=0, num_acs=0;
539
540 TRACE_FUNCTION ("for_check_multirate_conf()");
541
542 /*
543 * Check number of codec modes inside the set of AMR codec mode mask
544 */
545 for(i=0; i<8; i++)
546 {
547 if( (0x01<<i) & acs )
548 {
549 num_acs++;
550 TRACE_EVENT_P1("AMR no. acs %d", num_acs);
551 }
552 }
553
554 /*
555 * From 3GPP TS 04.18
556 *
557 * The MultiRate Configuration IE shall be considered as inconsistent by the MS if:
558 *
559 * - the active set does not include any codec mode or the active set includes more than four codec modes; or
560 * - one or more codec modes of the active codec set are not supported by the assigned channel; or
561 * - the threshold and hysteresis values are not set according to requirements given in 3GPP TS 05.09.
562 *
563 * Refer to 3GPP TS 05.05 for codec modes supported by different channels.
564 */
565
566 if(
567 ((chan_type EQ CH_TCH_H_1) OR (chan_type EQ CH_TCH_H_2))
568 AND
569 ((acs & SET_AMR_10_2) OR (acs & SET_AMR_12_2))
570 )
571 {
572 TRACE_EVENT_P2(" chan_type = %d acs = %d, invalid acs for TCH AHS", chan_type, acs);
573 for_set_content_error (RRC_CHANNEL_MODE);
574 return;
575 }
576
577 /*
578 * The active set does not include any codec mode or the active set includes more than four
579 * codec modes.
580 */
581 if( (num_acs > MAX_NO_ACS) OR (num_acs EQ 0) )
582 {
583 TRACE_EVENT("AMR ((num_acs > MAX_NO_ACS) OR (num_acs EQ 0))");
584 for_set_content_error (RRC_CHANNEL_MODE);
585 return;
586 }
587
588 /*
589 * One or mode codec modes of the active codec set are not supported by
590 * the assigned channel.
591 */
592 if ( num_acs < multirate_conf->st_mode )
593 {
594 /*
595 * The start mode is not supported by the acs, e.g. CODEC_MODE_4 is requested but only 3
596 * codec modes are part of the acs.
597 */
598 TRACE_EVENT("(num_acs < multirate_conf->st_mode)");
599 for_set_content_error (RRC_CHANNEL_MODE);
600 return;
601 }
602
603 /*
604 * The threshold and hysteresis values are not set according to requirements in 3GPP TS 05.09
605 */
606 /*
607 * Number of codec modes minus one must be equal to number of thresholds and hysteresis
608 */
609 if( ((num_acs-1) NEQ multirate_conf->c_cod_prop) )
610 {
611 TRACE_EVENT("((num_acs-1) NEQ multirate_conf->c_cod_prop))");
612 for_set_content_error (RRC_CHANNEL_MODE);
613 return;
614 }
615
616 /*
617 * Check if the thresholds and hysteresis values are in consistent order
618 */
619 for(i=0; i<(multirate_conf->c_cod_prop-1); i++)
620 {
621 if(multirate_conf->cod_prop[i].codec_thr > multirate_conf->cod_prop[i+1].codec_thr)
622 {
623 /* Implements Measure#32: Row 252 */
624 TRACE_EVENT_P2("cod_prop[%d].codec_thr > cod_prop[%d+1].codec_thr",i,i);
625 for_set_content_error (RRC_CHANNEL_MODE);
626 }
627 else
628 {
629 if( (multirate_conf->cod_prop[i].codec_thr + multirate_conf->cod_prop[i].codec_hyst) >
630 (multirate_conf->cod_prop[i+1].codec_thr + multirate_conf->cod_prop[i+1].codec_hyst) )
631 {
632 /* Implements Measure#32: Row 251 */
633 TRACE_EVENT_P4("cod_prop[%d].codec_thr+cod_prop[%d].codec_hyst>cod_prop[%d+1].codec_thr+cod_prop[%d+1].codec_hyst", i,i,i,i);
634 for_set_content_error (RRC_CHANNEL_MODE);
635 }
636 }
637 }
638 }
639
640 /*
641 +--------------------------------------------------------------------+
642 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
643 | STATE : code ROUTINE : for_check_channel_mode |
644 +--------------------------------------------------------------------+
645
646 PURPOSE : check the information element channel mode.
647
648 */
649
650 GLOBAL void for_check_channel_mode (UBYTE ch_mod)
651 {
652 GET_INSTANCE_DATA;
653 TRACE_FUNCTION ("for_check_channel_mode()");
654
655 /*
656 * Reads the ms bearer caps a second time after a config primitive was sent
657 * during a test case. Otherwise the new data will be ignored.
658 */
659 #if defined (_SIMULATION_)
660 rr_csf_ms_cap ();
661 #endif
662
663 /*
664 * depending on the channel mode.
665 */
666 switch (ch_mod)
667 {
668 case CM_DATA_12_0: /* data 12 k */
669 case CM_DATA_6_0: /* data 6 k */
670 case CM_DATA_3_6: /* data 3.6 k */
671 /*
672 * check against the data capabilities of the
673 * mobile. The PCM record must indicate data
674 * support.
675 */
676 if (FldGet(rr_data->mscap.datCap1, datSup) EQ 0)
677 for_set_content_error (RRC_CHANNEL_MODE);
678 break;
679
680 case CM_DATA_14_4: /* data 14.4 k */
681 /*
682 * check against the data capabilities of the
683 * mobile. The PCM record must indicate 14.4 k data
684 * support.
685 */
686 if (FldGet(rr_data->mscap.datCap1, Dr14_4Sup) EQ 0)
687 for_set_content_error (RRC_CHANNEL_MODE);
688 break;
689
690 case CM_EFR: /* enhanced full rate */
691 /*
692 * check against the mobile capabilities
693 * The PCM record must indicate support for
694 * enhanced fullrate.
695 */
696 if (FldGet(rr_data->mscap.chnMode, EFRSupV2) EQ 0)
697 for_set_content_error (RRC_CHANNEL_MODE);
698 break;
699
700 case CM_AMR: /* speech full rate / half rate version 3 - AMR */
701 /*
702 * check against the mobile capabilities
703 * The PCM record must indicate support for
704 * speech version 3.
705 */
706 if ( (FldGet(rr_data->mscap.chnMode, AHS) EQ 0) AND (FldGet(rr_data->mscap.chnMode, AFS) EQ 0))
707 for_set_content_error (RRC_CHANNEL_MODE);
708 break;
709
710 case CM_SIG_ONLY: /* signalling only */
711 break;
712 case CM_SPEECH: /* speech full or halfrate */
713 /* If a speech mode is intended, but the MS is a data only unit, then error */
714 if( !( rr_data->mscap.chnMode & ( spchSupV1m | HR_EFRSupm | EFRSupV3m | AHSm | AFSm )))
715 {
716 for_set_content_error (RRC_CHANNEL_MODE);
717 }
718 break;
719
720 default:
721 /*
722 * a non-supported channel mode is detected.
723 */
724 for_set_content_error (RRC_CHANNEL_MODE);
725 break;
726 }
727 }
728
729 /*
730 +--------------------------------------------------------------------+
731 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
732 | STATE : code ROUTINE : for_check_cipher_mode_set |
733 +--------------------------------------------------------------------+
734
735 PURPOSE : check cipher mode setting information element.
736
737 */
738
739 GLOBAL void for_check_cipher_mode_set (T_ciph_mode_set *ciph_mode_set)
740 {
741 GET_INSTANCE_DATA;
742 TRACE_FUNCTION ("for_check_cipher_mode_set()");
743
744 if (ciph_mode_set->algo_ident EQ 7)
745 {
746 /*
747 * check whether the algorithm identifier contains
748 * the reserved value.
749 */
750 for_set_content_error (RRC_INCORRECT_MSG);
751 }
752
753 /*
754 * If ciphering is set, check the ciphering algorithm against the mobile's
755 * capabilities. Regard message as incorrect if the requested algorithm is
756 * not supported by the mobile.
757 */
758 if (ciph_mode_set->sc EQ START_CIPH_YES)
759 {
760 switch (ciph_mode_set->algo_ident)
761 {
762 case ALGO_A5_1:
763 if (!rr_data->ms_data.rf_cap.a5_bits.a5_1)
764 for_set_content_error (RRC_INCORRECT_MSG);
765 break;
766 case ALGO_A5_2:
767 if (!rr_data->ms_data.rf_cap.a5_bits.a5_2)
768 for_set_content_error (RRC_INCORRECT_MSG);
769 break;
770 case ALGO_A5_3:
771 if (!rr_data->ms_data.rf_cap.a5_bits.a5_3)
772 for_set_content_error (RRC_INCORRECT_MSG);
773 break;
774 case ALGO_A5_4:
775 if (!rr_data->ms_data.rf_cap.a5_bits.a5_4)
776 for_set_content_error (RRC_INCORRECT_MSG);
777 break;
778 case ALGO_A5_5:
779 if (!rr_data->ms_data.rf_cap.a5_bits.a5_5)
780 for_set_content_error (RRC_INCORRECT_MSG);
781 break;
782 case ALGO_A5_6:
783 if (!rr_data->ms_data.rf_cap.a5_bits.a5_6)
784 for_set_content_error (RRC_INCORRECT_MSG);
785 break;
786 case ALGO_A5_7:
787 if (!rr_data->ms_data.rf_cap.a5_bits.a5_7)
788 for_set_content_error (RRC_INCORRECT_MSG);
789 break;
790 default: /* Reserved value received, already handled above */
791 break;
792 }
793 }
794 }
795
796 /*
797 +--------------------------------------------------------------------+
798 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
799 | STATE : code ROUTINE : for_check_frequency |
800 +--------------------------------------------------------------------+
801
802 PURPOSE : The function checks a frequency. The return value is TRUE
803 if the channel number is a GSM channel number. The output
804 variable range indicates whether the channel number is
805 supported by the mobile depending on the frequency standard.
806
807 Return Values :
808
809 if (arfcn) is not a valid GSM Channel :-
810 UNKNOWN_BAND_USED
811
812 if (arfcn) is valid GSM Channel then depending upon (std) one of the
813 4 values are returned :
814 LOW_BAND_USED
815 HIGH_BAND_USED
816 EXT_BAND_USED
817 INVALID_BAND_USED
818
819
820 */
821
822 GLOBAL UBYTE for_check_frequency (USHORT channel)
823 {
824
825 TRACE_FUNCTION ("for_check_frequency()");
826
827 /*
828 * check whether the channel number is a GSM channel number
829 * the check is a little bit too simple, but it seems not
830 * to be worst to check it.
831 */
832 if (channel >= HIGH_CHANNEL_EGSM)
833 {
834 return UNKNOWN_BAND_USED;
835 }
836
837 /*
838 * a more efficient way of range checking for ARM
839 * (according to application note 34, ARM DAI 0034A, January 1998)
840 *
841 * For the following code:
842 * if (channel >= low_channel AND channel <= high_channel)
843 * bitposition = ...;
844 *
845 * exist the faster way to implemented this:
846 * if ((unsigned)(channel - low_channel) <= (high_channel - low_channel)
847 * bitposition = ...;
848 *
849 * Future versions of the compiler will perform this optimization
850 * automatically.
851 *
852 * We use the follwing macro:
853 * #define INRANGE(min, x, max) ((unsigned)(x-min) <= (max-min))
854 *
855 */
856
857 /*
858 * depending on the frequency standard
859 */
860 switch (std)
861 {
862 case STD_900:
863 /*
864 if (channel >= LOW_CHANNEL_900 AND channel <= HIGH_CHANNEL_900)
865 *range = TRUE;
866 */
867 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
868 {
869 return LOW_BAND_USED;
870 }
871 break;
872
873 case STD_EGSM:
874 /*
875 if (channel EQ CHANNEL_0)
876 channel = CHANNEL_0_INTERNAL;
877 if (channel >= LOW_CHANNEL_900 AND channel <= HIGH_CHANNEL_900)
878 *range = TRUE;
879 else if (channel >= LOW_CHANNEL_EGSM AND channel <= HIGH_CHANNEL_EGSM)
880 *range = TRUE;
881 */
882 if (channel EQ CHANNEL_0)
883 channel = CHANNEL_0_INTERNAL;
884 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
885 {
886 return LOW_BAND_USED;
887 }
888 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
889 {
890 return EXT_BAND_USED;
891 }
892 break;
893
894 case STD_1900:
895 /*
896 if (channel >= LOW_CHANNEL_1900 AND channel <= HIGH_CHANNEL_1900)
897 *range = TRUE;
898 */
899 if (INRANGE(LOW_CHANNEL_1900,channel,HIGH_CHANNEL_1900))
900 {
901 return HIGH_BAND_USED;
902 }
903 break;
904
905 case STD_1800:
906 /*
907 if (channel >= LOW_CHANNEL_1800 AND channel <= HIGH_CHANNEL_1800)
908 *range = TRUE;
909 */
910 if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
911 {
912 return HIGH_BAND_USED;
913 }
914 break;
915
916 case STD_DUAL:
917 /*
918 if (channel >= LOW_CHANNEL_900 AND channel <= HIGH_CHANNEL_900)
919 *range = TRUE;
920 else if (channel >= LOW_CHANNEL_1800 AND channel <= HIGH_CHANNEL_1800)
921 *range = TRUE;
922 */
923 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
924 {
925 return LOW_BAND_USED;
926 }
927 else if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
928 {
929 return HIGH_BAND_USED;
930 }
931 break;
932
933 case STD_DUAL_EGSM:
934 /*
935 if (channel EQ CHANNEL_0)
936 channel = CHANNEL_0_INTERNAL;
937 if (channel >= LOW_CHANNEL_900 AND channel <= HIGH_CHANNEL_900)
938 *range = TRUE;
939 else if (channel >= LOW_CHANNEL_1800 AND channel <= HIGH_CHANNEL_1800)
940 *range = TRUE;
941 else if (channel >= LOW_CHANNEL_EGSM AND channel <= HIGH_CHANNEL_EGSM)
942 *range = TRUE;
943 */
944 if (channel EQ CHANNEL_0)
945 channel = CHANNEL_0_INTERNAL;
946 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
947 {
948 return LOW_BAND_USED;
949 }
950 else if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
951 {
952 return HIGH_BAND_USED;
953 }
954 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
955 {
956 return EXT_BAND_USED;
957 }
958 break;
959
960 case STD_850:
961 /*
962 if (channel >= LOW_CHANNEL_850 AND channel <= HIGH_CHANNEL_850)
963 *range = TRUE;
964 */
965 if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
966 {
967 return LOW_BAND_USED;
968 }
969 break;
970
971 case STD_DUAL_US:
972 /*
973 if (channel >= LOW_CHANNEL_850 AND channel <= HIGH_CHANNEL_850)
974 *range = TRUE;
975 else if (channel >= LOW_CHANNEL_1900 AND channel <= HIGH_CHANNEL_1900)
976 *range = TRUE;
977 */
978 if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
979 {
980 return LOW_BAND_USED;
981 }
982 else if (INRANGE(LOW_CHANNEL_1900,channel,HIGH_CHANNEL_1900))
983 {
984 return HIGH_BAND_USED;
985 }
986 break;
987
988 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
989 case STD_850_1800:
990 if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
991 {
992 return LOW_BAND_USED;
993 }
994 else if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
995 {
996 return HIGH_BAND_USED;
997 }
998 break;
999
1000 case STD_900_1900:
1001 if (channel EQ CHANNEL_0)
1002 channel = CHANNEL_0_INTERNAL;
1003 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
1004 {
1005 return LOW_BAND_USED;
1006 }
1007 else if (INRANGE(LOW_CHANNEL_1900,channel,HIGH_CHANNEL_1900))
1008 {
1009 return HIGH_BAND_USED;
1010 }
1011 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
1012 {
1013 return EXT_BAND_USED;
1014 }
1015 break;
1016
1017 case STD_850_900_1800:
1018 if (channel EQ CHANNEL_0)
1019 channel = CHANNEL_0_INTERNAL;
1020 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
1021 {
1022 return LOW_BAND_USED;
1023 }
1024 else if (INRANGE(LOW_CHANNEL_1800,channel,HIGH_CHANNEL_1800))
1025 {
1026 return HIGH_BAND_USED;
1027 }
1028 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
1029 {
1030 return EXT_BAND_USED;
1031 }
1032 else if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
1033 {
1034 return LOW_BAND_USED;
1035 }
1036 break;
1037
1038 case STD_850_900_1900:
1039 if (channel EQ CHANNEL_0)
1040 channel = CHANNEL_0_INTERNAL;
1041 if (INRANGE(LOW_CHANNEL_900,channel,HIGH_CHANNEL_900))
1042 {
1043 return LOW_BAND_USED;
1044 }
1045 else if (INRANGE(LOW_CHANNEL_1900,channel,HIGH_CHANNEL_1900))
1046 {
1047 return HIGH_BAND_USED;
1048 }
1049 else if (INRANGE(LOW_CHANNEL_EGSM,channel,HIGH_CHANNEL_EGSM))
1050 {
1051 return EXT_BAND_USED;
1052 }
1053 else if (INRANGE(LOW_CHANNEL_850,channel,HIGH_CHANNEL_850))
1054 {
1055 return LOW_BAND_USED;
1056 }
1057 break;
1058 #endif
1059
1060 }
1061
1062 return INVALID_BAND_USED;
1063 }
1064
1065 /*
1066 +--------------------------------------------------------------------+
1067 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1068 | STATE : code ROUTINE : for_check_handov_cmd |
1069 +--------------------------------------------------------------------+
1070
1071 PURPOSE : Content check of handover command message.
1072
1073 */
1074
1075 typedef struct
1076 {
1077 UBYTE count_after;
1078 UBYTE count_before;
1079 T_LIST cell_chan_desc;
1080 T_LIST hop_list_after;
1081 T_LIST hop_list_before;
1082 T_f_range freq_short_list_after;
1083 T_f_range freq_list_after;
1084 T_f_range freq_short_list_before;
1085 T_f_range freq_list_before;
1086 } T_HANDOVER_PARA;
1087
1088 GLOBAL void for_check_handov_cmd (T_DL_DATA_IND * dl_data_ind,
1089 T_D_HANDOV_CMD * handov_cmd)
1090 {
1091 GET_INSTANCE_DATA;
1092 T_HANDOVER_PARA * h_para;
1093 MALLOC (h_para, sizeof (T_HANDOVER_PARA));
1094
1095 h_para->count_after = 0;
1096 h_para->count_before= 0;
1097
1098 /*
1099 * clear several lists for building frequency hopping lists,
1100 */
1101 srv_clear_list (&h_para->hop_list_after);
1102 srv_clear_list (&h_para->hop_list_before);
1103 srv_clear_list (&h_para->cell_chan_desc);
1104
1105 /*
1106 * check the content of the cell description information element.
1107 */
1108 for_check_cell_descr (&handov_cmd->cell_desc);
1109
1110 /*
1111 * check the content of the channel description information element
1112 */
1113 for_check_channel_descr ((T_chan_desc *)
1114 &handov_cmd->chan_desc_after);
1115
1116 if (handov_cmd->v_freq_short_list_after)
1117 {
1118 /*
1119 * the message contains a frequency short list information element
1120 * for after starting time channel description
1121 */
1122
1123 /*
1124 * clear the local variable.
1125 */
1126
1127
1128 memset (&h_para->freq_short_list_after, 0,
1129 sizeof (T_f_range));
1130
1131 /*
1132 * copy the content of the information element
1133 */
1134 memcpy (&h_para->freq_short_list_after,
1135 &handov_cmd->freq_short_list_after,
1136 sizeof (BUF_freq_short_list_after));
1137
1138 /*
1139 * build a frequency hopping list for layer 1.
1140 */
1141 for_create_channel_list (&h_para->freq_short_list_after,
1142 &h_para->hop_list_after);
1143 /* check if all frequencies are in one band */
1144 if(! srv_check_frequencies_in_list (&h_para->hop_list_after))
1145 {
1146 for_set_content_error(RRC_FREQ_NOT_IMPL);
1147 }
1148 }
1149
1150 if (handov_cmd->v_freq_list_after)
1151 {
1152 /*
1153 * the message contains a frequency list information element.
1154 */
1155
1156 /*
1157 * clear the local variable
1158 */
1159 /* Implements RR Clone findings #6 */
1160 for_frequency_list (&handov_cmd->freq_list_after,
1161 &h_para->freq_list_after,
1162 &h_para->hop_list_after);
1163 }
1164
1165 if (handov_cmd->v_cell_chan_desc)
1166 {
1167 /*
1168 * the message contains a cell channel description information
1169 * element. Build a list for layer 1.
1170 */
1171 for_create_channel_list ((T_f_range *)&handov_cmd->cell_chan_desc,
1172 &h_para->cell_chan_desc);
1173 }
1174
1175 /*
1176 * if the message contains a channel mode information element,
1177 * check the channel mode against the mobile capabilities.
1178 */
1179 if (handov_cmd->v_chan_mode)
1180 for_check_channel_mode (handov_cmd->chan_mode);
1181
1182 /*
1183 * if the message contains a channel mode information element which
1184 * indicates AMR, check the multirate configuration information element.
1185 * or if no channel mode is present but we have been using AMR before
1186 * check the supplied mulitrate configuration
1187 */
1188 if ( ( handov_cmd->v_chan_mode AND (handov_cmd->chan_mode EQ CM_AMR)) OR
1189 (!handov_cmd->v_chan_mode AND (rr_data->sc_data.ch_mode EQ CM_AMR))
1190 )
1191 {
1192 if (handov_cmd->v_multirate_conf)
1193 for_check_multirate_conf( &handov_cmd->multirate_conf,
1194 handov_cmd->chan_desc_after.chan_type);
1195
1196 /*
1197 * check if the multirate configuration element is present
1198 */
1199 if ( (rr_data->sc_data.ch_mode NEQ CM_AMR) AND (!handov_cmd->v_multirate_conf) )
1200 for_set_content_error (RRC_CHANNEL_MODE);
1201
1202 /*
1203 * The MultiRate Configuration IE shall be included in the case of full rate channel
1204 * to half rate channel handover. If not included in this case, the mobile station
1205 * shall behave as if the MultiRate Configuration IE was inconsistent.
1206 */
1207
1208 if ( rr_data->sc_data.ch_mode EQ CM_AMR AND
1209 rr_data->sc_data.chan_desc.chan_type EQ TCH_F AND
1210 handov_cmd->chan_mode EQ CM_AMR AND
1211 (handov_cmd->chan_desc_after.chan_type EQ TCH_H_S0 OR
1212 handov_cmd->chan_desc_after.chan_type EQ TCH_H_S1) AND
1213 handov_cmd->v_multirate_conf EQ 0 )
1214 {
1215 for_set_content_error (RRC_CHANNEL_MODE);
1216 }
1217 }
1218
1219 if (handov_cmd->v_freq_chan_seq_after)
1220 {
1221 /*
1222 * the message contains a frequency channel sequence information
1223 * element. Build a frequency hopping list from this information.
1224 */
1225 if (!for_create_delta_list (&handov_cmd->freq_chan_seq_after,
1226 &h_para->hop_list_after))
1227 {
1228 /*
1229 * set a content error if the frequency hopping list
1230 * contains channel numbers which are not supported.
1231 */
1232 for_set_content_error (RRC_FREQ_NOT_IMPL);
1233 }
1234 }
1235
1236 if (handov_cmd->v_ciph_mode_set)
1237 {
1238 /*
1239 * if the message contains cipher mode information,
1240 * check the content.
1241 */
1242 for_check_cipher_mode_set (&handov_cmd->ciph_mode_set);
1243 }
1244
1245 if (handov_cmd->chan_desc_after.hop)
1246 {
1247 /*
1248 * the channel description after starting time uses
1249 * frequency hopping. It is counted the number of
1250 * used variants for building a frequency hopping list
1251 * after starting time.
1252 */
1253 h_para->count_after = handov_cmd->v_freq_list_after +
1254 handov_cmd->v_freq_short_list_after +
1255 handov_cmd->v_mob_alloc_after +
1256 handov_cmd->v_freq_chan_seq_after;
1257
1258 /*
1259 * If no or more then one variant is defined,
1260 * RR detects a conditional error.
1261 */
1262 if (h_para->count_after NEQ 1)
1263 for_set_conditional_error ();
1264
1265 /*
1266 * If the message contains a mobile allocation but no
1267 * cell channel description, it is not possible to
1268 * build a frequency hopping list: indicate a conditional
1269 * error.
1270 */
1271 if (handov_cmd->v_mob_alloc_after AND
1272 handov_cmd->v_cell_chan_desc EQ FALSE)
1273 for_set_conditional_error ();
1274 }
1275 else
1276 {
1277 /*
1278 * the frequency lists after aren't needed
1279 * for hopping after starting time (GSM 04.08 section 9.1.15.5)
1280 * now check whether the frequency lists after time are needed
1281 * for hopping before starting time (GSM 04.08 section 9.1.15.6)
1282 */
1283 if ( !( handov_cmd->v_start_time AND /* there is a starting time */
1284 ( handov_cmd->v_chan_desc_before AND /* there is required hopping before time */
1285 handov_cmd->chan_desc_before.hop /* explicitly, if using the chan_desc_after (see below) */
1286 ) /* hopping before is implicitly checked above */
1287 ) OR
1288 handov_cmd->v_freq_list_before OR /* hopping before time (if present) uses one of its "own" lists */
1289 handov_cmd->v_freq_short_list_before OR
1290 handov_cmd->v_mob_alloc_before OR
1291 handov_cmd->v_freq_chan_seq_before )
1292 {
1293 /* the frequency lists after time aren't needed */
1294 handov_cmd->v_freq_list_after =
1295 handov_cmd->v_freq_short_list_after =
1296 handov_cmd->v_mob_alloc_after =
1297 handov_cmd->v_freq_chan_seq_after = 0;
1298 }
1299 }
1300
1301 /*
1302 * In case of pseudo-synchronized handover it is
1303 * mandatory to have a time difference information
1304 * element, else set a conditional error.
1305 */
1306 if (handov_cmd->v_time_diff EQ FALSE AND
1307 handov_cmd->synch_ind.si EQ SYI_PSEUDO_SYNCH)
1308 for_set_conditional_error ();
1309
1310 if (handov_cmd->v_start_time)
1311 {
1312 h_para->count_before = handov_cmd->v_chan_desc_before +
1313 handov_cmd->v_freq_list_before +
1314 handov_cmd->v_freq_short_list_before +
1315 handov_cmd->v_mob_alloc_before +
1316 handov_cmd->v_freq_chan_seq_before;
1317
1318 if (h_para->count_before NEQ 0)
1319 {
1320 /*
1321 * The message contains a starting time information element.
1322 */
1323 if (handov_cmd->v_chan_desc_before EQ FALSE)
1324 {
1325 /*
1326 * if the message contains no channel description
1327 * before starting time element, use the
1328 * channel description after starting time instead.
1329 */
1330 memcpy (&handov_cmd->chan_desc_before,
1331 &handov_cmd->chan_desc_after,
1332 sizeof (T_chan_desc));
1333 handov_cmd->v_chan_desc_before = TRUE;
1334 }
1335
1336 if (handov_cmd->chan_desc_before.hop)
1337 {
1338 /*
1339 * if the channel description before starting time
1340 * contains a frequency hopping list, count the
1341 * number of possible variants.
1342 */
1343 h_para->count_before = handov_cmd->v_freq_list_before +
1344 handov_cmd->v_freq_short_list_before +
1345 handov_cmd->v_mob_alloc_before +
1346 handov_cmd->v_freq_chan_seq_before;
1347
1348 switch (h_para->count_before)
1349 {
1350 case 0:
1351 /*
1352 * no before elements for hopping list then use the
1353 * elements of the after starting time.
1354 */
1355 if (h_para->count_after EQ 1)
1356 {
1357 /*
1358 * copy the frequency list after starting time
1359 * if available
1360 */
1361 memcpy (&handov_cmd->freq_list_before,
1362 &handov_cmd->freq_list_after,
1363 sizeof (T_freq_list));
1364 handov_cmd->v_freq_list_before = handov_cmd->v_freq_list_after;
1365
1366 /*
1367 * copy the frequency short list after starting time if available
1368 */
1369 memcpy (&handov_cmd->freq_short_list_before,
1370 &handov_cmd->freq_short_list_after,
1371 sizeof (BUF_freq_short_list_after));
1372 handov_cmd->v_freq_short_list_before = handov_cmd->v_freq_short_list_after;
1373
1374 /*
1375 * copy mobile allocation after starting time if available
1376 */
1377 memcpy (&handov_cmd->mob_alloc_before,
1378 &handov_cmd->mob_alloc_after,
1379 sizeof (T_mob_alloc_after));
1380 handov_cmd->v_mob_alloc_before = handov_cmd->v_mob_alloc_after;
1381
1382 /*
1383 * copy frequency channel sequence after starting time if available
1384 */
1385 memcpy (&handov_cmd->freq_chan_seq_before,
1386 &handov_cmd->freq_chan_seq_after,
1387 sizeof (T_freq_chan_seq_after));
1388 handov_cmd->v_freq_chan_seq_before = handov_cmd->v_freq_chan_seq_after;
1389 }
1390 else
1391 {
1392 /*
1393 * more then one possibility to build a frequency hopping list.
1394 * This means an inconsistent message.
1395 */
1396 for_set_conditional_error ();
1397 }
1398 break;
1399
1400 case 1:
1401 /*
1402 * Just one variant to build a frequency hopping list before
1403 * starting time.
1404 */
1405 break;
1406
1407 default:
1408 /*
1409 * more then one possibility to build a frequency hopping list.
1410 * This means an inconsistent message.
1411 */
1412 for_set_conditional_error ();
1413 break;
1414 }
1415 }
1416 }
1417 }
1418 else
1419 { /* IEs are unnecessary */
1420 handov_cmd->v_chan_desc_before =
1421 handov_cmd->v_freq_list_before =
1422 handov_cmd->v_freq_short_list_before =
1423 handov_cmd->v_mob_alloc_before =
1424 handov_cmd->v_freq_chan_seq_before = 0;
1425 }
1426
1427 /*
1428 * the message contains a mobile allocation but no cell channel description.
1429 * It is not possible to build a frequency hopping list.
1430 */
1431 if (handov_cmd->v_mob_alloc_before AND
1432 handov_cmd->v_cell_chan_desc EQ FALSE)
1433 for_set_conditional_error ();
1434
1435 /*
1436 * If the message contains a channel description before starting time,
1437 * check the content.
1438 */
1439 if (handov_cmd->v_chan_desc_before)
1440 for_check_channel_descr ((T_chan_desc *)
1441 &handov_cmd->chan_desc_before);
1442
1443 if (handov_cmd->v_freq_short_list_before)
1444 {
1445 /*
1446 * build a frequency hopping list for the channel description before
1447 * starting time from the frequency short list information element.
1448 */
1449
1450 /*
1451 * clear the local variable.
1452 */
1453 memset (&h_para->freq_short_list_before, 0,
1454 sizeof (T_f_range));
1455
1456 /*
1457 * copy the content of the information element.
1458 */
1459 memcpy (&h_para->freq_short_list_before,
1460 &handov_cmd->freq_short_list_before,
1461 sizeof (BUF_freq_short_list_before));
1462
1463 /*
1464 * build a list for layer 1.
1465 */
1466 for_create_channel_list (&h_para->freq_short_list_before,
1467 &h_para->hop_list_before);
1468 /* check if all frequencies are in one band */
1469 if(! srv_check_frequencies_in_list (&h_para->hop_list_before))
1470 {
1471 for_set_content_error(RRC_FREQ_NOT_IMPL);
1472 }
1473 }
1474
1475 if (handov_cmd->v_freq_list_before)
1476 {
1477 /* Implements RR Clone findings #7 */
1478 for_frequency_list (&handov_cmd->freq_list_before,
1479 &h_para->freq_list_before,
1480 &h_para->hop_list_before);
1481 }
1482
1483 if (handov_cmd->v_freq_chan_seq_before)
1484 {
1485 /*
1486 * the message contains a frequency channel sequence element to
1487 * build the frequency hopping list.
1488 */
1489 if (!for_create_delta_list ((T_freq_chan_seq_after *)
1490 &handov_cmd->freq_chan_seq_before,
1491 &h_para->hop_list_before))
1492 {
1493 /*
1494 * set a content error if the frequency hopping list
1495 * contains channel numbers which are not supported.
1496 */
1497 for_set_content_error (RRC_FREQ_NOT_IMPL);
1498 }
1499 }
1500
1501 /*
1502 * handle the message, configure layer 1 etc.
1503 */
1504 dat_for_handov_cmd (dl_data_ind, handov_cmd, &h_para->cell_chan_desc,
1505 &h_para->hop_list_after, &h_para->hop_list_before);
1506 /*
1507 * de-allocate the dynamic memory
1508 */
1509 MFREE (h_para);
1510 }
1511
1512
1513 /*
1514 +--------------------------------------------------------------------+
1515 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1516 | STATE : code ROUTINE : for_create_channel_list |
1517 +--------------------------------------------------------------------+
1518
1519 PURPOSE : The function creates a frequency hopping list from one of
1520 the following information elements according GSM 4.08:
1521
1522 cell channel description
1523 frequency list
1524 frequency short list
1525 neighbour cell description
1526
1527 The format identifier of the information element is defined as:
1528
1529 FORMAT-ID, Format Identifier
1530
1531 Bit Bit Bit Bit Bit format notation
1532 8 7 4 3 2
1533
1534 0 0 X X X bit map 0
1535 1 0 0 X X 1024 range
1536 1 0 1 0 0 512 range
1537 1 0 1 0 1 256 range
1538 1 0 1 1 0 128 range
1539 1 0 1 1 1 variable bit map
1540
1541 */
1542
1543 GLOBAL void for_create_channel_list (T_f_range * cha_list_descr,
1544 T_LIST * cha_list)
1545 {
1546 /*
1547 * set a pointer to the begin of the array
1548 */
1549 UBYTE *cha_ptr = &cha_list_descr->
1550 b_f[cha_list_descr->o_f>>3];
1551
1552 TRACE_FUNCTION ("for_create_channel_list()");
1553
1554 /*
1555 * clear result list
1556 */
1557 srv_clear_list (cha_list);
1558
1559 if ((*cha_ptr & 0x80) EQ 0)
1560 {
1561 /*
1562 * Bitmap 0 format
1563 * only for GSM 900 or GSM 850 bands !!!!
1564 */
1565 switch (std)
1566 {
1567 case STD_900:
1568 case STD_EGSM:
1569 case STD_DUAL:
1570 case STD_DUAL_EGSM:
1571 case STD_850:
1572 case STD_DUAL_US:
1573 #ifdef TI_PS_FF_QUAD_BAND_SUPPORT
1574 case STD_850_1800:
1575 case STD_900_1900:
1576 case STD_850_900_1800:
1577 case STD_850_900_1900:
1578 #endif
1579 /*
1580 * clear the format identifier
1581 */
1582 *cha_ptr = *cha_ptr & 0x0F;
1583
1584 TRACE_EVENT_WIN ("bitmap 0 format");
1585 /*
1586 * resulting list has bitmap 0 format !
1587 * copy only the content of the GSM 900 or GSM 850 channels
1588 * equal to the first 16 byte.
1589 */
1590 memcpy (&cha_list->channels[T_LIST_MAX_SIZE-16], cha_ptr, 16);
1591 break;
1592
1593 default:
1594 /*
1595 * for PCS 1900 or DCS 1800 ignore the information element.
1596 */
1597 break;
1598 }
1599 }
1600 else
1601 {
1602 if ((*cha_ptr &0x8E) EQ 0x8C)
1603 {
1604
1605 /* Implements RR Clone findings #20 */
1606 for_decode_param_freq(128,cha_list_descr,cha_list);
1607
1608 }
1609
1610 if ((*cha_ptr &0x8E) EQ 0x8A)
1611 {
1612 /*
1613 * RANGE 256
1614 *
1615 * Use dynamic memory for calculation instead of global memory or stack.
1616 */
1617 /* Implements RR Clone findings #20 */
1618 for_decode_param_freq(256,cha_list_descr,cha_list);
1619
1620 }
1621
1622 if ((*cha_ptr &0x8E) EQ 0x88)
1623 {
1624 /*
1625 * RANGE 512
1626 *
1627 * Use dynamic memory for calculation instead of global memory or stack.
1628 */
1629 /* Implements RR Clone findings #21 */
1630 for_decode_param_freq(512,cha_list_descr,cha_list);
1631
1632
1633 }
1634
1635 if ((*cha_ptr &0x88) EQ 0x80)
1636 {
1637 /*
1638 * RANGE 1024
1639 *
1640 * Use dynamic memory for calculation instead of global memory or stack.
1641 */
1642 UBYTE f0;
1643
1644 SHORT *w;
1645 MALLOC (w, 257 * sizeof (USHORT));
1646
1647 TRACE_EVENT_WIN ("range 1024 format");
1648
1649 /*
1650 * get the f0 indicator. It indicates whether channel 0 is part
1651 * of the frequency hopping list or not.
1652 */
1653 ccd_decodeByte (cha_list_descr->b_f,
1654 (USHORT)(cha_list_descr->o_f+5),
1655 1, &f0);
1656
1657 /*
1658 * decode the W-parameter
1659 */
1660 for_decode_param_1024 (w, cha_list_descr);
1661
1662 /*
1663 * If indicated add channel 0 to the list
1664 */
1665 if (f0)
1666 srv_set_channel (cha_list, CHANNEL_0);
1667
1668 /*
1669 * decode and set the remaining channel number according the
1670 * algorithm described in GSM 4.08.
1671 */
1672 for_decode_frequencies (1023, &w[0], cha_list, 0);
1673
1674 /*
1675 * free the dynamic allocated memory.
1676 */
1677 MFREE (w);
1678 }
1679
1680 if ((*cha_ptr &0x8E) EQ 0x8E)
1681 {
1682 /*
1683 * RANGE variable
1684 *
1685 * The format is similar to the bitmap 0 format. The
1686 * calculation starts from a base channel number svalue
1687 * instead of channel number 1.
1688 */
1689 ULONG lvalue;
1690 USHORT svalue;
1691 UBYTE bvalue;
1692 USHORT i;
1693
1694 TRACE_EVENT_WIN ("range variable format");
1695
1696 /*
1697 * get the first channel number
1698 */
1699 ccd_decodeLong (cha_list_descr->b_f, 7, 10, &lvalue);
1700
1701 /*
1702 * copy lvalue to svalue to set the correct channel
1703 */
1704 svalue = (USHORT)lvalue;
1705 srv_set_channel (cha_list, svalue);
1706
1707 for (i=1;i<112;i++)
1708 {
1709 /*
1710 * get the value of the next bit
1711 */
1712 ccd_decodeByte (cha_list_descr->b_f,(USHORT)(i+16),1, &bvalue);
1713
1714 if (bvalue)
1715 {
1716 /*
1717 * If the bit is set, set channel i+svalue
1718 */
1719 srv_set_channel (cha_list, (USHORT)for_modulo(i+svalue, 1024));
1720 }
1721 }
1722 }
1723 }
1724 }
1725
1726 /*
1727 +--------------------------------------------------------------------+
1728 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1729 | STATE : code ROUTINE : for_create_delta_list |
1730 +--------------------------------------------------------------------+
1731
1732 PURPOSE : The function creates a frequency hopping list from the
1733 frequency channel sequence information element. This
1734 information element contains only GSM 900 channel numbers.
1735
1736 The first channel number is stored in low_arfcn. The several
1737 increments are defined by the information element which are
1738 added to this starting frequency.
1739
1740 */
1741
1742 static BOOL for_create_delta_list (T_freq_chan_seq_after *delta_list,
1743 T_LIST *cha_list)
1744 {
1745 USHORT i;
1746 UBYTE result = TRUE;
1747 USHORT delta;
1748
1749 /*
1750 * set the first cannel number.
1751 */
1752 USHORT cha_num = delta_list->low_arfcn;
1753
1754 TRACE_FUNCTION ("for_create_delta_list()");
1755
1756 /*
1757 * Check whether it is a GSM 900 channel number
1758 */
1759 if (cha_num < LOW_CHANNEL_900 OR
1760 cha_num > HIGH_CHANNEL_900)
1761 result = FALSE;
1762
1763 /*
1764 * clear the output parameter for the calculated frequency hopping list.
1765 */
1766 srv_clear_list (cha_list);
1767
1768 /*
1769 * set the first channel number.
1770 */
1771 srv_set_channel (cha_list, cha_num);
1772
1773 /*
1774 * for the 16 possible increments
1775 */
1776 for (i = 0; i < 16; i++)
1777 {
1778 /*
1779 * get the delta
1780 */
1781 delta = (USHORT) delta_list->inc_skip[i];
1782
1783 /*
1784 * if delta is equal to 0, add 15 to the base, but
1785 * do not store in the output list.
1786 */
1787 if (! delta)
1788 cha_num += 15;
1789 else
1790 {
1791 /*
1792 * add the delta to the base
1793 */
1794 cha_num += delta;
1795
1796 /*
1797 * Check whether it is a GSM 900 channel number
1798 */
1799 if (cha_num < LOW_CHANNEL_900 OR
1800 cha_num > HIGH_CHANNEL_900)
1801 result = FALSE;
1802
1803 /*
1804 * set the new frequency
1805 */
1806 srv_set_channel (cha_list, cha_num);
1807 }
1808 }
1809
1810 return result;
1811 }
1812
1813 /*
1814 +--------------------------------------------------------------------+
1815 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1816 | STATE : code ROUTINE : for_decode_param_1024 |
1817 +--------------------------------------------------------------------+
1818
1819 PURPOSE : The W-parameter in the 1024 range start from bit 6 of the
1820 information element. The following table indicate the number
1821 of W-parameters and their length in bits. A length of zero
1822 indicated the end of the table.
1823
1824 */
1825
1826 static const T_W_PARAM param_1024[9] =
1827 {
1828 /*
1829 * length count
1830 */
1831 10, 1,
1832 9, 2,
1833 8, 4,
1834 7, 8,
1835 6, 16,
1836 5, 32,
1837 4, 64,
1838 3, 128,
1839 0, 0
1840 };
1841
1842
1843 static void for_decode_param_1024 (SHORT *w,
1844 T_f_range *cha)
1845 {
1846 TRACE_FUNCTION ("for_decode_param_1024");
1847
1848 /*
1849 * the algorithm for the several ranges is the same with different
1850 * tables. The W-parameter start with bit 6.
1851 */
1852 for_decode_param (param_1024, w, cha, 6);
1853 }
1854
1855 /*
1856 +--------------------------------------------------------------------+
1857 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1858 | STATE : code ROUTINE : for_decode_param_512 |
1859 +--------------------------------------------------------------------+
1860
1861 PURPOSE : The W-parameter in the 512 range start from bit 7 of the
1862 information element. The following table indicate the number
1863 of W-parameters and their length in bits. A length of zero
1864 indicated the end of the table.
1865
1866 */
1867
1868 static const T_W_PARAM param_512[10] =
1869 {
1870 /*
1871 * length count
1872 */
1873 10, 1,
1874 9, 1,
1875 8, 2,
1876 7, 4,
1877 6, 8,
1878 5, 16,
1879 4, 32,
1880 3, 64,
1881 2, 128,
1882 0, 0
1883 };
1884
1885
1886 /*
1887 +--------------------------------------------------------------------+
1888 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1889 | STATE : code ROUTINE : for_decode_param_256 |
1890 +--------------------------------------------------------------------+
1891
1892 PURPOSE : The W-parameter in the 256 range start from bit 7 of the
1893 information element. The following table indicate the number
1894 of W-parameters and their length in bits. A length of zero
1895 indicated the end of the table.
1896
1897 */
1898
1899 static const T_W_PARAM param_256[10] =
1900 {
1901 /*
1902 * length count
1903 */
1904 10, 1,
1905 8, 1,
1906 7, 2,
1907 6, 4,
1908 5, 8,
1909 4, 16,
1910 3, 32,
1911 2, 64,
1912 1, 128,
1913 0, 0
1914 };
1915
1916
1917
1918 /*
1919 +--------------------------------------------------------------------+
1920 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1921 | STATE : code ROUTINE : for_decode_param_128 |
1922 +--------------------------------------------------------------------+
1923
1924 PURPOSE : The W-parameter in the 128 range start from bit 7 of the
1925 information element. The following table indicate the number
1926 of W-parameters and their length in bits. A length of zero
1927 indicated the end of the table.
1928
1929 */
1930
1931 static const T_W_PARAM param_128[9] =
1932 {
1933 /*
1934 * length count
1935 */
1936 10, 1,
1937 7, 1,
1938 6, 2,
1939 5, 4,
1940 4, 8,
1941 3, 16,
1942 2, 32,
1943 1, 64,
1944 0, 0
1945 };
1946
1947
1948
1949 /*
1950 +--------------------------------------------------------------------+
1951 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
1952 | STATE : code ROUTINE : for_decode_param |
1953 +--------------------------------------------------------------------+
1954
1955 PURPOSE : The information element contains a list of W-parameter.
1956 The table param indicates how many W-parameter from each
1957 length shall be inside. The function converts the bitstream
1958 of the W-parameter to an array of W-parameter 16 bit values.
1959
1960 */
1961
1962 static void for_decode_param (const T_W_PARAM *param,
1963 SHORT *w,
1964 T_f_range *cha,
1965 USHORT initial_offset)
1966 {
1967 UBYTE end_detected = FALSE;
1968 USHORT w_index = 0;
1969 USHORT offset = cha->o_f + initial_offset;
1970 USHORT length = cha->l_f - initial_offset;
1971 USHORT act_length = param->length;
1972 USHORT act_counter = param->count;
1973 ULONG lvalue;
1974 UBYTE bvalue;
1975
1976 TRACE_FUNCTION ("for_decode_param()");
1977
1978 /*
1979 * Until the end of the information element is detected.
1980 */
1981 while (!end_detected)
1982 {
1983 if (act_length > 8)
1984 {
1985 /*
1986 * the length of the next W-parameter is greater than eight bits
1987 * so use the ccd_decodeLong function.
1988 */
1989 ccd_decodeLong (cha->b_f, offset, act_length, &lvalue);
1990 w[w_index++] = (SHORT)lvalue;
1991 }
1992 else
1993 {
1994 /*
1995 * else use the ccd_decodeByte function to extract the W-parameter
1996 * from the bitstream.
1997 */
1998 ccd_decodeByte (cha->b_f, offset, act_length, &bvalue);
1999 w[w_index++] = (SHORT)bvalue;
2000 }
2001
2002 /*
2003 * w = 0 is equal to end of list if it is not the w(0) !!!
2004 */
2005 if (w_index NEQ 1)
2006 if (w[w_index-1] EQ 0)
2007 end_detected = TRUE;
2008
2009 /*
2010 * end of buffer is equal to end of list
2011 */
2012 if (length > act_length)
2013 {
2014 length -= act_length;
2015 offset += act_length;
2016 }
2017 else
2018 end_detected = TRUE;
2019
2020 /*
2021 * all w parameter of one size read
2022 */
2023 if (--act_counter EQ 0)
2024 {
2025 param++;
2026 act_length = param->length;
2027 act_counter = param->count;
2028 }
2029 /*
2030 * End of parameter table
2031 */
2032 if ((act_length EQ 0) OR (length < act_length))
2033 end_detected = TRUE;
2034 }
2035
2036 /*
2037 * add an end identifier
2038 */
2039 w[w_index++] = 0;
2040 }
2041
2042
2043 /*
2044 +--------------------------------------------------------------------+
2045 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2046 | STATE : code ROUTINE : for_decode_frequencies |
2047 +--------------------------------------------------------------------+
2048
2049 PURPOSE : The algorithm is according GSM 4.08 Annex J. It calculates
2050 a frequency hopping list from the W-parameter.
2051
2052 */
2053
2054 static void for_decode_frequencies (SHORT original_range,
2055 SHORT *w,
2056 T_LIST *f,
2057 SHORT offset)
2058 {
2059 SHORT g;
2060 SHORT k;
2061 SHORT j;
2062 SHORT index;
2063 SHORT n;
2064 SHORT range;
2065
2066 TRACE_FUNCTION ("for_decode_frequencies()");
2067
2068 for (k = 1; w[k-1]; k++)
2069 {
2070 /*
2071 * The next loop follows the tree from child to parent,
2072 * from the node of index K to the root (index 1). For each iteration the
2073 * node of index INDEX is tackled. The corresponding range is RANGE, and N
2074 * is the value of the element in the range defined by the node.
2075 *
2076 * The data are set to their initial values
2077 */
2078 index = k;
2079 n = w[index-1];
2080 g = for_get_generation (index);
2081 j = (1 << (g-1));
2082 range = original_range / j;
2083
2084 while (index > 1)
2085 {
2086 /*
2087 * Due to the assumption that the original range is a power of two minus one,
2088 * the range for the parent node can be easily computed, and does not depend
2089 * upon whether the current node is a left or right child
2090 */
2091 g = for_get_generation (index);
2092 j = (1 << (g-1));
2093 range = 2 * range + 1;
2094
2095 /*
2096 * Let us note J := 2 g-1 , g being the generation of node INDEX. We have J =
2097 * GREATEST_POWER_OF_2_LESSER_OR_EQUAL_TO(INDEX). The numbering used in the tree
2098 * is such that the nodes of index J to J + J/2 - 1 are left children, and the nodes
2099 * of index J/2 to J+J-1 are right children. Hence an easy test to
2100 * distinguish left and right children:
2101 */
2102 if (2 * index < 3 * j)
2103 {
2104 /*
2105 * The next computation gives the index of the parent node of the node of index
2106 * INDEX, for a left child :
2107 */
2108 index = index - j / 2;
2109
2110 /*
2111 * The next formula is the inverse of the renumbering appearing in the encoding
2112 * for a left child. It gives the value of the parent node in the range defined
2113 * by the grand-parent node:
2114 */
2115 n = (SHORT)for_smodulo (n + w[index-1] + (range-1) / 2, range);
2116 }
2117 else
2118 {
2119 /*
2120 * The next computation gives the index of the parent node of the node of index
2121 * INDEX, for a right child :
2122 */
2123 index = index - j;
2124
2125 /*
2126 * The next formula is the inverse of the renumbering appearing in the encoding
2127 * for a right child:
2128 */
2129 n = (SHORT)for_smodulo (n + w[index-1], range);
2130 }
2131 }
2132
2133 /*
2134 * set the calculated channel number.
2135 */
2136 srv_set_channel (f, (USHORT)for_modulo (n+offset, 1024));
2137 }
2138 }
2139
2140
2141 /*
2142 +--------------------------------------------------------------------+
2143 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2144 | STATE : code ROUTINE : for_get_generation |
2145 +--------------------------------------------------------------------+
2146
2147 PURPOSE : The function calculates the greatest power of 2 of the given
2148 value. The algorithm simply looks to the position of the
2149 highest bit.
2150
2151 */
2152
2153 static USHORT for_get_generation (USHORT value)
2154 {
2155 int result = 0;
2156 int i;
2157
2158
2159 /*
2160 * check all 16 bit positions.
2161 */
2162 for (i = 0; i < 16; i++)
2163 {
2164 /*
2165 * if bit is set, store the position.
2166 */
2167 if (value & 1)
2168 result = i + 1;
2169
2170 /*
2171 * shift value to have the next bit for
2172 * comparision.
2173 */
2174 value = value >> 1;
2175 }
2176
2177 /*
2178 * return the highest position.
2179 */
2180 return result;
2181 }
2182
2183 /*
2184 +--------------------------------------------------------------------+
2185 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2186 | STATE : code ROUTINE : for_modulo |
2187 +--------------------------------------------------------------------+
2188
2189 PURPOSE : A modulo calculation function. The standard C-Operator
2190 fails for negative values ! (e.g. -4 mod 6 is 2 and not 4).
2191
2192 */
2193
2194 static LONG for_modulo (LONG a, LONG b)
2195 {
2196 long result;
2197
2198 /*
2199 * use standard C-Operator for calculation
2200 */
2201 result = a % b;
2202
2203 /*
2204 * correct the result for negative values.
2205 */
2206 if (result < 0)
2207 result += b;
2208
2209 return result;
2210 }
2211
2212 /*
2213 +--------------------------------------------------------------------+
2214 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2215 | STATE : code ROUTINE : for_smodulo |
2216 +--------------------------------------------------------------------+
2217
2218 PURPOSE : Similar to the modulo operator, but 0 smod n is n and
2219 not 0. Same problem for negative values with the standard
2220 C-Operator.
2221
2222 */
2223
2224 static LONG for_smodulo (LONG a, LONG b)
2225 {
2226 long result;
2227
2228 /*
2229 * use standard C-Operator for calculation
2230 */
2231 result = a % b;
2232
2233 /*
2234 * correct the result for negative values.
2235 */
2236 if (result < 0)
2237 result += b;
2238
2239 /*
2240 * special handling for result equal 0
2241 */
2242 if (result EQ 0)
2243 result = b;
2244
2245 return result;
2246 }
2247
2248 /*
2249 +--------------------------------------------------------------------+
2250 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2251 | STATE : code ROUTINE : for_set_conditional_error |
2252 +--------------------------------------------------------------------+
2253
2254 PURPOSE : set a conditional error.
2255
2256 */
2257
2258 static void for_set_conditional_error (void)
2259 {
2260 GET_INSTANCE_DATA;
2261 TRACE_FUNCTION ("for_set_conditional_error()");
2262
2263 switch (rr_data->ms_data.error.cs)
2264 {
2265 /* case RRC_INVALID_MAN_INFO: this value is currently never set */
2266 case RRC_INCORRECT_MSG:
2267 break;
2268
2269 default:
2270 /*
2271 * set the conditional information element error.
2272 */
2273 rr_data->ms_data.error.cs = RRC_COND_IE_ERROR;
2274 break;
2275 }
2276 }
2277
2278 /*
2279 +--------------------------------------------------------------------+
2280 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2281 | STATE : code ROUTINE : for_set_content_error |
2282 +--------------------------------------------------------------------+
2283
2284 PURPOSE : set a content error.
2285
2286 */
2287
2288 GLOBAL void for_set_content_error (UBYTE value)
2289 {
2290 GET_INSTANCE_DATA;
2291 TRACE_FUNCTION ("for_set_content_error()");
2292
2293 switch (rr_data->ms_data.error.cs)
2294 {
2295 /* case RRC_INVALID_MAN_INFO: this value is currently never set */
2296 case RRC_COND_IE_ERROR:
2297 case RRC_INCORRECT_MSG:
2298 /*
2299 * Ignore a content error, if already an error with higher
2300 * priority has been detected.
2301 */
2302 break;
2303
2304 default:
2305 /*
2306 * store the content error.
2307 */
2308 rr_data->ms_data.error.cs = RRC_INCORRECT_MSG;
2309 rr_data->ms_data.error.val = value;
2310 break;
2311 }
2312 }
2313
2314 /*
2315 +--------------------------------------------------------------------+
2316 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2317 | STATE : code ROUTINE : for_suspend_layer_2 |
2318 +--------------------------------------------------------------------+
2319
2320 PURPOSE : suspend layer 2 in case of assignment or handover command.
2321
2322 */
2323
2324 GLOBAL void for_suspend_layer_2 (void)
2325 {
2326 GET_INSTANCE_DATA;
2327 PALLOC (dl_suspend_req, DL_SUSPEND_REQ);
2328
2329 TRACE_FUNCTION ("for_suspend_layer_2()");
2330
2331 /*
2332 * set channel type and SAPI for layer 2.
2333 */
2334 dat_code_prr_channel (&dl_suspend_req->ch_type,
2335 &dl_suspend_req->sapi,
2336 rr_data->sc_data.chan_desc.chan_type);
2337
2338 PSENDX (DL, dl_suspend_req);
2339 }
2340
2341
2342 /*
2343 +--------------------------------------------------------------------+
2344 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2345 | STATE : code ROUTINE : for_frequency_list |
2346 +--------------------------------------------------------------------+
2347
2348 PURPOSE : This function creates a frequency list and channel list
2349
2350 */
2351 LOCAL void for_frequency_list(T_freq_list *freq_list_starting_time_cmd,
2352 T_f_range *freq_list_starting_time_para,
2353 T_LIST *hop_list_starting_time)
2354 {
2355 TRACE_FUNCTION("for_frequency_list()");
2356
2357 memset (freq_list_starting_time_para, 0, sizeof (T_f_range));
2358 memcpy (freq_list_starting_time_para->b_f,
2359 freq_list_starting_time_cmd->flist,
2360 freq_list_starting_time_cmd->c_flist);
2361 freq_list_starting_time_para->l_f = 8*freq_list_starting_time_cmd->c_flist;
2362
2363 /*
2364 * create a frequency list.
2365 */
2366 for_create_channel_list (freq_list_starting_time_para, hop_list_starting_time);
2367
2368 /* check if all frequencies are in one band */
2369 if(! srv_check_frequencies_in_list (hop_list_starting_time))
2370 {
2371 for_set_content_error(RRC_FREQ_NOT_IMPL);
2372 }
2373 }
2374
2375 /*
2376 +--------------------------------------------------------------------+
2377 | PROJECT : GSM-PS (6147) MODULE : RR_FOR |
2378 | STATE : code ROUTINE : for_decode_param_freq |
2379 +--------------------------------------------------------------------+
2380
2381 PURPOSE : This function decodes the frequency parameter from the channel
2382 description IE
2383
2384 */
2385 LOCAL void for_decode_param_freq(USHORT range ,T_f_range *cha_list_descr,
2386 T_LIST *cha_list)
2387 {
2388 SHORT *w;
2389 SHORT size_mul;
2390 const T_W_PARAM *param_ptr;
2391
2392 TRACE_FUNCTION("for_decode_param_freq()");
2393 /*
2394 * RANGE 128/256/512
2395 *
2396 * Use dynamic memory for calculation instead of global memory or stack.
2397 */
2398 switch(range)
2399 {
2400 case 128:
2401 TRACE_EVENT_WIN ("range 128 format");
2402 size_mul = 129;
2403 param_ptr = param_128;
2404
2405 break;
2406 case 256:
2407 TRACE_EVENT_WIN ("range 256 format");
2408 size_mul = 257;
2409 param_ptr = param_256;
2410 break;
2411 case 512:
2412 TRACE_EVENT_WIN ("range 512 format");
2413 size_mul = 257;
2414 param_ptr = param_512;
2415 break;
2416 default:
2417 size_mul = 0;
2418 param_ptr = NULL;
2419 break;
2420 }
2421
2422 MALLOC (w, size_mul * sizeof (USHORT));
2423 for_decode_param (param_ptr, w, cha_list_descr, 7);
2424
2425 /*
2426 * W[0] contains the first channel number
2427 */
2428 srv_set_channel (cha_list, w[0]);
2429
2430 /*
2431 * decode and set the remaining channel number according the
2432 * algorithm described in GSM 4.08.
2433 */
2434 for_decode_frequencies ((range -1), &w[1], cha_list, w[0]);
2435
2436 /*
2437 * free the dynamic allocated memory.
2438 */
2439 MFREE (w);
2440 }
2441
2442 #if defined (REL99) && defined (TI_PS_FF_EMR)
2443 /*[xgiridha] : EMR */
2444 /*
2445 +------------------------------------------------------------------------------
2446 | Function : for_process_si2quater
2447 +------------------------------------------------------------------------------
2448 | Description : Process SI-2quater information and store it in enh_para of serving cell
2449 | This is a multi instance message. check whether all the instances are
2450 | received or not before indicating to ALR and to GRR,if required.
2451 |
2452 | Parameters : SI-2quater rest octets
2453 |
2454 +------------------------------------------------------------------------------
2455 */
2456 GLOBAL BOOL for_process_si2quater(T_si_2qua_octets *p_si2q)
2457 {
2458 GET_INSTANCE_DATA;
2459 T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current;
2460 T_rr_enh_para *p_temp = &rr_data->sc_data.emr_data_temp;
2461 BOOL send_enh_para = FALSE;
2462 T_gprs_rep_prio *p_rep = NULL;
2463 T_gprs_bsic *p_bsic = NULL;
2464
2465 #if defined (TI_PS_FF_RTD) AND defined (REL99)
2466 UBYTE i,j;
2467 #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */
2468
2469 TRACE_FUNCTION ("for_process_si2quater");
2470
2471 /* Step 1: Check if we received right BA_IND */
2472 if((rr_data->sc_data.ba_index NEQ NOT_PRESENT_8BIT) AND (p_si2q->ba_ind NEQ rr_data->sc_data.ba_index ))
2473 {
2474 /* re-read si2qtr*/
2475
2476 if(rr_data->sc_data.cd.si2quater_status EQ SI2QUATER_ABSENT OR
2477 rr_data->sc_data.cd.si2quater_status EQ SI2QUATER_ACQ_PENDING)
2478 {
2479 TRACE_EVENT("This is not the right BA_IND set that we have. So,ignore this SI-2quater");
2480 rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_WRONG_BAIND;
2481 {
2482 PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
2483 mph_mon_ctrl_req->action = STOP_MON_BCCH;
2484 mph_mon_ctrl_req->si_to_read = UPDATE_SI2QUATER_AGAIN;
2485 PSENDX (PL, mph_mon_ctrl_req);
2486 }
2487 }
2488 else
2489 {
2490 TRACE_EVENT("This is not the right BA_IND set that we have.Re-read SI-2quater");
2491 rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_PENDING;
2492 {
2493 PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
2494 if ( rr_data->sc_data.cd.si2quater_pos EQ SI2QUATER_ON_EBCCH )
2495 {
2496 mph_mon_ctrl_req->action = START_MON_EBCCH;
2497 }
2498 else
2499 {
2500 mph_mon_ctrl_req->action = START_MON_NBCCH;
2501 }
2502 mph_mon_ctrl_req->si_to_read = UPDATE_SI2QUATER_AGAIN;
2503 PSENDX (PL, mph_mon_ctrl_req);
2504 }
2505 }
2506 return send_enh_para;
2507 }
2508
2509 /* Step 2: Check report type.
2510 IMPORTANT ASSUMPTION: We process only NC PARA (if present) if report type is Normal*/
2511 if( !(( (p_si2q->v_gprs_meas_para EQ TRUE) AND (p_si2q->gprs_meas_para.report_type EQ ENHANCED_MEAS)) OR
2512 ( (p_si2q->v_meas_para EQ TRUE) AND (p_si2q->meas_para.report_type EQ ENHANCED_MEAS )) ) )
2513 {
2514 /*check whether there are enhanced parameters and BA list already.
2515 If present then it means that report type is changing from
2516 Enhanced to Normal*/
2517 if ( p_cur->is_data_valid EQ TRUE )
2518 {
2519 for_set_default_emr_data(p_cur);
2520 #ifdef GPRS
2521 if (p_si2q->v_nc_meas_para EQ TRUE)
2522 for_store_nc_para(&p_si2q->nc_meas_para, p_cur);
2523 #endif
2524 return TRUE; /*send enh para update to indicate change in report type and NC para*/
2525 }
2526 else
2527 return send_enh_para;
2528 }
2529
2530 /* Step 3: Check if we already have enh_para in current or temp
2531 and if there is change in parameters or continuation of reception*/
2532 if(p_temp->is_data_valid EQ FALSE )
2533 {
2534 /*This means we were not in the process of receiving. Check whether there
2535 is already information in current and if so, is there change in mp_change_mark*/
2536 if( (p_cur->mp_change_mark NEQ NOT_PRESENT_8BIT) AND
2537 (p_cur->mp_change_mark EQ p_si2q->mp_change_mark ) )
2538 {
2539 TRACE_EVENT("No change in Enhanced measurement parameters -ignore ");
2540 return TRUE;
2541 }
2542 /* decode rest of the parameters*/
2543 p_temp->is_data_valid = TRUE;
2544 rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE;
2545 p_temp->enh_para.ncc_permitted = rr_data->sc_data.cd.ncc_permitted;
2546 rr_data->sc_data.ba_index = p_si2q->ba_ind;
2547 }
2548 /*Note :If different values occur for the same parameter in different instances of a message,
2549 the instance with the highest index shall be used (sec.3.4.1.2.1, 4.18)*/
2550 if ( (p_si2q->si2qua_index > rr_data->sc_data.prev_highest_index ) OR
2551 (rr_data->sc_data.prev_highest_index EQ NOT_PRESENT_8BIT) )
2552 {
2553 p_temp->mp_change_mark = p_si2q->mp_change_mark;
2554 p_temp->msg_count = p_si2q->si2qua_count;
2555 for_update_emr_rep_para(p_si2q,p_temp); /* This is updation of parameters other than BSIC list*/
2556 rr_data->sc_data.prev_highest_index = p_si2q->si2qua_index;
2557 #if defined (TI_PS_FF_RTD) AND defined (REL99)
2558 if(p_si2q->v_rtdd)
2559 for_store_rtd_data(p_si2q,p_temp);
2560 #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */
2561
2562 }
2563
2564 if(p_si2q->v_gprs_rep_prio EQ TRUE)
2565 p_rep = &p_si2q->gprs_rep_prio;
2566
2567 if(p_si2q->v_gprs_bsic EQ TRUE)
2568 p_bsic = &p_si2q->gprs_bsic;
2569
2570 if (for_process_common_emr_data(p_rep,p_bsic,p_si2q->si2qua_index,
2571 rr_data->sc_data.ba_list_idle) )
2572 {
2573 rr_data->sc_data.enh_para_status = ENH_PARA_IDLE;
2574 #if defined (TI_PS_FF_RTD) AND defined (REL99)
2575 /* store the RTD values received in all instances of SI2quater in permanent location */
2576 if(p_si2q->v_rtdd)
2577 {
2578 memcpy(p_cur,p_temp,MAX_NR_OF_NCELL*sizeof(USHORT));
2579 /* reset the temporary storage to RTD value not available */
2580 for(j = 0;j < MAX_NR_OF_NCELL; j++ )
2581 {
2582 p_temp->enh_para.enh_cell_list[j].v_rtd = FALSE;
2583 for(i = 0;i < MAX_NUM_OF_RTD_VALUES; i++)
2584 p_temp->enh_para.enh_cell_list[j].rtd[i]= RTD_NOT_AVAILABLE;
2585 }/*for*/
2586 }/*if*/
2587 #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */
2588
2589 if ( rr_data->sc_data.ba_list_idle EQ TRUE)
2590 send_enh_para = TRUE;
2591 }
2592 return send_enh_para;
2593 }
2594
2595 /*
2596 +------------------------------------------------------------------------------
2597 | Function : for_update_emr_rep_para
2598 +------------------------------------------------------------------------------
2599 | Description : This function updates all the miscelaneous parameters related
2600 | to enhanced measurements. This doesn't include BSIC and Report priority
2601 | list.
2602 | Parameters : SI-2quater rest octets, target location where to store data
2603 +------------------------------------------------------------------------------
2604 */
2605 GLOBAL void for_update_emr_rep_para(T_si_2qua_octets *p_si2q,T_rr_enh_para *p_em)
2606 {
2607 #ifdef GPRS
2608 UBYTE state;
2609 GET_INSTANCE_DATA;
2610 #endif
2611 /*Decide whether to use GPRS part of measurement parameters or RR part*/
2612 TRACE_FUNCTION ("for_update_emr_rep_para");
2613
2614 #ifdef GPRS
2615 state = GET_STATE(STATE_GPRS);
2616 if( (state EQ GPRS_PIM_BCCH) OR (state EQ GPRS_PAM_BCCH) OR
2617 (state EQ GPRS_PTM_BCCH))
2618 {
2619 /*Use GPRS part*/
2620 if(p_si2q->v_gprs_meas_para EQ TRUE )
2621 {
2622 p_em->grr_rep_type = p_si2q->gprs_meas_para.report_type;
2623 p_em->enh_para.inv_bsic_enabled = p_si2q->gprs_meas_para.inv_bsic_rep;
2624 if ( p_si2q->gprs_meas_para.v_serv_band_rep EQ TRUE)
2625 p_em->enh_para.servingband_rep = p_si2q->gprs_meas_para.serv_band_rep;
2626 if( p_si2q->gprs_meas_para.v_mr EQ TRUE )
2627 p_em->enh_para.multiband_rep = p_si2q->gprs_meas_para.mr;
2628 p_em->enh_para.scale_order = p_si2q->gprs_meas_para.scale_ord;
2629 p_em->enh_para.rep_rate = p_si2q->gprs_meas_para.reporting_rate;
2630
2631 /* Update reporting thresholds and reporting offsets*/
2632 if (p_si2q->gprs_meas_para.v_report_900 EQ TRUE)
2633 {
2634 p_em->enh_para.enh_rep_data[0].rep_offset =
2635 p_si2q->gprs_meas_para.report_900.rep_offset_900;
2636 p_em->enh_para.enh_rep_data[0].rep_offset =
2637 p_si2q->gprs_meas_para.report_900.th_rep_900;
2638 }
2639 if (p_si2q->gprs_meas_para.v_report_1800 EQ TRUE)
2640 {
2641 p_em->enh_para.enh_rep_data[1].rep_offset =
2642 p_si2q->gprs_meas_para.report_1800.rep_offset_1800;
2643 p_em->enh_para.enh_rep_data[1].rep_offset =
2644 p_si2q->gprs_meas_para.report_1800.th_rep_1800;
2645 }
2646 if (p_si2q->gprs_meas_para.v_report_400 EQ TRUE)
2647 {
2648 p_em->enh_para.enh_rep_data[2].rep_offset =
2649 p_si2q->gprs_meas_para.report_400.rep_offset_400;
2650 p_em->enh_para.enh_rep_data[2].rep_offset =
2651 p_si2q->gprs_meas_para.report_400.th_rep_400;
2652 }
2653 if (p_si2q->gprs_meas_para.v_report_1900 EQ TRUE)
2654 {
2655 p_em->enh_para.enh_rep_data[3].rep_offset =
2656 p_si2q->gprs_meas_para.report_1900.rep_offset_1900;
2657 p_em->enh_para.enh_rep_data[3].rep_offset =
2658 p_si2q->gprs_meas_para.report_1900.th_rep_1900;
2659 }
2660 if (p_si2q->gprs_meas_para.v_report_850 EQ TRUE)
2661 {
2662 p_em->enh_para.enh_rep_data[4].rep_offset =
2663 p_si2q->gprs_meas_para.report_850.rep_offset_850;
2664 p_em->enh_para.enh_rep_data[4].rep_offset =
2665 p_si2q->gprs_meas_para.report_850.th_rep_850;
2666 }
2667 }
2668 /*Update Network Control (NC) parameters */
2669 if (p_si2q->v_nc_meas_para EQ TRUE )
2670 for_store_nc_para(&p_si2q->nc_meas_para,p_em);
2671 }
2672 else
2673 {
2674 #endif
2675 /* Use RR part */
2676 if(p_si2q->v_meas_para EQ TRUE )
2677 {
2678 p_em->rep_type = p_si2q->meas_para.report_type;
2679 p_em->enh_para.servingband_rep = p_si2q->meas_para.serv_band_rep;
2680 }
2681 #ifdef GPRS
2682 }
2683 #endif
2684 return;
2685 }
2686
2687 #ifdef GPRS
2688 static void for_store_nc_para(T_nc_meas_para *p_nc,T_rr_enh_para *p_em)
2689 {
2690 TRACE_FUNCTION ("for_store_nc_para");
2691 p_em->nc_para.nco = p_nc->nco;
2692 if(p_nc->v_nc_meas_struct EQ TRUE )
2693 {
2694 p_em->nc_para.is_valid = TRUE;
2695 p_em->nc_para.nc_non_drx = p_nc->nc_meas_struct.nc_non_drx;
2696 p_em->nc_para.nc_rep_per_i = p_nc->nc_meas_struct.nc_rep_i;
2697 p_em->nc_para.nc_rep_per_t = p_nc->nc_meas_struct.nc_rep_t;
2698 }
2699 return;
2700 }
2701 #endif
2702
2703 /*
2704 +------------------------------------------------------------------------------
2705 | Function : for_set_default_emr_data
2706 +------------------------------------------------------------------------------
2707 | Description : This function performs the default intialization of emr data
2708 | Parameters : target location where to initialize
2709 +------------------------------------------------------------------------------
2710 */
2711 GLOBAL void for_set_default_emr_data(T_rr_enh_para *p_em)
2712 {
2713 GET_INSTANCE_DATA;
2714 UBYTE i;
2715
2716 TRACE_FUNCTION ("for_set_default_emr_data");
2717
2718 memset(p_em, 0, sizeof(T_rr_enh_para));
2719 /*But there are some parameters whose default value is not 0, so we
2720 need to set them explicitly*/
2721 p_em->grr_rep_type = p_em->rep_type = NORMAL_MEAS; /*Default*/
2722
2723 #ifdef GPRS
2724 p_em->nc_para.nco = NCO_EMPTY; /*If GRR receives this value, it should not use
2725 entire nc parameters*/
2726 p_em->nc_para.is_valid = TRUE;
2727 p_em->nc_para.nc_non_drx = NC_0_48S;
2728 p_em->nc_para.nc_rep_per_i = NC_I_3_84S; /*see rr.aim for details*/
2729 p_em->nc_para.nc_rep_per_t = NC_I_61_44S;
2730 #endif
2731
2732 p_em->enh_para.scale_order = SCALE_0dB;
2733 p_em->enh_para.inv_bsic_enabled = FALSE;
2734 p_em->enh_para.rep_rate = NORMAL_RATE;
2735 p_em->enh_para.servingband_rep = DEFAULT_SERV_BAND_REP; /*Default value (3) */
2736 p_em->mp_change_mark = NOT_PRESENT_8BIT;
2737
2738 /* Default initialization of Reporting thresholds and offsets */
2739 for ( i=0; i<MAX_NUM_BANDS; i++)
2740 {
2741 p_em->enh_para.enh_rep_data[i].rep_threshold = REP_THRESHOLD_NONE;
2742 p_em->enh_para.enh_rep_data[i].rep_offset = REP_OFFSET_0;
2743 }
2744 rr_data->sc_data.rep_bmp = 0;
2745 rr_data->sc_data.instance_bmp = 0;
2746 rr_data->sc_data.prev_highest_index = NOT_PRESENT_8BIT;
2747 memset(rr_data->sc_data.bsic_list,0,MAX_MULTI_INST * sizeof(T_bsic_list));
2748 return;
2749 }
2750
2751 /*
2752 +------------------------------------------------------------------------------
2753 | Function : for_send_enh_para
2754 +------------------------------------------------------------------------------
2755 | Description : This function calls the functions needed to send ENH PARA to GRR
2756 | and ALR, under suitable conditions.
2757 | Parameters : enh para structure of RR
2758 +------------------------------------------------------------------------------
2759 */
2760 GLOBAL void for_send_enh_para(T_rr_enh_para *p_src)
2761 {
2762 UBYTE rep_type = p_src->rep_type;
2763 #ifdef GPRS
2764 GET_INSTANCE_DATA;
2765 #endif
2766 TRACE_FUNCTION ("for_send_enh_para");
2767 /* GRR is updated only in PIM/PAM/PTM when PBCCH is absent
2768 ALR is updated always with enhanced measurement parameters,
2769 it can be decided in ALR whether to use this information while
2770 sending report depending on report type*/
2771
2772 #ifdef GPRS
2773 {
2774 UBYTE state;
2775 state = GET_STATE(STATE_GPRS);
2776 if( (state EQ GPRS_PIM_BCCH) OR (state EQ GPRS_PAM_BCCH) OR
2777 (state EQ GPRS_PTM_BCCH))
2778 {
2779 att_send_enh_para_to_grr(p_src);
2780 if (p_src->grr_rep_type EQ REP_TYPE_ENH)
2781 rep_type = REP_TYPE_ENH;
2782 }
2783 }
2784 #endif
2785 attf_send_enh_para_to_alr(rep_type,&p_src->enh_para);
2786 return;
2787 }
2788
2789 /*
2790 +------------------------------------------------------------------------------
2791 | Function : for_perform_ba_bsic_mapping
2792 +------------------------------------------------------------------------------
2793 | Description : This function performs the BA list to BSIC list mapping, by taking BSIC list from
2794 | each instance of SI-2quater/MI-message and BA list. Here we store only the index into
2795 | BA list for ARFCN.
2796 | Parameters : Input:
2797 | BSIC list from air message
2798 | Output:
2799 | Update Enhanced cell list with BA indices.
2800 +------------------------------------------------------------------------------
2801 */
2802 LOCAL void for_perform_ba_bsic_mapping(T_gprs_bsic *p_bsic, T_enh_para_struct *p_enh )
2803 {
2804 UBYTE i=0;
2805 UBYTE j;
2806 UBYTE k=0;
2807
2808 TRACE_FUNCTION ("for_perform_ba_bsic_mapping");
2809 j = p_enh->num_valid_cells; /*If some cells were already filled from a previous instance,
2810 then this would be non-zero. We have to start updating this enhanced list from here*/
2811 if ( j >= MAX_NEIGHBOURCELLS )
2812 return; /* we cannot store any more neighbour cells, we only support GSM cells*/
2813
2814 if (p_bsic->v_ba_start_bsic EQ TRUE )
2815 i = p_bsic->ba_start_bsic;
2816 else
2817 i = 0;
2818
2819 /* Note : here we only store indices of ARFCNs*/
2820 /* Update from first BSIC, which is given outside the recursive structure*/
2821 p_enh->enh_cell_list[j].arfcn = i;
2822 p_enh->enh_cell_list[j].bsic = p_bsic->bsic;
2823 j++;
2824
2825 k = 0;
2826 if ( p_bsic->rem_bsic > 0)
2827 {
2828 while ( (k < p_bsic->rem_bsic) AND j < MAX_NEIGHBOURCELLS )
2829 {
2830 if (p_bsic->bsic_struct[k].freq_scroll EQ SCROL_NO)
2831 /* This means same frequency as before */
2832 p_enh->enh_cell_list[j].arfcn = i;
2833 else
2834 p_enh->enh_cell_list[j].arfcn = ++i;
2835 p_enh->enh_cell_list[j].bsic = p_bsic->bsic_struct[k].bsic;
2836 j++;
2837 k++;
2838 }
2839 }
2840 if ( j >= MAX_NEIGHBOURCELLS )
2841 p_enh->num_valid_cells = MAX_NEIGHBOURCELLS; /* we will not monitor more than 32 cells*/
2842 else
2843 p_enh->num_valid_cells = j;
2844 return;
2845 }
2846
2847 /*
2848 +------------------------------------------------------------------------------
2849 | Function : for_update_enh_cell_list
2850 +------------------------------------------------------------------------------
2851 | Description : This function updates the enhanced cell list with actual ARFCNs from
2852 | BA list. Note that this updation is always with respect to temp data base
2853 | and will be moved to current only if updation is successful.
2854 | If there are any indices pointing to unavailable ARFCN (due to SI-5ter)
2855 | then the updation is continued by marking that these need to be updated
2856 | later. In this case we still consider, updation to be successful.
2857 | Parameters : Input:
2858 | Stored BA list
2859 | Output:
2860 | TRUE - Updation successful
2861 | FALSE - Updation unsuccessful
2862 +------------------------------------------------------------------------------
2863 */
2864 GLOBAL BOOL for_update_enh_cell_list (USHORT *p_list)
2865 {
2866 GET_INSTANCE_DATA;
2867 T_rr_enh_para *p_enh = &rr_data->sc_data.emr_data_temp;
2868 T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current;
2869 UBYTE i;
2870 UBYTE j;
2871 ULONG rep_bmp = rr_data->sc_data.rep_bmp;
2872 ULONG ba_bitmap = 0;
2873
2874 TRACE_FUNCTION ("for_update_enh_cell_list");
2875 /*First check whether BSIC list was given or it's only updation
2876 of parameters*/
2877 if (p_enh->enh_para.num_valid_cells EQ 0)
2878 {
2879 /*There should be enhanced cell list atleast in current*/
2880 if ( (p_cur->is_data_valid EQ TRUE) AND (p_cur->enh_para.num_valid_cells > 0) )
2881 {
2882 /*This copy is actually over head, but done to maintain uniformity in
2883 copying after this function returns*/
2884 p_enh->enh_para.num_valid_cells = p_cur->enh_para.num_valid_cells;
2885 memcpy(p_enh->enh_para.enh_cell_list,p_cur->enh_para.enh_cell_list,
2886 p_cur->enh_para.num_valid_cells * sizeof(T_enh_cell_list));
2887 return TRUE;
2888 }
2889 else
2890 {
2891 TRACE_EVENT("BSIC Information required for enhanced reporting, is missing");
2892 return FALSE;
2893 }
2894 }
2895
2896 /*Under the conditions when this function is called, the
2897 enhanced cell list contains the index of the ARFCN in neighbourcell list*/
2898 for (i = 0; i < p_enh->enh_para.num_valid_cells; i++ )
2899 {
2900 j = (UBYTE)p_enh->enh_para.enh_cell_list[i].arfcn;
2901 p_enh->enh_para.enh_cell_list[i].rep_priority = (UBYTE) ((rep_bmp >> i) & 1);
2902 if ( p_list[j] NEQ NOT_PRESENT_16BIT )
2903 {
2904 ba_bitmap |= (1 << j);
2905 p_enh->enh_para.enh_cell_list[i].arfcn = p_list[j];
2906 }
2907 else
2908 {
2909 /*This indicates that we received BSIC for an unknown ARFCN. This ambiguity
2910 may be resolved once we receive SI-5ter*/
2911 p_enh->ba2bsic_map_pending |= ( 1<<i); /*set the bit of the corresponding index of enh-cell-list*/
2912 /*Index to BA(list) is retained as it is and actual ARFCN from this index is copied after receiving
2913 SI-5ter*/
2914 }
2915 }
2916
2917 /*verify whether the mapping is complete*/
2918 i = 0;
2919 while (p_list[i] NEQ NOT_PRESENT_16BIT)
2920 {
2921 if (( (ba_bitmap >> i) & 1) NEQ TRUE )
2922 {
2923 /* This indicates that there are still some ARFCN in BA list
2924 that doesn't have a corresponding BSIC */
2925 TRACE_EVENT("BA - BSIC list mapping is incorrect : IGNORE the message ");
2926 return FALSE;
2927 }
2928 i++;
2929 }
2930
2931 return TRUE;
2932 }
2933
2934 /*
2935 +------------------------------------------------------------------------------
2936 | Function : for_store_rep_priority
2937 +------------------------------------------------------------------------------
2938 | Description : This function stores the report priority temporarily in the form
2939 | of bit map.
2940 | Parameters : Input:
2941 | Reporting prioirty list from air message
2942 +------------------------------------------------------------------------------
2943 */
2944 LOCAL void for_store_rep_priority ( T_gprs_rep_prio *p_rp)
2945 {
2946 GET_INSTANCE_DATA;
2947 ULONG rep_bmp = 0;
2948 UBYTE i;
2949
2950 TRACE_FUNCTION ("for_store_rep_priority");
2951 /*IMPORTANT ASSUMPTION: since there is no index information
2952 associated explicitly with REPORT PRIORITY information, it's
2953 more likely that entire report priority info is given in one instance*/
2954 /* Only GSM neighbor cells upto 32 are supported */
2955 if (p_rp->num_cells > (MAX_NEIGHBOURCELLS -1) )
2956 p_rp->num_cells = MAX_NEIGHBOURCELLS -1;
2957
2958 for ( i = 0; i < p_rp->num_cells; i++ )
2959 {
2960 rep_bmp |= ( (p_rp->rep_priority[i] & 1) << i );
2961 }
2962 rr_data->sc_data.rep_bmp = rep_bmp;
2963 return;
2964 }
2965
2966 /*
2967 +------------------------------------------------------------------------------
2968 | Function : for_process_common_emr_data
2969 +------------------------------------------------------------------------------
2970 | Description : This function processes the EMR parameters that are common in
2971 | SI-2quater and MI messages.
2972 | Parameters : Input:
2973 | Reporting prioirty list from air message
2974 | BSIC list from air message
2975 | Enhanced para structure, where the data needs to be updated
2976 | message instance number
2977 | Output
2978 | TRUE - processing successful
2979 | FALSE - processing unsuccessful
2980 +------------------------------------------------------------------------------
2981 */
2982 GLOBAL BOOL for_process_common_emr_data (T_gprs_rep_prio *p_rep,
2983 T_gprs_bsic *p_bsic,
2984 UBYTE msg_index,
2985 BOOL ba_available)
2986 {
2987 GET_INSTANCE_DATA;
2988 T_bsic_list *p_bl = &rr_data->sc_data.bsic_list[0];
2989 T_rr_enh_para *p_enh = &rr_data->sc_data.emr_data_temp;
2990
2991 TRACE_FUNCTION ("for_process_common_emr_data");
2992 /*check for duplication of instance */
2993 if ( ((rr_data->sc_data.instance_bmp >> msg_index) & (0x01)) EQ TRUE )
2994 return FALSE; /*This instance was already received, so need to process
2995 it again*/
2996
2997 /*set the bit of the received instance in the bit map */
2998 rr_data->sc_data.instance_bmp |= (1 << msg_index);
2999
3000 /*Store report priority: Ref. sec.3.4.1.2.1.5, 4.18
3001 Report Priority information can be received in one instance of the MEASUREMENT INFORMATION message*/
3002 if(p_rep NEQ NULL)
3003 for_store_rep_priority(p_rep);
3004
3005 if(p_bsic NEQ NULL )
3006 {
3007 /*BSIC list is available, store it to perform BA-BSIC mapping at the end */
3008 p_bl[msg_index].is_valid = TRUE;
3009 p_bl[msg_index].bsic_info = *p_bsic;
3010 }
3011
3012 /*check whether all the instances are received or not
3013 Number of 1's in instance_bmp should equal msg_count+1
3014 Eg: if msg_count = 3, instance_bmp = 0000 0000 0000 1111 = 15
3015 2^(3+1)-1 = 15 */
3016 if ( rr_data->sc_data.instance_bmp EQ ( (1 << (p_enh->msg_count+1))-1) )
3017 {
3018 UBYTE i;
3019 /*all the instances are received, perform updations from temp --> current */
3020
3021 /* BA-BSIC mapping makes sense only if enhanced measurement reporting is enabled*/
3022 if ((p_enh->rep_type EQ ENHANCED_MEAS) OR (p_enh->grr_rep_type EQ ENHANCED_MEAS) )
3023 {
3024 for ( i= 0; i <= p_enh->msg_count; i++ )
3025 {
3026 if ( p_bl[i].is_valid EQ TRUE )
3027 for_perform_ba_bsic_mapping(&p_bl[i].bsic_info, &p_enh->enh_para);
3028 }
3029
3030 if ( ba_available EQ TRUE )
3031 {
3032 /*First we update the enhanced cell list in the temp and then store
3033 into current, if the updation is successful*/
3034 if ( for_update_enh_cell_list( rr_data->act_ncell_list) EQ TRUE)
3035 {
3036 rr_data->sc_data.emr_data_current = *p_enh;
3037 memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS);
3038 for_set_default_emr_data(p_enh);
3039 return TRUE;
3040 }
3041 else
3042 {
3043 /*Updation of enhanced cell list is unsuccesful, so flush temp
3044 and ignore the entire message */
3045 for_set_default_emr_data(p_enh);
3046 return FALSE;
3047 }
3048 }
3049 }
3050 else
3051 {
3052 /*If we recieved SI2q without Enhanced para, Update the CM value in the emr_current*/
3053 rr_data->sc_data.emr_data_current.mp_change_mark = p_enh->mp_change_mark;
3054 /*After cell reselection the first si2qtr received must be processed,
3055 for this is_data_valid flag should be reset */
3056 rr_data->sc_data.emr_data_current.is_data_valid = TRUE;
3057 for_set_default_emr_data(p_enh);
3058 }
3059 return TRUE;
3060 }
3061 return FALSE;
3062 }
3063
3064 GLOBAL void for_mon_si2quater_req(UBYTE action)
3065 {
3066 PALLOC(mph_mon_ctrl_req, MPH_MON_CTRL_REQ );
3067 TRACE_FUNCTION ("for_mon_si2quater_req");
3068 mph_mon_ctrl_req->action = action;
3069 mph_mon_ctrl_req->si_to_read = UPDATE_SI2QUATER;
3070 PSENDX (PL, mph_mon_ctrl_req);
3071 return;
3072 }
3073
3074 /*
3075 +------------------------------------------------------------------------------
3076 | Function : for_update_ba_ind
3077 +------------------------------------------------------------------------------
3078 | Description :
3079 |
3080 | Parameters : Input:
3081 |
3082 +------------------------------------------------------------------------------
3083 */
3084 GLOBAL void for_update_ba_ind (UBYTE index, UBYTE ba_ind)
3085 {
3086 GET_INSTANCE_DATA;
3087 if( index EQ SC_INDEX )
3088 {
3089 T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current;
3090 if ( rr_data->sc_data.ba_index NEQ ba_ind)
3091 {
3092 rr_data->sc_data.ba_index = ba_ind;
3093 /*Received SI-2 on serving cell: this indicates there is change in
3094 SI-2 ==> store an indication that SI-2quater also has to be configured.
3095 Once the BA list is received completely, then we will configure ALR for receiving
3096 SI-2quater*/
3097 if (rr_data->sc_data.cd.si2quater_status NEQ SI2QUATER_ABSENT)
3098 rr_data->sc_data.cd.si2quater_status = SI2QUATER_CONFIGURE;
3099 if ( p_cur->is_data_valid )
3100 {
3101 memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS);
3102 for_set_default_emr_data(p_cur);
3103 /*Indicate to GRR and ALR that current enhanced para are not valid*/
3104 for_send_enh_para(p_cur);
3105 }
3106 }
3107 }
3108 else
3109 rr_data->cr_data.ba_index = ba_ind;
3110 }
3111
3112 /*
3113 +------------------------------------------------------------------------------
3114 | Function : for_check_and_configure_si2quater
3115 +------------------------------------------------------------------------------
3116 | Description :
3117 |
3118 | Parameters : Input:
3119 |
3120 +------------------------------------------------------------------------------
3121 */
3122 GLOBAL void for_check_and_configure_si2quater (UBYTE index)
3123 {
3124 GET_INSTANCE_DATA;
3125 T_rr_enh_para *p_temp = &rr_data->sc_data.emr_data_temp;
3126 T_rr_enh_para *p_cur = &rr_data->sc_data.emr_data_current;
3127
3128 if ( index EQ SC_INDEX)
3129 {
3130 UBYTE si2_read = (SYS_INFO_2_READ | SYS_INFO_2BIS_READ |SYS_INFO_2TER_READ );
3131 rr_data->sc_data.ba_list_idle = FALSE; /*This makes sure that we wait till SI-2,2bis/2ter
3132 are received before configuring L1 for SI-2quater,
3133 when it is on E-BCCH.If it's on N-BCCH, SI-2quater
3134 will be stored in temp database, till BA(BCCH) is complete*/
3135
3136 if ( ((rr_data->sc_data.cd.sys_info_read ) & si2_read) EQ si2_read )
3137 {
3138 /*This indicates that all required SI-2 have been read*/
3139 rr_data->sc_data.ba_list_idle = TRUE;
3140 rr_data->sc_data.ba_list_ded = FALSE;
3141 /*configure SI-2quater if either configuration is pending or previously
3142 acquired and needs fresh acquisition due to change in SI-2/2bis*/
3143 if ( (rr_data->sc_data.cd.si2quater_status NEQ SI2QUATER_ABSENT ) AND
3144 (rr_data->sc_data.cd.si2quater_status NEQ SI2QUATER_ACQ_PENDING) )
3145 {
3146 if (p_cur->is_data_valid EQ TRUE)
3147 {
3148 memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS);
3149 for_set_default_emr_data(p_cur);
3150 /*Indicate to GRR and ALR that current enhanced para are not valid*/
3151 for_send_enh_para(p_cur);
3152 }
3153 /*configure ALR for acquiring SI-2quater if it is scheduled on E-BCCH.
3154 If it's on N-BCCH, it would have been acquired already or we might
3155 be in the process of acquiring*/
3156 if ( rr_data->sc_data.cd.si2quater_pos EQ SI2QUATER_ON_EBCCH )
3157 {
3158 for_mon_si2quater_req(START_MON_EBCCH);
3159 rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_PENDING;
3160 }
3161 else
3162 {
3163 if((rr_data->sc_data.cd.sys_info_read & SYS_INFO_2QUATER_READ) NEQ SYS_INFO_2QUATER_READ) /* SI 2qtr not yet read */
3164 {
3165 rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_PENDING;
3166 if((rr_data->sc_data.cd.sys_info_read & ALL_SYS_INFO_READ) EQ ALL_SYS_INFO_READ)
3167 {
3168 /*All other sys info has been read*/
3169 for_mon_si2quater_req(START_MON_NBCCH);
3170 }
3171 /*else
3172 {
3173 There are other SI that have not been read yet on Normal BCCH, just continue to read normal BCCH
3174 }
3175 */
3176
3177 }/*if*/
3178 }
3179 }
3180 }
3181 }
3182
3183 if ( rr_data->sc_data.enh_para_status EQ ENH_PARA_DEDICATED)
3184 {
3185 /*The enhanced parameters are from previous state: reset them */
3186 memset (rr_data->sc_data.rep_count, NOT_PRESENT_8BIT, MAX_NEIGHBOURCELLS);
3187 for_set_default_emr_data(p_cur);
3188 for_set_default_emr_data(p_temp);
3189 for_send_enh_para(p_cur);
3190 rr_data->sc_data.enh_para_status = ENH_PARA_INVALID_STATE;
3191 }
3192 /*When BA(BCCH) is ready, check whether there are enhanced parameters in
3193 temp that needs attention*/
3194 if ( (rr_data->sc_data.ba_list_idle EQ TRUE ) AND
3195 ( rr_data->sc_data.enh_para_status EQ ENH_PARA_IDLE) AND
3196 (p_temp->is_data_valid EQ TRUE))
3197 {
3198 /* This means enhanced parameters were received before BA list - so
3199 update the enhanced list with actual ARFCN and update current EMR data*/
3200 if ( for_update_enh_cell_list( rr_data->act_ncell_list) EQ TRUE)
3201 {
3202 *p_cur = *p_temp;
3203 for_send_enh_para(p_temp);
3204 }
3205 /*Reset temporary, irrespective of whether updation is succesful or not*/
3206 for_set_default_emr_data(p_temp);
3207 if ((rr_data->sc_data.cd.si2quater_status EQ SI2QUATER_ACQ_PENDING) OR
3208 (rr_data->sc_data.cd.si2quater_status EQ SI2QUATER_ACQ_WRONG_BAIND))
3209 {
3210 for_mon_si2quater_req(STOP_MON_BCCH);
3211 rr_data->sc_data.cd.si2quater_status = SI2QUATER_ACQ_COMP;
3212 }
3213 }
3214
3215 return;
3216 }
3217 #endif
3218
3219 #if defined (TI_PS_FF_RTD) AND defined (REL99)
3220 /*
3221 +------------------------------------------------------------------------------
3222 | Function : for_store_rtd_data
3223 +------------------------------------------------------------------------------
3224 | Description : This function stores the rtd parameters received in si2quarter.
3225 | Parameters : RTD information/data,target enh para struct where we store RTD para
3226 +------------------------------------------------------------------------------
3227 */
3228 GLOBAL void for_store_rtd_data(T_si_2qua_octets *p_si2q,T_rr_enh_para *p_temp)
3229 {
3230 T_rtdd *rtdd_struct= &p_si2q->rtdd;
3231 dat_update_common_rtd_struct(rtdd_struct,p_temp);
3232 } /* end for_store_rtd_data() */
3233 #endif /* #if defined (TI_PS_FF_RTD) AND defined (REL99) */
3234
3235 #endif