comparison src/g23m-gsm/rr/rr_forf.c @ 1:d393cd9bb723

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