comparison gsm-fw/g23m-gsm/mm/mm_tim.c @ 673:2f7df7a314f8

gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 28 Sep 2014 23:20:04 +0000
parents
children acc31840d51c
comparison
equal deleted inserted replaced
672:0dc6f9e8e980 673:2f7df7a314f8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : GSM-PS (8410)
4 | Modul : MM_TIM
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 Modul defines the timer handling functions
18 | for the component MM of the mobile station
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef MM_TIM_C
23 #define MM_TIM_C
24
25 #define ENTITY_MM
26
27 /*==== INCLUDES ===================================================*/
28 #if defined (NEW_FRAME)
29
30 #include <string.h>
31 #include <stdlib.h>
32 #include <stddef.h>
33 #include "typedefs.h"
34 #include "pcm.h"
35 #include "pconst.cdg"
36 #include "mconst.cdg"
37 #include "message.h"
38 #include "ccdapi.h"
39 #include "vsi.h"
40 #include "custom.h"
41 #include "gsm.h"
42 #include "prim.h"
43 #include "cnf_mm.h"
44 #include "mon_mm.h"
45 #include "pei.h"
46 #include "tok.h"
47 #include "mm.h"
48
49 #else
50
51 #include <string.h>
52 #include <stdlib.h>
53 #include <stddef.h>
54 #include "stddefs.h"
55 #include "pcm.h"
56 #include "pconst.cdg"
57 #include "mconst.cdg"
58 #include "message.h"
59 #include "ccdapi.h"
60 #include "custom.h"
61 #include "gsm.h"
62 #include "prim.h"
63 #include "cnf_mm.h"
64 #include "mon_mm.h"
65 #include "vsi.h"
66 #include "pei.h"
67 #include "tok.h"
68 #include "mm.h"
69
70 #endif
71 /*==== EXPORT =====================================================*/
72
73 /*==== PRIVAT =====================================================*/
74
75 /*==== VARIABLES ==================================================*/
76
77 #if defined (OPTION_TIMER)
78 LOCAL T_TIMER_CONFIG config_table[NUM_OF_MM_TIMERS];
79 #endif
80
81
82 /*==== FUNCTIONS ==================================================*/
83 #if defined (OPTION_TIMER)
84 /*
85 +--------------------------------------------------------------------+
86 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
87 | STATE : code ROUTINE : tim_init_timer |
88 +--------------------------------------------------------------------+
89
90 PURPOSE : Initialise Time-out FIFO and configuration data.
91
92 */
93
94
95 GLOBAL BOOL tim_init_timer (void)
96 {
97 USHORT i;
98
99 TRACE_FUNCTION ("tim_init_timer()");
100
101 for (i = 0; i < NUM_OF_MM_TIMERS; i++)
102 {
103 config_table[i].t_mode = TIMER_RESET;
104 config_table[i].t_val = 0L;
105 }
106
107 return TRUE;
108 }
109 #endif /* #if defined (OPTION_TIMER) */
110
111 #if defined (OPTION_TIMER)
112
113 /*
114 +--------------------------------------------------------------------+
115 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
116 | STATE : code ROUTINE : tim_config_timer |
117 +--------------------------------------------------------------------+
118
119 PURPOSE : Configure Timer
120
121 */
122
123 GLOBAL void tim_config_timer (UBYTE t_num, UBYTE t_mod, ULONG t_val)
124 {
125 TRACE_FUNCTION ("tim_config_timer()");
126
127 assert (t_num < NUM_OF_MM_TIMERS);
128
129 if (t_num < NUM_OF_MM_TIMERS)
130 {
131 config_table[t_num].t_mode = t_mod;
132 config_table[t_num].t_val = t_val;
133 }
134 else
135 {
136 TRACE_ERROR ("tim_config_timer(): index out of range");
137 }
138 }
139 #endif /* #if defined (OPTION_TIMER) */
140
141 #if defined (NEW_FRAME)
142 /*
143 +--------------------------------------------------------------------+
144 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
145 | STATE : code ROUTINE : tim_exec_timeout |
146 +--------------------------------------------------------------------+
147
148 PURPOSE : execute timeout
149
150 */
151
152 GLOBAL void tim_exec_timeout (USHORT index)
153 {
154 GET_INSTANCE_DATA;
155 /* typedef void (*T_VOID_FUNC)(); */ /* Already defined */
156
157 static const T_VOID_FUNC timer_jump_table[NUM_OF_MM_TIMERS] =
158 {
159 tim_t_reg, /* T_REGISTRATION */
160 tim_t3210, /* T3210 */
161 tim_t3211, /* T3211 */
162 tim_t3212, /* T3212 */
163 tim_t3213, /* T3213 */
164 tim_t3220, /* T3220 */
165 tim_t3230, /* T3230 */
166 tim_t3240, /* T3240 */
167
168 tim_t_hplmn /* T_HPLMN */
169 #ifdef REL99
170 , tim_t3241 /* T3241 */
171 #endif
172 };
173
174 if (index < NUM_OF_MM_TIMERS)
175 {
176 /*
177 * Timeout is handled in SDL like the reception of a primitive,
178 * so enable also this trace if primitive traces are enabled only
179 */
180 /* Implements Measure#36 */
181 #if defined(NCONFIG)
182 /* partab is not defined when NCONFIG is defined */
183 TRACE_EVENT_P1 ("tim_exec_timeout: index (%d)", index);
184 #else /* not (NCONFIG) */
185 #if defined (TRACE_PRIM) AND defined(OPTION_TIMER)
186 TRACE_EVENT_P1 ("tim_exec_timeout (%s)", partab[index].keyword);
187 #endif
188 #endif /* NCONFIG */
189
190 mm_data->t_running[index] = FALSE;
191 timer_jump_table[index]();
192 }
193 else
194 {
195 TRACE_ERROR ("tim_exec_timeout(): index out of range");
196 }
197 }
198
199
200 /*
201 +--------------------------------------------------------------------+
202 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
203 | STATE : code ROUTINE : tim_stop_timer |
204 +--------------------------------------------------------------------+
205
206 PURPOSE : stop timer
207
208 */
209
210 GLOBAL void tim_stop_timer (USHORT index)
211 {
212 GET_INSTANCE_DATA;
213 assert (index < NUM_OF_MM_TIMERS);
214
215 if (index < NUM_OF_MM_TIMERS)
216 {
217 /* Implements Measure#36 */
218 #if defined(NCONFIG)
219 /* partab is not defined when NCONFIG is defined */
220 TRACE_EVENT_P1 ("tim_stop_timer: index (%d)", index);
221 #else /* not (NCONFIG) */
222 #if defined (TRACE_PRIM) AND defined(OPTION_TIMER)
223 TRACE_EVENT_P1 ("tim_stop_timer (%s)", partab[index].keyword);
224 #endif
225 #endif /* NCONFIG */
226
227 mm_data->t_running[index] = FALSE;
228 TIMER_STOP (mm_handle, index);
229 }
230 else
231 {
232 TRACE_ERROR ("tim_stop_timer(): index out of range");
233 }
234 }
235
236 /*
237 +--------------------------------------------------------------------+
238 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
239 | STATE : code ROUTINE : tim_start_timer |
240 +--------------------------------------------------------------------+
241
242 PURPOSE : start timer
243
244 */
245
246 GLOBAL void tim_start_timer (USHORT index, T_TIME value)
247 {
248 GET_INSTANCE_DATA;
249 assert (index < NUM_OF_MM_TIMERS);
250
251 if (index < NUM_OF_MM_TIMERS)
252 {
253 /* Implements Measure#36 */
254 #if defined(NCONFIG)
255 /* partab is not defined when NCONFIG is defined */
256 TRACE_EVENT_P1 ("tim_start_timer: index (%d)", index);
257 #else /* not (NCONFIG) */
258 #if defined (TRACE_PRIM) AND defined(OPTION_TIMER)
259 TRACE_EVENT_P1 ("tim_start_timer (%s)", partab[index].keyword);
260 #endif
261 #endif /* NCONFIG */
262 #if defined (OPTION_TIMER)
263 switch (config_table[index].t_mode)
264 {
265 case TIMER_SET:
266 value = config_table[index].t_val;
267 break;
268
269 case TIMER_RESET:
270 value = value;
271 break;
272
273 case TIMER_SPEED_UP:
274 value = value / config_table[index].t_val;
275 if (value == 0)
276 value = 1;
277 TRACE_EVENT_P1 ("timer_speed_up (%d)", value);
278 break;
279
280 case TIMER_SLOW_DOWN:
281 value = value * config_table[index].t_val;
282 TRACE_EVENT_P1 ("timer_speed_down (%d)", value);
283 break;
284
285 default:
286 TRACE_FUNCTION ("ERROR: UNKNOWN MODE");
287 return;
288 }
289 #endif
290
291 mm_data->t_running[index] = TRUE;
292
293 TIMER_START (mm_handle, index, value);
294 }
295 else
296 {
297 TRACE_ERROR ("tim_start_timer(): index out of range");
298 }
299 }
300
301 #endif /* #if defined (NEW_FRAME) */
302
303 /*
304 +--------------------------------------------------------------------+
305 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
306 | STATE : code ROUTINE : tim_t3210 |
307 +--------------------------------------------------------------------+
308
309 PURPOSE : Timeout of timer T3210
310
311 */
312
313 GLOBAL void tim_t3210 (void)
314 {
315 GET_INSTANCE_DATA;
316 TRACE_FUNCTION ("tim_t3210()");
317
318 switch (GET_STATE (STATE_MM))
319 {
320 case MM_LUP_INITIATED:
321 case MM_WAIT_FOR_RR_CONN_LUP:
322 TIMERSTOP (T3240);
323 mm_abort_connection (ABCS_NORM);
324 /*
325 * The RR connection is aborted normally. RR guarantees that this will
326 * be answered by RR_RELEASE_IND.
327 * This has the advange that GMM gets the MMGMM_NREG_IND after the
328 * channel release of layer 2 if GPRS present without any disadvantage
329 * for a GSM only protocol stack. No state change here.
330 */
331 break;
332
333 default: /* Ignore event */
334 break;
335 }
336 }
337
338 /*
339 +--------------------------------------------------------------------+
340 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
341 | STATE : code ROUTINE : tim_t3211 |
342 +--------------------------------------------------------------------+
343
344 PURPOSE : Timeout of timer T3211
345
346 */
347
348 // T3211 handling routine does the same as T3213 handling routine now ...
349
350 GLOBAL void tim_t3211 (void)
351 {
352 GET_INSTANCE_DATA;
353 TRACE_FUNCTION ("tim_t3211()");
354
355 switch (GET_STATE (STATE_MM))
356 {
357 // If we leave these states and reenter a full service IDLE state,
358 // mm_release_rr_connection()
359 // for MM_WAIT_FOR_OUTG_MM_CONN and MM_WAIT_FOR_RR_CONN_MM will
360 // handle the update.
361 // mm_rr_activate_cnf() for MM_WAIT_FOR_RR_ACTIVE will also
362 // handle the an outstanding update if coming back to full
363 // service IDLE state.
364 // mm_rr_abort_ind() will be called if the state was
365 // MM_PLMN_SEARCH_NORMAL_SERVICE, if there is an outstanding
366 // updating procedure and the new service is full service,
367 // this will be checked there after state transition.
368 // MM_IDLE_NO_CELL_AVAILABLE / RR_ACTIVATE_IND is handled also.
369 // No need to store the timer anymore into the queue.
370
371 /*
372 // case MM_WAIT_FOR_OUTG_MM_CONN:
373 // case MM_WAIT_FOR_RR_CONN_MM:
374 // case MM_WAIT_FOR_RR_ACTIVE:
375 case MM_PLMN_SEARCH_NORMAL_SERVICE:
376 // case MM_IDLE_NO_CELL_AVAILABLE:
377 mm_write_entry (TIMEOUT, T3211, 0);
378 break;
379 */
380
381 case MM_IDLE_ATTEMPT_TO_UPDATE:
382 case MM_IDLE_NORMAL_SERVICE:
383 mm_continue_running_update ();
384 break;
385
386 default: /* Ignore event */
387 break;
388 }
389 }
390
391 /*
392 +--------------------------------------------------------------------+
393 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
394 | STATE : code ROUTINE : tim_t3212 |
395 +--------------------------------------------------------------------+
396
397 PURPOSE : Timeout of counter timer for timer T3212
398
399 */
400
401 GLOBAL void tim_t3212 (void)
402 {
403 GET_INSTANCE_DATA;
404 TRACE_FUNCTION ("tim_t3212()");
405
406 switch (GET_STATE (STATE_MM))
407 {
408 case MM_NULL:
409 case MM_IDLE_NO_IMSI:
410 break; /* Forget the event */
411
412 case MM_IDLE_NORMAL_SERVICE:
413 mm_data->t3212_timeout = TRUE;
414 mm_data->attempt_cnt = 0; /* Expiry of timer T3212 */
415 if (!mm_normal_upd_needed())
416 {
417 /* MM is updated on the cell, no Imm Ass Rej, no cell barred */
418 if (mm_lup_allowed_by_gmm())
419 {
420 mm_periodic_loc_upd ();
421 }
422 else
423 {
424 mm_mmgmm_lup_needed_ind (MMGMM_T3212);
425 /* No state change, remains in MM_IDLE_NORMAL_SERVICE */
426 }
427 }
428 break;
429
430 case MM_IDLE_ATTEMPT_TO_UPDATE:
431 if (mm_data->mm.mm_info.t3212 NEQ T3212_NO_PRD_UPDAT)
432 {
433 mm_data->t3212_timeout = TRUE;
434 mm_data->attempt_cnt = 0; /* Expiry of timer T3212 */
435 if (mm_lup_allowed_by_gmm())
436 {
437 mm_normal_loc_upd ();
438 }
439 else
440 {
441 mm_mmgmm_lup_needed_ind (MMGMM_T3212);
442 /* No state change, remains in MM_IDLE_ATTEMPT_TO_UPDATE */
443 }
444 }
445 break;
446
447 default: /* Store the event until it is possible to handle it */
448 mm_data->t3212_timeout = TRUE;
449 break;
450 }
451 }
452
453 /*
454 +--------------------------------------------------------------------+
455 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
456 | STATE : code ROUTINE : tim_t3213 |
457 +--------------------------------------------------------------------+
458
459 PURPOSE : Timeout of timer T3213
460
461 */
462
463 GLOBAL void tim_t3213 (void)
464 {
465 GET_INSTANCE_DATA;
466 TRACE_FUNCTION ("tim_t3213()");
467
468 switch (GET_STATE (STATE_MM))
469 {
470 /*
471 case MM_WAIT_FOR_OUTG_MM_CONN:
472 case MM_WAIT_FOR_RR_CONN_MM:
473 case MM_WAIT_FOR_RR_ACTIVE:
474 case MM_PLMN_SEARCH_NORMAL_SERVICE:
475 mm_write_entry (TIMEOUT, T3213, 0);
476 break;
477 */
478
479 case MM_IDLE_ATTEMPT_TO_UPDATE:
480 case MM_IDLE_NORMAL_SERVICE:
481 /*
482 * if something is received from RR or T3213 was already restarted 2 times --> delay of additional 8 seconds
483 * continue the LUP attempts
484 */
485 mm_data->t3213_restart++;
486 if (mm_data->t3213_restart > MAX_REST_T3213)
487 mm_continue_running_update ();
488 else
489 TIMERSTART (T3213, T_3213_VALUE);
490 break;
491
492 default: /* Ignore event */
493 break;
494 }
495 }
496
497 /*
498 +--------------------------------------------------------------------+
499 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
500 | STATE : code ROUTINE : tim_t3220 |
501 +--------------------------------------------------------------------+
502
503 PURPOSE : Timeout of timer T3220
504
505 */
506
507 GLOBAL void tim_t3220 (void)
508 {
509 GET_INSTANCE_DATA;
510 TRACE_FUNCTION ("tim_t3220()");
511
512 switch (GET_STATE (STATE_MM))
513 {
514 case MM_IMSI_DETACH_INIT:
515 case MM_WAIT_FOR_RR_CONN_DETACH:
516 /*
517 * The RR connection is aborted normally. RR guarantees that this will
518 * be answered by RR_RELEASE_IND. If MM receives the RR_RELEASE_IND,
519 * the IMSI DETACH procedure ends and appropriate actions are taken.
520 * This has the advange that GMM gets the MMGMM_NREG_CNF after the
521 * channel release of layer 2 if GPRS present without any disadvantage
522 * for a GSM only protocol stack. No state change here.
523 */
524 mm_abort_connection (ABCS_NORM);
525 break;
526
527 default: /* Ignore event */
528 break;
529 }
530 }
531
532 /*
533 +--------------------------------------------------------------------+
534 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
535 | STATE : code ROUTINE : tim_t3230 |
536 +--------------------------------------------------------------------+
537
538 PURPOSE : Timeout of timer T3230
539
540 */
541
542 GLOBAL void tim_t3230 (void)
543 {
544 GET_INSTANCE_DATA;
545 TRACE_FUNCTION ("tim_t3230()");
546
547 /*
548 * If T3230 expires (i.e. no response is given but a RR connection is
549 * available) the MM connection establishment is aborted and the requesting
550 * CM sublayer is informed. If no other MM connection exists then the mobile
551 * station shall proceed as described in section 4.5.3.1 for release of the
552 * RR connection. Otherwise the mobile station shall return to the MM
553 * sublayer state where the request of an MM connection was received,
554 * i.e. to MM sublayer state MM connection active. Other ongoing
555 * MM connections (if any) shall not be affected.
556 * [GSM 04.08 subclause 4.5.1.2 b)]
557 *
558 * If all MM connections are released by their CM entities, the
559 * mobile station shall set timer T3240 and enter the state
560 * WAIT FOR NETWORK COMMAND, expecting the release of the RR connection.
561 * [Excerpt from GSM 04.08 subclause 4.5.3.1]
562 */
563
564 switch (GET_STATE (STATE_MM))
565 {
566 case MM_WAIT_FOR_REESTABLISH:
567 case MM_WAIT_FOR_OUTG_MM_CONN:
568 mm_mmxx_rel_ind (MMCS_TIMER_RECOVERY, CM_ACTIVE);
569 mm_mmxx_rel_ind (MMCS_TIMER_RECOVERY, CM_PENDING);
570 mm_data->wait_for_accept = FALSE;
571 TIMERSTART (T3240, T_3240_VALUE);
572 SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD);
573 break;
574
575 case MM_CONN_ACTIVE: /* wait_for_accept expected to be TRUE */
576 mm_mmxx_rel_ind (MMCS_TIMER_RECOVERY, CM_PENDING);
577 mm_data->wait_for_accept = FALSE;
578 if ((mm_count_connections (CM_ACTIVE) EQ 0) AND
579 (mm_count_connections (CM_STORE) EQ 0))
580 {
581 TIMERSTART (T3240, T_3240_VALUE);
582 SET_STATE (STATE_MM, MM_WAIT_FOR_NW_CMD);
583 }
584 USE_STORED_ENTRIES();
585 break;
586
587 default: /* Ignore event */
588 break;
589 }
590 }
591
592 /*
593 +--------------------------------------------------------------------+
594 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
595 | STATE : code ROUTINE : tim_t3240 |
596 +--------------------------------------------------------------------+
597
598 PURPOSE : Timeout of timer T3240
599
600 */
601
602 GLOBAL void tim_t3240 (void)
603 {
604 GET_INSTANCE_DATA;
605 TRACE_FUNCTION ("tim_t3240()");
606
607 switch (GET_STATE (STATE_MM))
608 {
609 case MM_PROCESS_PROMPT:
610 case MM_WAIT_FOR_NW_CMD:
611 mm_abort_connection (ABCS_NORM);
612 mm_mmxx_rel_ind (MMCS_TIMER_RECOVERY, CM_ACTIVE);
613 mm_mmxx_rel_ind (MMCS_TIMER_RECOVERY, CM_PENDING);
614
615 /*
616 * The RR connection is aborted normally. RR guarantees that this will
617 * be answered by RR_RELEASE_IND.
618 * This has the advange that GMM gets the MMGMM_CM_RELEASE_IND after the
619 * channel release of layer 2 if GPRS present without any disadvantage
620 * for a GSM only protocol stack. No state change here.
621 */
622 break;
623
624 case MM_LUP_REJECTED:
625 mm_abort_connection (ABCS_NORM);
626 /*
627 * The RR connection is aborted normally. RR guarantees that this will
628 * be answered by RR_RELEASE_IND.
629 * This has the advange that GMM gets the MMGMM_NREG_IND after the
630 * channel release of layer 2 if GPRS present without any disadvantage
631 * for a GSM only protocol stack. No state change here.
632 */
633 break;
634
635 default: /* Ignore event */
636 break;
637 }
638 }
639
640 #ifdef REL99
641 /*
642 +--------------------------------------------------------------------+
643 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
644 | STATE : code ROUTINE : tim_t3241 |
645 +--------------------------------------------------------------------+
646
647 PURPOSE : Timeout of timer T3241
648
649 */
650
651 GLOBAL void tim_t3241 (void)
652 {
653 GET_INSTANCE_DATA;
654 TRACE_FUNCTION ("tim_t3241()");
655
656 switch (GET_STATE (STATE_MM))
657 {
658 case MM_RR_CONN_RELEASE_NOT_ALLOWED:
659 mm_abort_connection (ABCS_NORM);
660 /*
661 * The RR connection is aborted normally. RR guarantees that this will
662 * be answered by RR_RELEASE_IND.
663 * This has the advange that GMM gets the MMGMM_CM_RELEASE_IND after the
664 * channel release of layer 2 if GPRS present without any disadvantage
665 * for a GSM only protocol stack. No state change here.
666 */
667 break;
668 default: /* Ignore event */
669 break;
670 }
671 }
672 #endif
673
674
675 /*
676 +----------------------------------------------------------------------------+
677 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
678 | STATE : code ROUTINE : tim_t_hplmn |
679 +----------------------------------------------------------------------------+
680
681 PURPOSE : Timeout of timer T_HPLMN.
682 This timer allows control of the PPLMN rescan and
683 national roaming procedure to recover the HPLMN.
684 */
685
686 GLOBAL void tim_t_hplmn (void)
687 {
688 GET_INSTANCE_DATA;
689 TRACE_FUNCTION ("tim_t_hplmn()");
690
691 /*
692 * Launch the scan procedure if it still makes sense to do it according to
693 * MM state.
694 */
695 if (mm_full_service_pplmn_scan())
696 {
697 mm_data->plmn_scan_mm = TRUE;
698 mm_data->first_attach_mem = FALSE;
699 mm_func_mmgmm_net_req();
700 }
701 }
702
703
704 /*
705 +--------------------------------------------------------------------+
706 | PROJECT : GSM-PS (6147) MODULE : MM_TIM |
707 | STATE : code ROUTINE : tim_t_reg |
708 +--------------------------------------------------------------------+
709
710 PURPOSE : Timeout of timer T_REG.
711 This timer is not foreseen by the recommendations.
712 It is MM's health monitor timer, checking
713 the conditions whether an update has been missed.
714
715 */
716
717 GLOBAL void tim_t_reg (void)
718 {
719 GET_INSTANCE_DATA;
720 TRACE_FUNCTION ("tim_t_reg()");
721
722 switch (GET_STATE (STATE_MM))
723 {
724 case MM_NULL:
725 break; /* No timer activity in this state */
726
727 case MM_IDLE_NORMAL_SERVICE: /* 19.1 */
728 /* Restart the registration timer */
729 TIMERSTART (T_REGISTRATION, T_REG_VALUE);
730
731 /*
732 * As it is not expected that the timer catches in state
733 * MM_IDLE_NORMAL_SERVICE in FTA, there is no test
734 * here for a test SIM. The goal is to have an MM
735 * where the timer never catches in MM_IDLE_NORMAL_SERVICE.
736 */
737
738 /* Check whether T3211, T3213 are running retriggering update anyway */
739 if ((TIMERACTIVE (T3211) OR TIMERACTIVE (T3213)) AND
740 (mm_data->loc_upd_type.lut NEQ NOT_RUNNING))
741 return;
742
743 /* Check whether MM is temporary barred and cannot update now */
744 if ((mm_data->idle_entry EQ RRCS_ACCESS_BARRED) OR
745 (mm_data->idle_entry EQ RRCS_RND_ACC_DELAY))
746 return;
747
748 /*
749 * Check whether we are in an ATTACH update procedure, but there is no
750 * T3211, T3213 timer running and MM is not temporary barred.
751 */
752 if (mm_attach_upd_needed() OR mm_normal_upd_needed())
753 {
754 TRACE_ERROR ("Recover ATTACH/NORMAL");
755
756 mm_mmgmm_lup_needed_ind (MMGMM_REG_TIMER);
757
758 if (mm_normal_upd_needed ())
759 {
760 mm_data->attempt_cnt = 0; /* New location area */
761 mm_normal_loc_upd ();
762 }
763 else
764 {
765 mm_attach_loc_upd ();
766 }
767 return;
768 }
769
770 /*
771 * Check whether T3212 should run, but is not running.
772 * If so, something irregular has happened and
773 * we have to start the update immediately.
774 */
775 if (mm_data->mm.mm_info.t3212 NEQ T3212_NO_PRD_UPDAT AND
776 (!TIMERACTIVE (T3212) OR mm_data->t3212_timeout))
777 {
778 /*
779 * The networks says we have periodic updating,
780 * but unexpectedly T3212 is not running or T3212 timed out.
781 */
782 TRACE_ERROR ("Recover PERIODIC");
783
784 if (mm_lup_allowed_by_gmm())
785 {
786 mm_periodic_loc_upd ();
787 }
788 else
789 {
790 // Don't add recovery code now for GPRS, maybe more has to be done.
791 // mm_mmgmm_lup_needed_ind (MMGMM_REG_TIMER);
792 }
793 return;
794 }
795 break;
796
797 case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */
798 /* Restart the registration timer */
799 TIMERSTART (T_REGISTRATION, T_REG_VALUE);
800
801 /* Timer only handled in this state if a normal SIM is present */
802 if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT OR
803 mm_data->reg.op.ts EQ TS_AVAIL)
804 return;
805
806 /* Check whether T3211, T3213 are running retriggering update anyway */
807 if ((TIMERACTIVE (T3211) OR TIMERACTIVE (T3213)) AND
808 (mm_data->loc_upd_type.lut NEQ NOT_RUNNING))
809 return;
810
811 if (TIMERACTIVE (T3212))
812 return;
813
814
815 /* Check whether MM is temporary barred and cannot update now */
816 if ((mm_data->idle_entry EQ RRCS_ACCESS_BARRED) OR
817 (mm_data->idle_entry EQ RRCS_RND_ACC_DELAY))
818 return;
819
820 if (mm_gsm_alone ())
821 {
822 mm_normal_loc_upd ();
823 }
824 else
825 {
826 mm_mmgmm_lup_needed_ind (MMGMM_REG_TIMER);
827 /* No state change, remains in MM_IDLE_ATTEMPT_TO_UPDATE */
828 }
829 break;
830
831 default:
832 /* Restart the registration timer */
833 TIMERSTART (T_REGISTRATION, T_REG_VALUE);
834 break;
835 }
836 }
837
838 #endif