comparison src/g23m-gprs/grr/grr_pgf.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 : GPRS (8441)
4 | Modul : GRR
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 : This module implements local functions for service PG of
18 | entity GRR.
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef GRR_PGF_C
23 #define GRR_PGF_C
24 #endif
25
26 #define ENTITY_GRR
27
28 /*==== INCLUDES =============================================================*/
29
30 #include "typedefs.h" /* to get Condat data types */
31
32 #include "vsi.h" /* to get a lot of macros */
33 #include "macdef.h"
34 #include "gprs.h"
35 #include "gsm.h" /* to get a lot of macros */
36 #include "ccdapi.h" /* to get CCD API */
37 #include "cnf_grr.h" /* to get cnf-definitions */
38 #include "mon_grr.h" /* to get mon-definitions */
39 #include "prim.h" /* to get the definitions of used SAP and directions */
40 #include "message.h"
41 #include "grr.h" /* to get the global entity definitions */
42
43 #include "grr_f.h" /* */
44 #include "grr_pgf.h" /* */
45
46 #include "grr_ctrls.h" /* */
47 #include "grr_meass.h"
48 #include "grr_css.h"
49 #include "grr_em.h" /*for Engineering mode*/
50
51 #include <string.h> /* for memcpy*/
52 #include <stdio.h> /* for memcpy*/
53
54 /*==== CONST ================================================================*/
55
56 const USHORT NC2_NON_DRX_TABLE[8] = {0, 240, 480, 720, 960, 1200, 1440, 1920};
57
58 /*==== LOCAL VARS ===========================================================*/
59 static UBYTE NON_DRX_TABLE[] = {0, 1, 2, 4, 8, 16, 32, 64};
60
61 /*==== GLOBAL VARS ===========================================================*/
62
63
64
65 /*==== PRIVATE FUNCTIONS ====================================================*/
66 LOCAL void pg_stop_t_nc2_ndrx( void );
67 LOCAL void pg_stop_non_drx_timer( void );
68 LOCAL void pg_start_non_drx_timer(USHORT milliseconds);
69 LOCAL BOOL pg_decode_imsi(T_ms_id ms_id, UBYTE *digits, UBYTE *nr_digits);
70 /*==== PUBLIC FUNCTIONS =====================================================*/
71
72
73
74 /*
75 +------------------------------------------------------------------------------
76 | Function : pg_init
77 +------------------------------------------------------------------------------
78 | Description : The function pg_init() ....
79 |
80 | Parameters : void
81 |
82 +------------------------------------------------------------------------------
83 */
84 GLOBAL void pg_init ( void )
85 {
86 TRACE_FUNCTION( "pg_init" );
87
88 pg_init_params();
89
90 grr_data->pg.v_emlpp_prio = FALSE; /* valid flag for emlpp_priority*/
91 grr_data->pg.packet_mode = PACKET_MODE_NULL;
92
93 INIT_STATE(PG,PG_NULL);
94 } /* pg_init() */
95
96 /*
97 +------------------------------------------------------------------------------
98 | Function : pg_init_params
99 +------------------------------------------------------------------------------
100 | Description : The function pg_init_params() ....
101 |
102 | Parameters : void
103 |
104 +------------------------------------------------------------------------------
105 */
106 GLOBAL void pg_init_params ( void )
107 {
108 TRACE_FUNCTION( "pg_init_params" );
109
110 psc_db->last_pg_mode = psc_db->network_pg_mode = REORG_PAGING;
111
112 } /* pg_init_params() */
113
114 /*
115 +------------------------------------------------------------------------------
116 | Function : pg_process_pp_req
117 +------------------------------------------------------------------------------
118 | Description : The function pg_process_pp_req() ....
119 |
120 | Parameters : T_D_PAGING_REQ *paging_req: pointer to the decoded message,
121 UBYTE state: state of pg state machine: IDLE, TRANSFER, TIMER_3172
122 |
123 +------------------------------------------------------------------------------
124 */
125 GLOBAL void pg_process_pp_req ( T_D_PAGING_REQ *paging_req, UBYTE state )
126 {
127 char i;
128 ULONG ul;
129
130 TRACE_FUNCTION( "pg_process_pp_req" );
131
132 if(paging_req->v_pers_lev)
133 { /*copy persistence level parameters into database*/
134 grr_save_persistence_level (&(paging_req->pers_lev));
135 }
136 /*if(paging_req->v_nln)
137 { message contains at least one page request for RR connection establishment
138 04.08: NLN(PCH) Notification List Number
139 "The presence of the NLN(PCH) field indicates that if an NCH is present, reduced NCH monitoring can be used, and
140 gives the NLN(PCH) value, to be used as specified in 3.3.3."
141 This is used by VGCS MSs...
142
143 }*/
144 if(paging_req->rep_page_info_trnc_grp.v_rep_page_info)
145 {
146 for (i=0; i < paging_req->rep_page_info_trnc_grp.c_rep_page_info; i++)
147 {
148 if(paging_req->rep_page_info_trnc_grp.rep_page_info[i].v_rep_page_s1
149 AND
150 grr_t_status( T3172_1 ) EQ 0 /* T3172 is not running*/
151 )
152 {
153 /*
154 * page request for TBF establishment
155 */
156 switch(state)
157 {
158 case PG_IDLE:
159 if(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s1.v_ptmsi)
160 {
161 /*
162 *Paging with PTMSI
163 */
164 if(grr_data->db.ms_id.new_ptmsi NEQ GMMRR_TMSI_INVALID)
165 {
166 if(grr_check_ptmsi(&(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s1.ptmsi)))
167 {
168 TRACE_EVENT("Paging with PTIMSI for TBF");
169 sig_pg_ctrl_downlink_transfer ( GMMRR_PTMSI );
170 i = paging_req->rep_page_info_trnc_grp.c_rep_page_info; /* break condition for for loop*/
171 }
172 else
173 {
174 TRACE_EVENT("Paging with wrong PTIMSI for TBF: IGNORE");
175 }
176 }
177 else
178 {
179 TRACE_EVENT("Paging with PTMSI, but no valid PTMSI in MS");
180 }
181 }
182 else
183 {
184 /*
185 *Paging with Mobile Identity (IMSI)
186 */
187 UBYTE dummy_digits[MAX_IMSI_DIGITS];
188 UBYTE dummy_nr_digits = 0;
189
190 if(pg_decode_imsi(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s1.ms_id,
191 dummy_digits, &dummy_nr_digits))
192 {
193
194 if( dummy_nr_digits
195 EQ
196 grr_data->db.ms_id.imsi.number_of_digits)/* check the number of digits*/
197 {
198 if( !memcmp
199 ( grr_data->db.ms_id.imsi.digit, /* IMSI stored in the data_base*/
200 dummy_digits, /* received IMSI*/
201 grr_data->db.ms_id.imsi.number_of_digits
202 )
203 )
204 {
205 /* The MS was paged with the IMSI*/
206 TRACE_EVENT("Paging with Mobile Identity (IMSI) for TBF");
207 sig_pg_ctrl_downlink_transfer ( GMMRR_IMSI );
208 i = paging_req->rep_page_info_trnc_grp.c_rep_page_info; /* break condition for for loop*/
209 }
210 else
211 {
212 TRACE_EVENT("Paging with wrong IMSI for TBF: IGNORE");
213 }
214
215 }
216 }
217 }
218 break;
219 default:
220 /*
221 * ignore paging request for TBF establishment, do
222 * not check the content
223 */
224 break;
225 }
226 }
227
228 if(paging_req->rep_page_info_trnc_grp.rep_page_info[i].v_rep_page_s2)
229 {
230 /*
231 * page request for RR connection establishment
232 */
233 /*
234 * In packet access mode, class A or B shall respond to a pp_req for
235 * RR connection est.
236 * During the time T3172 is running, the mobile station shall ignore all
237 * received PACKET PAGING REQUEST messages except paging request to trigger
238 * RR connection establishment.
239 */
240 switch(state)
241 {
242 case PG_IDLE:
243 case PG_TRANSFER:
244 case PG_ACCESS:
245 if(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.v_tmsi_field)
246 {
247 /*
248 *Paging with TMSI
249 */
250 if(grr_data->db.ms_id.tmsi NEQ GMMRR_TMSI_INVALID)
251 {
252 ul = grr_buffer2ulong((BUF_ptmsi *)&(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.tmsi_field));
253 if(ul EQ grr_data->db.ms_id.tmsi)
254 {
255 TRACE_EVENT("Paging with Mobile Identity (TMSI) for RR est");
256
257 /* Set some parameters needed RR connection establishment*/
258 grr_data->pg.ch_needed = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.chan_need;
259 grr_data->pg.v_emlpp_prio = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.v_emlpp_prio;
260 grr_data->pg.emlpp_prio = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.emlpp_prio;
261
262 /* MS was paged with TMSI for RR connection establishment*/
263 grr_data->pg.type = ID_TMSI;
264 sig_pg_ctrl_rr_est_req ( PG_ON_PCCCH);
265 i = paging_req->rep_page_info_trnc_grp.c_rep_page_info; /* break condition for for loop*/
266 }
267 else
268 {
269 TRACE_EVENT("Paging with wrong TMSI for RR: IGNORE");
270 }
271 }
272 else
273 {
274 TRACE_EVENT("Paging with TMSI, but no valid TMSI in MS");
275 }
276 }
277 else
278 {
279 /*
280 *Paging with Mobile Identity (IMSI)
281 */
282 UBYTE dummy_digits[MAX_IMSI_DIGITS];
283 UBYTE dummy_nr_digits = 0;
284
285 if(pg_decode_imsi(paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.ms_id,
286 dummy_digits, &dummy_nr_digits))
287 {
288
289 if( dummy_nr_digits
290 EQ
291 grr_data->db.ms_id.imsi.number_of_digits)/* check the number of digits*/
292 {
293 if( !memcmp
294 ( grr_data->db.ms_id.imsi.digit, /* IMSI stored in the data_base*/
295 dummy_digits, /* received IMSI*/
296 grr_data->db.ms_id.imsi.number_of_digits
297 )
298 )
299 {
300 /* The MS was paged with the IMSI*/
301 TRACE_EVENT("Paging with Mobile Identity (IMSI) for RR est");
302
303 /* Set some parameters needed RR connection establishment*/
304 grr_data->pg.ch_needed = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.chan_need;
305 grr_data->pg.v_emlpp_prio = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.v_emlpp_prio;
306 grr_data->pg.emlpp_prio = paging_req->rep_page_info_trnc_grp.rep_page_info[i].rep_page_s2.emlpp_prio;
307
308 /* MS was paged with IMSI for RR connection establishment*/
309 grr_data->pg.type = ID_IMSI;
310 sig_pg_ctrl_rr_est_req ( PG_ON_PCCCH );
311 i = paging_req->rep_page_info_trnc_grp.c_rep_page_info; /* break condition for for loop*/
312 }
313 else
314 {
315 TRACE_EVENT("Paging with wrong IMSI for RR: IGNORE");
316 }
317 }
318 }
319 }
320 break;
321 default:
322 /*
323 * ignore paging request for RR connection establishment, do
324 * not check the content
325 */
326 break;
327 }
328 }
329 }
330 }
331 } /* pg_process_pp_req() */
332
333
334
335 /*
336 +------------------------------------------------------------------------------
337 | Function : pg_send_stop
338 +------------------------------------------------------------------------------
339 | Description : The function pg_send_stop() ....
340 |
341 | Parameters : void
342 |
343 +------------------------------------------------------------------------------
344 */
345 GLOBAL void pg_send_stop ( void )
346 {
347 TRACE_FUNCTION( "pg_send_stop" );
348
349 if (grr_data->is_pg_started EQ TRUE)
350 {
351 PALLOC (mphp_stop_pccch_req, MPHP_STOP_PCCCH_REQ);
352 PSEND (hCommL1, mphp_stop_pccch_req);
353 }
354 grr_data->is_pg_started = FALSE;
355
356 pg_stop_non_drx_timer();
357 pg_stop_t_nc2_ndrx();
358
359 } /* pg_send_stop() */
360
361
362
363 /*
364 +------------------------------------------------------------------------------
365 | Function : pg_send_start
366 +------------------------------------------------------------------------------
367 | Description : The function pg_send_start() ....
368 |
369 | Parameters : UBYTE page_mode
370 |
371 +------------------------------------------------------------------------------
372 */
373 GLOBAL void pg_send_start ( UBYTE page_mode )
374 {
375 UBYTE pccch_group; /* 0 .. KC-1*/
376 USHORT dummy;
377
378 TRACE_FUNCTION( "pg_send_start" );
379
380 if(grr_is_non_drx_period())
381 page_mode = REORG_PAGING;
382
383 switch(page_mode)
384 {
385 case NORMAL_PAGING:
386 case EXT_PAGING:
387 case REORG_PAGING:
388 case SAME_PAGING:
389 break;/*O.K.*/
390 default:
391 /* same as before: nothing to do return*/
392 TRACE_EVENT("page_mode is corrupt: assume same as before: return");
393 return;
394 }
395
396 if(psc_db->paging_group.kc EQ 0)
397 {
398 /*
399 * No PCCCH description: return
400 */
401 TRACE_ERROR("psc_db->paging_group.kc EQ 0");
402 return;
403 }
404
405 {
406 PALLOC( start_pccch, MPHP_START_PCCCH_REQ );
407
408 start_pccch->imsi_mod = grr_imsi_mod( );
409 pccch_group = ( UBYTE )( start_pccch->imsi_mod % psc_db->paging_group.kc );
410
411 if( !grr_get_pccch_freq_par( pccch_group,
412 &start_pccch->p_ch_des.p_chan_sel,
413 &start_pccch->p_freq_list ) )
414 {
415 PFREE( start_pccch );
416
417 return;
418 }
419
420 start_pccch->kcn = psc_db->paging_group.kc; /*< KC multiplied by N */
421 start_pccch->split_pg_cycle = grr_data->ms.split_pg_cycle; /*< Split paging cycle */
422 start_pccch->bs_pag_blks_res = psc_db->pccch.bs_pag_blks; /*< No paging no PBCCH */
423 start_pccch->bs_pbcch_blks = psc_db->pccch.bs_pbcch_blks; /*< Number of PBCCH per multiframe */
424 start_pccch->pb = psc_db->g_pwr_par.pb; /*< Power reduction value */
425 start_pccch->p_ch_des.tsc = psc_db->paging_group.pccch[pccch_group].tsc; /*< Training sequence code */
426 start_pccch->p_ch_des.tn = psc_db->paging_group.pccch[pccch_group].tn;
427
428 if( start_pccch->p_ch_des.p_chan_sel.hopping )
429 {
430 TRACE_EVENT_P8( "Hopping PCCCH - ma_num:%d hsn/maio:%ld tsc:%d tn:%d f1:%d f2:%d f3:%d f4:%d",
431 psc_db->paging_group.pccch[pccch_group].ma_num,
432 start_pccch->p_ch_des.p_chan_sel.p_rf_ch.arfcn,
433 start_pccch->p_ch_des.tsc,
434 start_pccch->p_ch_des.tn,
435 start_pccch->p_freq_list.p_rf_chan_no.p_radio_freq[0],
436 start_pccch->p_freq_list.p_rf_chan_no.p_radio_freq[1],
437 start_pccch->p_freq_list.p_rf_chan_no.p_radio_freq[2],
438 start_pccch->p_freq_list.p_rf_chan_no.p_radio_freq[3] );
439 }
440 else
441 {
442 TRACE_EVENT_P3( "Static PCCCH - arfcn:%ld tsc:%d tn:%d",
443 start_pccch->p_ch_des.p_chan_sel.p_rf_ch.arfcn,
444 start_pccch->p_ch_des.tsc,
445 start_pccch->p_ch_des.tn );
446
447 start_pccch->p_ch_des.p_chan_sel.p_rf_ch.arfcn =
448 grr_g23_arfcn_to_l1( start_pccch->p_ch_des.p_chan_sel.p_rf_ch.arfcn );
449 }
450
451 /*
452 * Calculate downlink signalling counter
453 */
454 /* DRX period is used, there is a valid SPILT_PG_CYCLE value */
455 dummy = grr_data->ms.split_pg_cycle;
456
457
458 /* Downlink signalling counter*/
459 dummy = ( ( 90 * dummy ) / 64 < 10 ) ? 10 : ( 90 * dummy ) / 64;
460
461 if(!grr_data->is_pg_started)
462 {
463 grr_data->pg.initial_dsc = dummy;
464 grr_data->pg.dsc = dummy;
465
466 GRR_EM_SET_DSC_VAL(dummy);
467
468 }
469 if( grr_data->pg.is_l1_ref_tn_changed NEQ psc_db->paging_group.pccch[pccch_group].tn )
470 {
471 sig_pg_cs_pause( );
472 }
473
474 /*Read PCCCH */
475 {
476 start_pccch->page_mode = page_mode;
477 PSEND(hCommL1, start_pccch);
478 }
479 if( grr_data->pg.is_l1_ref_tn_changed NEQ psc_db->paging_group.pccch[pccch_group].tn )
480 {
481 sig_pg_cs_resume( );
482
483 grr_data->pg.is_l1_ref_tn_changed = psc_db->paging_group.pccch[pccch_group].tn;
484 }
485
486 psc_db->last_pg_mode = page_mode;
487
488 switch(page_mode)
489 {
490 case NORMAL_PAGING:
491 TRACE_EVENT("page mode NORMAL");
492 break;/*O.K.*/
493 case EXT_PAGING:
494 TRACE_EVENT("page mode EXT");
495 break;/*O.K.*/
496 case REORG_PAGING:
497 TRACE_EVENT("page mode REORG");
498 break;/*O.K.*/
499 case SAME_PAGING:
500 TRACE_EVENT("page mode SAME");
501 break;/*O.K.*/
502 }
503
504 }
505 grr_data->is_pg_started = TRUE;
506
507 } /* pg_send_start() */
508
509 /*
510 +------------------------------------------------------------------------------
511 | Function : pg_start_non_drx_timer
512 +------------------------------------------------------------------------------
513 | Description : The function pg_start_non_drx_timer() starts the timer for
514 | non DRX period
515 |
516 | Parameters : USHORT milliseconds
517 |
518 +------------------------------------------------------------------------------
519 */
520 LOCAL void pg_start_non_drx_timer(USHORT milliseconds)
521 {
522 TRACE_FUNCTION( "pg_start_non_drx_timer");
523
524 psc_db->non_drx_timer_running = TRUE;
525 vsi_t_start(GRR_handle,T_TRANS_NON_DRX, milliseconds);
526 }/* pg_start_non_drx_timer*/
527
528 /*
529 +------------------------------------------------------------------------------
530 | Function : pg_stop_non_drx_timer
531 +------------------------------------------------------------------------------
532 | Description : The function pg_stop_non_drx_timer() stops the timer for
533 | non DRX period
534 |
535 | Parameters : void
536 |
537 +------------------------------------------------------------------------------
538 */
539 GLOBAL void pg_stop_non_drx_timer(void)
540 {
541 TRACE_FUNCTION( "pg_stop_non_drx_timer");
542
543 if(psc_db->non_drx_timer_running)
544 {
545 psc_db->non_drx_timer_running = FALSE;
546 vsi_t_stop(GRR_handle,T_TRANS_NON_DRX);
547 }
548 }/* pg_stop_non_drx_timer*/
549
550 /*
551 +------------------------------------------------------------------------------
552 | Function : pg_start_t_nc2_ndrx
553 +------------------------------------------------------------------------------
554 | Description : ...
555 |
556 | Parameters : void
557 |
558 +------------------------------------------------------------------------------
559 */
560 GLOBAL void pg_start_t_nc2_ndrx( UBYTE nc_non_drx_period )
561 {
562 TRACE_FUNCTION( "pg_start_t_nc2_ndrx");
563
564 if( nc_non_drx_period NEQ 0 )
565 {
566 USHORT nc2_drx_period = NC2_NON_DRX_TABLE[nc_non_drx_period];
567
568 psc_db->nc2_non_drx_period_running = TRUE;
569
570 vsi_t_start( GRR_handle, T_NC2_NON_DRX, nc2_drx_period );
571
572 TRACE_EVENT_P1( "Timer T_NC2_NON_DRX started: %d", nc2_drx_period );
573 }
574 }/* pg_start_t_nc2_ndrx */
575
576 /*
577 +------------------------------------------------------------------------------
578 | Function : pg_stop_t_nc2_ndrx
579 +------------------------------------------------------------------------------
580 | Description : ...
581 |
582 | Parameters : void
583 |
584 +------------------------------------------------------------------------------
585 */
586 GLOBAL void pg_stop_t_nc2_ndrx( void )
587 {
588 TRACE_FUNCTION( "pg_stop_t_nc2_ndrx" );
589
590 if( psc_db->nc2_non_drx_period_running EQ TRUE )
591 {
592 psc_db->nc2_non_drx_period_running = FALSE;
593
594 vsi_t_stop( GRR_handle, T_NC2_NON_DRX );
595
596 TRACE_EVENT( "Timer T_NC2_NON_DRX stopped" );
597 }
598 } /* pg_stop_t_nc2_ndrx */
599
600 /*
601 +------------------------------------------------------------------------------
602 | Function : pg_handle_non_drx_timers
603 +------------------------------------------------------------------------------
604 | Description : ...
605 |
606 | Parameters : void
607 |
608 +------------------------------------------------------------------------------
609 */
610 GLOBAL void pg_handle_non_drx_timers(void)
611 {
612 USHORT non_drx_timer = 0;
613 TRACE_FUNCTION("pg_handle_non_drx_timers");
614
615 non_drx_timer = ( psc_db->non_drx_timer < psc_db->gprs_cell_opt.drx_t_max ) ?
616 psc_db->non_drx_timer : psc_db->gprs_cell_opt.drx_t_max;
617
618 non_drx_timer = (USHORT)(NON_DRX_TABLE[non_drx_timer]*1000);/* in milliseconds*/
619
620 pg_start_non_drx_timer(non_drx_timer);
621
622 }/* pg_handle_non_drx_timers */
623
624 /*
625 +------------------------------------------------------------------------------
626 | Function : pg_non_drx
627 +------------------------------------------------------------------------------
628 | Description : Handles the timer of non DRX mode
629 |
630 | Parameters : void
631 |
632 +------------------------------------------------------------------------------
633 */
634 GLOBAL void pg_non_drx ( void )
635 {
636 TRACE_FUNCTION( "pg_non_drx" );
637
638 switch( GET_STATE( PG ) )
639 {
640 case PG_IDLE:
641 /*
642 * To ensure that the paging mode is not set to page normal in other states
643 * than packet idle mode, the function grr_is_packet_idle_mode is called in
644 * advance.
645 *
646 * State PG_IDLE not necessarily means that GRR is in packet idle mode. In
647 * case GRR is currently executing the RRGRR_STOP_TASK_REQ/CNF procedure,
648 * just the services CPAP and TC changes their states. All other services
649 * remain in state IDLE, which is not quite correct. A similar scenario
650 * occurs during execution of the MPHP_ASSIGNMENT_REQ/CON procedure.
651 */
652 if( grr_is_packet_idle_mode( ) EQ TRUE )
653 {
654 pg_handle_idle_mode( PTM_IDLE );
655 }
656 else
657 {
658 TRACE_EVENT( "pg_non_drx: Timeout T_TRANS_NON_DRX handled by next packet idle mode" );
659 }
660 break;
661 default:
662 TRACE_EVENT( "pg_non_drx: Timeout T_TRANS_NON_DRX handled by next PG_IDLE" );
663 break;
664 }
665 }/* pg_non_drx*/
666
667 /*
668 +------------------------------------------------------------------------------
669 | Function : pg_decode_imsi
670 +------------------------------------------------------------------------------
671 | Description : Handles the timer of non DRX mode
672 |
673 | Parameters : void
674 |
675 +------------------------------------------------------------------------------
676 */
677 LOCAL BOOL pg_decode_imsi(T_ms_id ms_id, UBYTE *digits, UBYTE *nr_digits)
678 {
679 UBYTE odd_even_type, i;
680 BOOL is_odd;
681 TRACE_FUNCTION("pg_decode_imsi");
682
683 *nr_digits = 0;
684 if(ms_id.ms_id_len > 0)
685 {
686 odd_even_type = (ms_id.ident_digit[0] & 0x0f);
687
688 if(odd_even_type & 1) /* Check IMSI or not*/
689 {
690 is_odd = odd_even_type & 0x08; /* odd: ung.*/
691 digits[0] = (ms_id.ident_digit[0] >> 4);
692 *nr_digits = 1;
693
694 for(i=1; i< ms_id.ms_id_len; i++)
695 {
696 if(!is_odd AND (i EQ (ms_id.ms_id_len-1)))
697 {
698 digits[*nr_digits] = (ms_id.ident_digit[i] & 0x0f);
699 *nr_digits = (*nr_digits) + 1;
700 }
701 else
702 {
703 digits[*nr_digits] = (ms_id.ident_digit[i] & 0x0f);
704 *nr_digits = (*nr_digits) + 1;
705 digits[*nr_digits] = (ms_id.ident_digit[i] >> 4);
706 *nr_digits = (*nr_digits) + 1;
707 }
708 }
709 }
710 else
711 {
712 /*No IMSI, ignore*/
713 return FALSE;
714 }
715 }
716 else
717 {
718 /* No mobile identity: strange*/
719 return FALSE;
720 }
721 return TRUE;
722 }/* pg_decode_imsi*/
723
724 /*
725 +------------------------------------------------------------------------------
726 | Function : pg_handle_classB_NMO_III
727 +------------------------------------------------------------------------------
728 | Description : Handles NMO III for Class B mobile
729 |
730 | Parameters : void
731 |
732 +------------------------------------------------------------------------------
733 */
734 GLOBAL void pg_handle_classB_NMO_III(T_PG_TRANS transition)
735 {
736 TRACE_FUNCTION("pg_handle_classB_NMO_III");
737
738 switch(transition)
739 {
740 case T3172_PTM:
741 case ACCESS_PTM:
742 case IDLE_PTM:
743 if(grr_data->ms.reverts_NMO_III)
744 {
745 /*
746 * The MS reverts to CC or CG in NMO III
747 * In this state IDLE->TRANSFER it can be only a CG mobile
748 * it shall stop PCCCH reading, if available
749 * it shall stop also CCCH reading, if running
750 */
751 TRACE_EVENT("IDLE/ACCESS->PTM: NMO III Class B reverts. Stop CCCH (and PCCCH)");
752 if(grr_is_pbcch_present())
753 {
754 /*
755 * Stop monitoring PCCCH
756 */
757 pg_send_stop();
758 }
759 /*
760 * Stop monitoring CCCH
761 */
762 sig_pg_ctrl_stop_mon_ccch();
763 }
764 else
765 {
766 /*
767 * This is non reverting Class B
768 * If PBCCH is present it should stop PCCCH and start CCCH
769 * else it should only monitor CCCH
770 */
771 TRACE_EVENT("IDLE/ACCESS->PTM: NMO III Class B. Start CCCH (and stop PCCCH)");
772 if(grr_is_pbcch_present())
773 {
774 /*
775 * Stop monitoring PCCCH
776 */
777 pg_send_stop();
778 }
779 /*
780 * Start monitoring CCCH (Normal Paging)
781 */
782 if( grr_data->ms.tbf_mon_ccch
783 #ifdef REL99
784 AND
785 !psc_db->gprs_cell_opt.gprs_ext_bits.gprs_ext_info.bss_paging_coord
786 #endif
787 )
788 {
789 sig_pg_ctrl_start_mon_ccch(PAG_MODE_PTM_NP);
790 }
791 }
792 break;
793 case NULL_IDLE:
794 case PTM_IDLE:
795 if(grr_data->ms.reverts_NMO_III)
796 {
797 /*
798 * The MS reverts to CC or CG in NMO III
799 * In this state TRANSFER/NULL->IDLE it can be only a CG mobile
800 * it shall start PCCCH reading, if available
801 * it shall start also CCCH reading, if NO PBCCH
802 */
803 TRACE_EVENT("PTM/NULL->IDLE: NMO III Class B reverts. Start (P) or CCCH");
804 if(grr_is_pbcch_present())
805 {
806 /*
807 * Start monitoring PCCCH
808 */
809 pg_send_start( psc_db->last_pg_mode );
810
811 }
812 else
813 {
814 /*
815 * Start monitoring CCCH (Normal Paging)
816 */
817 sig_pg_ctrl_start_mon_ccch(PAG_MODE_DEFAULT);
818 }
819 }
820 else
821 {
822 /*
823 * This is non reverting Class B
824 * If PBCCH is present it should start PCCCH and start CCCH
825 * else it should only monitor CCCH
826 */
827 TRACE_EVENT("PTM/NULL->IDLE: NMO III Class B. Start (P) and CCCH");
828 if(grr_is_pbcch_present())
829 {
830 /*
831 * Start monitoring PCCCH
832 */
833 pg_send_start( psc_db->last_pg_mode );
834 /*
835 * Start monitoring CCCH (Normal Paging), before doing this use PAG_MODE_PIM_NP
836 * to enter later to idle mode
837 * Exceptional situation: if NON DRX is used, REORG is only for PCCCH
838 */
839 sig_pg_ctrl_start_mon_ccch(PAG_MODE_PIM_NP);
840 }
841 else
842 {
843 /*
844 * Start monitoring CCCH (Normal Paging)
845 * Normal Paging
846 */
847 sig_pg_ctrl_start_mon_ccch(PAG_MODE_DEFAULT);
848 }
849 }
850 break;
851 case ACCESS_IDLE:
852 if(grr_data->ms.reverts_NMO_III)
853 {
854 /*
855 * The MS reverts to CC or CG in NMO III
856 * In this state ACCESS->IDLE it can be only a CG mobile
857 * it shall start PCCCH reading, if available
858 * it shall start CCCH reading, if NO PBCCH
859 */
860 TRACE_EVENT("ACCESS->IDLE: NMO III Class B reverts. Start (P) or CCCH");
861 if(!grr_is_pbcch_present())
862 {
863 /*
864 * Start monitoring CCCH (Normal Paging)
865 */
866 sig_pg_ctrl_start_mon_ccch(PAG_MODE_DEFAULT);
867 }
868 }
869 else
870 {
871 /*
872 * This is non reverting Class B
873 * If PBCCH is present it should start PCCCH and start CCCH
874 * else it should only monitor CCCH
875 */
876 TRACE_EVENT("ACCESS->IDLE: NMO III Class B. Start (P) and CCCH");
877 if(grr_is_pbcch_present())
878 {
879 /*
880 * Start monitoring PCCCH
881 */
882 pg_send_start( psc_db->last_pg_mode );
883 /*
884 * Start monitoring CCCH (Normal Paging)
885 * Exceptional situation: if NON DRX is used, we RORG is only for PCCCH
886 */
887 if(grr_data->ms.tbf_mon_ccch
888 #ifdef REL99
889 AND
890 !psc_db->gprs_cell_opt.gprs_ext_bits.gprs_ext_info.bss_paging_coord
891 #endif
892 )
893 {
894 sig_pg_ctrl_start_mon_ccch(PAG_MODE_PTM_NP);
895 }
896 }
897 else
898 {
899 /*
900 * Start monitoring CCCH (Normal Paging)
901 * Normal Paging
902 */
903 sig_pg_ctrl_start_mon_ccch(PAG_MODE_DEFAULT);
904 }
905 }
906 break;
907 case PTM_ACCESS:
908 case IDLE_ACCESS:
909 /*
910 * Not necessary
911 */
912 break;
913 }/*switch*/
914 }
915
916 /*
917 +------------------------------------------------------------------------------
918 | Function : pg_handle_access_mode
919 +------------------------------------------------------------------------------
920 | Description : Handles the paging when entering the packet access mode.
921 |
922 | Parameters : void
923 |
924 +------------------------------------------------------------------------------
925 */
926 GLOBAL void pg_handle_access_mode ( void )
927 {
928 TRACE_FUNCTION( "pg_handle_access_mode" );
929
930
931 if( grr_is_pbcch_present( ) )
932 {
933 if( !grr_data->is_pg_started OR psc_db->last_pg_mode NEQ REORG_PAGING )
934 {
935 /*
936 * enable the L1 reading USF values
937 */
938 pg_send_start( PG_REORG );
939 }
940 }
941 else
942 {
943 /*
944 * start monitoring CCCH
945 */
946 sig_pg_ctrl_start_mon_ccch( PAG_MODE_REORG );
947 }
948 } /* pg_handle_access_mode() */
949
950 /*
951 +------------------------------------------------------------------------------
952 | Function : pg_set_l1_ref_tn
953 +------------------------------------------------------------------------------
954 | Description : The function pg_set_l1_ref_tn () ....
955 |
956 | Parameters :
957 |
958 +------------------------------------------------------------------------------
959 */
960 GLOBAL void pg_set_l1_ref_tn ( UBYTE* out_tn, UBYTE in_tn )
961 {
962 TRACE_FUNCTION( "pg_set_l1_ref_tn" );
963
964 if( in_tn NEQ *out_tn )
965 {
966 grr_data->pg.is_l1_ref_tn_changed = TRUE;
967 }
968
969 *out_tn = in_tn;
970
971 } /* pg_set_l1_ref_tn */
972
973 /*
974 +------------------------------------------------------------------------------
975 | Function : pg_handle_idle_mode
976 +------------------------------------------------------------------------------
977 | Description :
978 |
979 | Parameters :
980 |
981 +------------------------------------------------------------------------------
982 */
983 GLOBAL void pg_handle_idle_mode ( T_PG_TRANS transition )
984 {
985 TRACE_FUNCTION( "pg_handle_idle_mode" );
986
987 switch( grr_data->pg.nmo )
988 {
989 case GMMRR_NET_MODE_I:
990 /*
991 * NMOI:
992 * ====
993 * Paging on ( CCCH or PCCCH ) and PACCH, GPRS attached MS should
994 * monitor one paging channel, so we have to stop monitoring CCCH
995 * channel if PCCCH is present.
996 */
997 if( grr_is_pbcch_present( ) )
998 {
999 pg_send_start( psc_db->last_pg_mode );
1000 }
1001 else
1002 {
1003 sig_pg_ctrl_start_mon_ccch( PAG_MODE_DEFAULT );
1004 }
1005 break;
1006
1007 case GMMRR_NET_MODE_II:
1008 /*
1009 * NMOII:
1010 * =====
1011 * Paging on CCCH, paging for both circuit switched and packet data
1012 * will be sent on CCCH, PCCCH has been not allocated in the cell.
1013 */
1014 switch( grr_data->ms.class_of_mode )
1015 {
1016 case GMMRR_CLASS_A:
1017 /* BEGIN GRR_NMO_III */
1018 case GMMRR_CLASS_B:
1019 /* END GRR_NMO_III */
1020 case GMMRR_CLASS_BG:
1021 case GMMRR_CLASS_BC:
1022 case GMMRR_CLASS_CG:
1023 case GMMRR_CLASS_CC:
1024 sig_pg_ctrl_start_mon_ccch( PAG_MODE_DEFAULT );
1025 break;
1026 }
1027 break;
1028
1029 case GMMRR_NET_MODE_III:
1030 /*
1031 * NMOIII:
1032 * =======
1033 * If PBCCH not present paging for both circuit switched and packet
1034 * data will be sent on CCCH,
1035 * if PBCCH is present paging for circuit switched data is sent on
1036 * CCCH and for packet data on PCCCH.
1037 */
1038 if( grr_is_pbcch_present( ) )
1039 {
1040 TRACE_EVENT( "GMMRR_NET_MODE_III PBCCH" );
1041
1042 switch(grr_data->ms.class_of_mode)
1043 {
1044 case GMMRR_CLASS_A:
1045 pg_send_start( psc_db->last_pg_mode );
1046 sig_pg_ctrl_start_mon_ccch( PAG_MODE_PIM_NP );
1047 break;
1048
1049 /*
1050 * We need to check whether the MS class B mobile
1051 * reverts to CG or CC in NMO III. If not it should monitor PCCCH and CCCH
1052 * else it needs to monitor either CCCH or PCCCH
1053 */
1054 /* BEGIN GRR_NMO_III */
1055 case GMMRR_CLASS_B:
1056 /* END GRR_NMO_III */
1057 case GMMRR_CLASS_BG:
1058 case GMMRR_CLASS_BC:
1059 pg_handle_classB_NMO_III( transition );
1060 break;
1061
1062 case GMMRR_CLASS_CG:
1063 sig_pg_ctrl_stop_mon_ccch( );
1064 pg_send_start( psc_db->last_pg_mode );
1065 break;
1066
1067 case GMMRR_CLASS_CC:
1068 sig_pg_ctrl_start_mon_ccch( PAG_MODE_DEFAULT );
1069 break;
1070 }
1071 }
1072 else
1073 {
1074 TRACE_EVENT ( "GMMRR_NET_MODE_III BCCH" );
1075
1076 sig_pg_ctrl_start_mon_ccch( PAG_MODE_DEFAULT );
1077 }
1078 break;
1079 }
1080 } /* pg_handle_idle_mode() */
1081
1082 /*
1083 +------------------------------------------------------------------------------
1084 | Function : pg_handle_transfer_mode
1085 +------------------------------------------------------------------------------
1086 | Description :
1087 |
1088 | Parameters :
1089 |
1090 +------------------------------------------------------------------------------
1091 */
1092 GLOBAL void pg_handle_transfer_mode ( T_PG_TRANS transition )
1093 {
1094 TRACE_FUNCTION( "pg_handle_transfer_mode" );
1095
1096 switch( grr_data->pg.nmo )
1097 {
1098 case GMMRR_NET_MODE_I:
1099 /*
1100 * NMOI:
1101 * ====
1102 * Paging on ( CCCH or PCCCH ) and PACCH, GPRS attached MS should
1103 * monitor one paging channel, so we have to stop monitoring CCCH
1104 * channel if PCCCH is present.
1105 */
1106 if( grr_is_pbcch_present( ) )
1107 {
1108 pg_send_stop( );
1109 }
1110 else
1111 {
1112 sig_pg_ctrl_stop_mon_ccch( );
1113 }
1114 break;
1115
1116 case GMMRR_NET_MODE_II:
1117 /*
1118 * NMOII:
1119 * =====
1120 * Paging on CCCH, paging for both circuit switched and packet data
1121 * will be sent on CCCH, PCCCH has been not allocated in the cell.
1122 *
1123 * The MS should monitor CCCH except for the CLASS_CG.
1124 */
1125 switch( grr_data->ms.class_of_mode )
1126 {
1127 case GMMRR_CLASS_A:
1128 /* BEGIN GRR_NMO_III*/
1129 case GMMRR_CLASS_B:
1130 /* END GRR_NMO_III*/
1131 case GMMRR_CLASS_BG:
1132 case GMMRR_CLASS_BC:
1133 if( grr_data->ms.tbf_mon_ccch
1134 #ifdef REL99
1135 AND
1136 !psc_db->gprs_cell_opt.gprs_ext_bits.gprs_ext_info.bss_paging_coord
1137 #endif
1138 )
1139 {
1140 sig_pg_ctrl_start_mon_ccch( PAG_MODE_PTM_NP );
1141 }
1142 else
1143 {
1144 sig_pg_ctrl_stop_mon_ccch( );
1145 }
1146 break;
1147
1148 case GMMRR_CLASS_CG:
1149 sig_pg_ctrl_stop_mon_ccch( );
1150 break;
1151 }
1152 break;
1153
1154 case GMMRR_NET_MODE_III:
1155 /*
1156 * NMOIII:
1157 * =======
1158 * If PBCCH not present paging for both circuit switched and packet
1159 * data will be sent on CCCH,
1160 * if PBCCH is present paging for circuit switched data is sent on
1161 * CCCH and for packet data on PCCCH.
1162 */
1163 switch( grr_data->ms.class_of_mode )
1164 {
1165 case GMMRR_CLASS_A:
1166 if( grr_is_pbcch_present( ) )
1167 {
1168 pg_send_stop( );
1169 }
1170
1171 sig_pg_ctrl_start_mon_ccch( PAG_MODE_PTM_NP );
1172 break;
1173
1174 /* BEGIN GRR_NMO_III*/
1175 case GMMRR_CLASS_B:
1176 /* END GRR_NMO_III*/
1177 case GMMRR_CLASS_BG:
1178 case GMMRR_CLASS_BC:
1179 pg_handle_classB_NMO_III( transition );
1180 break;
1181
1182 case GMMRR_CLASS_CG:
1183 if( grr_is_pbcch_present( ) )
1184 {
1185 pg_send_stop( );
1186 }
1187 else
1188 {
1189 sig_pg_ctrl_stop_mon_ccch( );
1190 }
1191 break;
1192 }
1193 break;
1194 }
1195 } /* pg_handle_transfer_mode() */