comparison src/g23m-gsm/mm/mm_mmf.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : GSM-PS (8410)
4 | Modul : MM_MMF
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 functions for the mob. management
18 | capability of the module Mobility Management.
19 +-----------------------------------------------------------------------------
20 */
21
22 #ifndef MM_MMF_C
23 #define MM_MMF_C
24
25 #define ENTITY_MM
26
27 /*==== INCLUDES ===================================================*/
28
29 #include <string.h>
30 #include <stdlib.h>
31 #include <stddef.h>
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_mm.h"
43 #include "mon_mm.h"
44 #include "pei.h"
45 #include "tok.h"
46 #include "mm.h"
47 #ifdef _SIMULATION_
48 #include "ffs_pc_api.h"
49 #else
50 #include "ffs/ffs.h"
51 #endif
52 #include "mm_em.h"
53
54
55
56
57 /*==== EXPORT =====================================================*/
58 BOOL poor_quality_network = FALSE; /* Hack, maybe needed by CC */
59
60 /*==== TEST =====================================================*/
61
62 /*==== VARIABLES ==================================================*/
63
64 /*==== FUNCTIONS ==================================================*/
65 GLOBAL T_FFS_RET ffs_mkdir(const char *name);
66
67 /*==== PRIVAT =====================================================*/
68 LOCAL BOOL mm_handle_ffs_read_result (T_FFS_SIZE status_read);
69 LOCAL BOOL mm_handle_ffs_write_result (T_FFS_RET status_write);
70 LOCAL BOOL mm_create_ffs_dirs (const char *name);
71 LOCAL BOOL mm_check_ffs_dirs (void);
72
73
74 /*
75 +--------------------------------------------------------------------+
76 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
77 | STATE : code ROUTINE : mm_fill_identity |
78 +--------------------------------------------------------------------+
79
80 PURPOSE : This function fills the mobile identity structure with
81 the desired identity, this maybe the IMSI, the IMSISV,
82 the IMEI or the TMSI.
83
84 */
85
86 LOCAL void mm_fill_identity (T_mob_id *mob_ident, UBYTE id_type)
87 {
88 GET_INSTANCE_DATA;
89 T_imsi_struct imei_struct;
90 TRACE_FUNCTION ("mm_fill_identity()");
91
92 memset (mob_ident, 0, sizeof (T_mob_id));
93
94 switch (id_type)
95 {
96 case ID_TYPE_IMSI:
97 mob_ident->ident_type = id_type;
98 mob_ident->v_ident_dig = TRUE;
99 mob_ident->c_ident_dig = mm_calculate_digits (mm_data->reg.imsi_struct.id);
100 mob_ident->odd_even = mob_ident->c_ident_dig & 1;
101 memcpy (mob_ident->ident_dig, mm_data->reg.imsi_struct.id, 16);
102 break;
103
104 case ID_TYPE_IMEI:
105 csf_read_imei (&imei_struct);
106 mob_ident->ident_type = id_type;
107 mob_ident->v_ident_dig = TRUE;
108 mob_ident->c_ident_dig = 15;
109 mob_ident->odd_even = 1;
110 memcpy (mob_ident->ident_dig, imei_struct.id, 14);
111 mob_ident->ident_dig[14] = 0;
112 break;
113
114 case ID_TYPE_IMEISV:
115 csf_read_imei (&imei_struct);
116 mob_ident->ident_type = id_type;
117 mob_ident->v_ident_dig = TRUE;
118 mob_ident->c_ident_dig = 16;
119 mob_ident->odd_even = 0;
120 memcpy (mob_ident->ident_dig, imei_struct.id, 16);
121 break;
122
123 case ID_TYPE_TMSI:
124 mob_ident->ident_type = id_type;
125 mob_ident->v_ident_dig = FALSE;
126 mob_ident->tmsi.l_tmsi = 32;
127 mob_ident->v_tmsi = TRUE;
128 ccd_codeByte (mob_ident->tmsi.b_tmsi, 0, 8,
129 (UBYTE)(mm_data->reg.tmsi >> 24));
130 ccd_codeByte (mob_ident->tmsi.b_tmsi, 8, 8,
131 (UBYTE)(mm_data->reg.tmsi >> 16));
132 ccd_codeByte (mob_ident->tmsi.b_tmsi, 16, 8,
133 (UBYTE)(mm_data->reg.tmsi >> 8));
134 ccd_codeByte (mob_ident->tmsi.b_tmsi, 24, 8,
135 (UBYTE)(mm_data->reg.tmsi));
136 break;
137
138 default:
139 TRACE_ERROR ("No such mobile identity");
140 break;
141 }
142 }
143
144 /*
145 +--------------------------------------------------------------------+
146 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
147 | STATE : code ROUTINE : mm_fill_ident_for_est |
148 +--------------------------------------------------------------------+
149
150 PURPOSE : This functinon fills the mobile identity for an
151 establishment message and uses the appropriate identity
152 for this purpose. The function returns the used mobile
153 identity type.
154
155 */
156
157 LOCAL UBYTE mm_fill_ident_for_est (T_mob_id *mob_ident)
158 {
159 GET_INSTANCE_DATA;
160 UBYTE id_type;
161
162 TRACE_FUNCTION ("mm_fill_ident_for_est()");
163
164 if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT)
165 {
166 /* No SIM present */
167 id_type = ID_TYPE_IMEI;
168 }
169 else
170 {
171 /* SIM present */
172 if (mm_data->reg.tmsi EQ TMSI_INVALID_VALUE)
173 {
174 /* No TMSI present */
175 id_type = ID_TYPE_IMSI;
176 }
177 else
178 {
179 /* TMSI present */
180 id_type = ID_TYPE_TMSI;
181 }
182 }
183
184 mm_fill_identity (mob_ident, id_type);
185
186 return id_type;
187 }
188
189 /*==== VARIABLES ==================================================*/
190
191 /*==== FUNCTIONS ==================================================*/
192
193 /*
194 * -------------------------------------------------------------------
195 * Procedures
196 * -------------------------------------------------------------------
197 */
198
199
200 /*
201 +--------------------------------------------------------------------+
202 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
203 | STATE : code ROUTINE : mm_abort_connection |
204 +--------------------------------------------------------------------+
205
206 PURPOSE : This function sends the RR_ABORT_REQ primitive.
207
208 */
209
210 GLOBAL void mm_abort_connection (UBYTE abcs)
211 {
212 TRACE_FUNCTION ("mm_abort_connection ()");
213
214 assert (abcs EQ ABCS_SIM_REM OR
215 abcs EQ ABCS_NORM);
216
217 {
218 PALLOC ( rr_abort_req, RR_ABORT_REQ); /* T_RR_ABORT_REQ */
219 rr_abort_req->abcs = abcs;
220 PSENDX (RR, rr_abort_req);
221 }
222 }
223
224
225 /*
226 +--------------------------------------------------------------------+
227 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
228 | STATE : code ROUTINE : mm_attach_loc_upd |
229 +--------------------------------------------------------------------+
230
231 PURPOSE : This function starts an IMSI ATTACH location update.
232
233 */
234
235 GLOBAL void mm_attach_loc_upd (void)
236 {
237 GET_INSTANCE_DATA;
238 TRACE_FUNCTION ("mm_attach_loc_upd ()");
239
240 if (mm_lup_allowed_by_gmm())
241 {
242 mm_start_loc_upd (IMSI_ATTACH_LUP);
243 }
244 else
245 {
246 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
247 }
248 }
249
250
251 /*
252 +--------------------------------------------------------------------+
253 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
254 | STATE : code ROUTINE : mm_normal_loc_upd |
255 +--------------------------------------------------------------------+
256
257 PURPOSE : This function starts a normal location update procedure.
258
259 */
260
261 GLOBAL void mm_normal_loc_upd (void)
262 {
263 GET_INSTANCE_DATA;
264 TRACE_FUNCTION ("mm_normal_loc_upd ()");
265
266 if (mm_lup_allowed_by_gmm())
267 {
268 mm_start_loc_upd (NORMAL_LUP);
269 }
270 else
271 {
272 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
273 }
274 }
275
276
277 /*
278 +--------------------------------------------------------------------+
279 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
280 | STATE : code ROUTINE : mm_periodic_loc_upd |
281 +--------------------------------------------------------------------+
282
283 PURPOSE : This function starts a periodic location update.
284
285 */
286
287 GLOBAL void mm_periodic_loc_upd (void)
288 {
289 GET_INSTANCE_DATA;
290 TRACE_FUNCTION ("mm_periodic_loc_upd ()");
291 if (mm_lup_allowed_by_gmm())
292 {
293 mm_start_loc_upd (PERIODIC_LUP);
294 }
295 else
296 {
297 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
298 }
299 }
300
301
302 /*
303 +--------------------------------------------------------------------+
304 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
305 | STATE : code ROUTINE : mm_build_auth_res |
306 +--------------------------------------------------------------------+
307
308 PURPOSE : In this function the AUTHENTICATION RESPONSE message is
309 built.
310
311 */
312
313 GLOBAL void mm_build_auth_res (T_SIM_AUTHENTICATION_CNF *sim_auth_cnf,
314 T_U_AUTH_RES *auth_res)
315 {
316 TRACE_FUNCTION ("mm_build_auth_res ()");
317 auth_res->msg_type = U_AUTH_RES;
318 auth_res->auth_sres.l_auth_sres = MAX_SRES << 3;
319 auth_res->auth_sres.o_auth_sres = 0;
320 memcpy (auth_res->auth_sres.b_auth_sres, sim_auth_cnf->sres, MAX_SRES);
321 }
322
323 /*
324 +--------------------------------------------------------------------+
325 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
326 | STATE : code ROUTINE : mm_build_ident_res |
327 +--------------------------------------------------------------------+
328
329 PURPOSE : In this function the IDENTITY RESPONSE message is built.
330
331 */
332
333 GLOBAL void mm_build_ident_res (UBYTE id_type,
334 T_U_IDENT_RES *ident_res)
335 {
336 TRACE_FUNCTION ("mm_build_ident_res ()");
337 ident_res->msg_type = U_IDENT_RES;
338 mm_fill_identity (&ident_res->mob_id, id_type);
339 }
340
341 /*
342 +--------------------------------------------------------------------+
343 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
344 | STATE : code ROUTINE : mm_build_mm_status |
345 +--------------------------------------------------------------------+
346
347 PURPOSE : In this function the MM STATUS message is built.
348
349 */
350
351 GLOBAL void mm_build_mm_status (UBYTE cause,
352 T_B_MM_STATUS *mm_status)
353 {
354 TRACE_FUNCTION ("mm_build_mm_status ()");
355 mm_status->msg_type = B_MM_STATUS;
356 mm_status->rej_cause = cause;
357 }
358
359 /*
360 +--------------------------------------------------------------------+
361 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
362 | STATE : code ROUTINE : mm_build_rr_sync_req_cause |
363 +--------------------------------------------------------------------+
364
365 PURPOSE : This function is used to synchronize RR information
366 with changed information in MM.
367 The function mm_build_rr_sync_req_cause() is used especially
368 if the registration has failed for some reason, e.g.
369 authentication failure. Cause value is given,
370 ciphering information and tmsi are not present if this
371 function is called.
372
373 */
374
375 GLOBAL void mm_build_rr_sync_req_cause (USHORT cause)
376 {
377 GET_INSTANCE_DATA;
378 PALLOC (rr_sync_req, RR_SYNC_REQ); /* T_RR_SYNC_REQ */
379
380 TRACE_FUNCTION ("mm_build_rr_sync_req_cause ()");
381
382 rr_sync_req->op.v_op = V_OP_NOT_PRES;
383 rr_sync_req->cksn = CKSN_NOT_PRES;
384 rr_sync_req->kcv.v_kc = V_KC_NOT_PRES;
385 rr_sync_req->tmsi_struct.v_mid = V_MID_NOT_PRES;
386 rr_sync_req->plmn.v_plmn = V_PLMN_NOT_PRES;
387 rr_sync_req->synccs = cause;
388 rr_sync_req->accc = mm_data->reg.acc_class;
389 rr_sync_req->eq_plmn_list.v_eq_plmn = FALSE;
390
391 TRACE_EVENT_P1 ("sync_cause = %04x", cause);
392
393 switch (cause)
394 {
395 case SYNCCS_LAI_ALLOW:
396 case SYNCCS_LAI_NOT_ALLOW:
397 case SYNCCS_LAI_NOT_ALLOW_FOR_ROAMING:
398 rr_sync_req->plmn.v_plmn = V_PLMN_PRES;
399 memcpy (rr_sync_req->plmn.mcc, mm_data->mm.lai.mcc, SIZE_MCC);
400 memcpy (rr_sync_req->plmn.mnc, mm_data->mm.lai.mnc, SIZE_MNC);
401 rr_sync_req->lac = mm_data->mm.lai.lac;
402 break;
403 case SYNCCS_EPLMN_LIST:
404 rr_sync_req->eq_plmn_list.v_eq_plmn = TRUE;
405 memcpy(&rr_sync_req->eq_plmn_list.eq_plmn,
406 &mm_data->reg.eqv_plmns.eqv_plmn_list,
407 EPLMNLIST_SIZE*UBYTES_PER_PLMN);
408 break;
409 default: /* eg. SYNCCS_ACCC */
410 break;
411 }
412 PSENDX (RR, rr_sync_req);
413 }
414
415 /*
416 +--------------------------------------------------------------------+
417 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
418 | STATE : code ROUTINE : mm_build_rr_sync_req |
419 +--------------------------------------------------------------------+
420
421 PURPOSE : The function unifies the functions mm_build_rr_sync_req_mode()
422 and mm_build_rr_sync_req_ciph() and is used to synchronize
423 RR information with changed information in MM. The parameter
424 'ciph' decides whether the ciphering parameters are to be
425 set.
426 */
427
428 GLOBAL void mm_build_rr_sync_req (T_MSG_TYPE ciph)
429 {
430 GET_INSTANCE_DATA;
431 PALLOC (rr_sync_req, RR_SYNC_REQ); /* T_RR_SYNC_REQ */
432
433 TRACE_FUNCTION ("mm_build_rr_sync_req()");
434 rr_sync_req->tmsi_struct.v_mid = V_MID_NOT_PRES;
435 rr_sync_req->synccs = NOT_PRESENT_16BIT;
436 rr_sync_req->accc = mm_data->reg.acc_class;
437 rr_sync_req->plmn.v_plmn = V_PLMN_NOT_PRES;
438
439 if( ciph EQ MSG_MM_CIPH)
440 {
441 rr_sync_req->op.v_op = V_OP_NOT_PRES;
442 rr_sync_req->cksn = mm_data->reg.cksn;
443 rr_sync_req->kcv.v_kc = V_KC_PRES;
444 memcpy (rr_sync_req->kcv.kc, mm_data->reg.kc, MAX_KC);
445 }
446 else
447 {
448 memcpy (&rr_sync_req->op, &mm_data->reg.op, sizeof (T_op));
449 rr_sync_req->cksn = NOT_PRESENT_8BIT;
450 rr_sync_req->kcv.v_kc = V_KC_NOT_PRES;
451 }
452 PSENDX (RR, rr_sync_req);
453 }
454
455
456 /*
457 +--------------------------------------------------------------------+
458 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
459 | STATE : code ROUTINE : mm_build_rr_sync_req_tmsi |
460 +--------------------------------------------------------------------+
461
462 PURPOSE : This function is used to synchronize RR information
463 with changed information in MM.
464 The function mm_build_rr_sync_req_tmsi() is used especially
465 to inform RR about a change in the ciphering parameter
466 tmsi.
467
468 */
469
470 GLOBAL void mm_build_rr_sync_req_tmsi (void)
471 {
472 GET_INSTANCE_DATA;
473 PALLOC (rr_sync_req, RR_SYNC_REQ); /* T_RR_SYNC_REQ */
474
475 TRACE_FUNCTION ("mm_build_rr_sync_req_tmsi ()");
476
477 rr_sync_req->op.v_op = V_OP_NOT_PRES;
478 rr_sync_req->cksn = CKSN_RES;
479 rr_sync_req->kcv.v_kc = V_KC_NOT_PRES;
480 rr_sync_req->plmn.v_plmn = V_PLMN_NOT_PRES;
481 rr_sync_req->synccs = NOT_PRESENT_16BIT;
482 rr_sync_req->accc = mm_data->reg.acc_class;
483
484 memset (rr_sync_req->tmsi_struct.id, 0,
485 sizeof (rr_sync_req->tmsi_struct.id)); /* IMSI digits */
486 rr_sync_req->tmsi_struct.v_mid = V_MID_PRES;
487 rr_sync_req->tmsi_struct.id_type = TYPE_TMSI;
488 rr_sync_req->tmsi_struct.tmsi_dig = mm_data->reg.tmsi;
489
490 PSENDX (RR, rr_sync_req);
491 }
492
493
494 /*
495 +--------------------------------------------------------------------+
496 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
497 | STATE : code ROUTINE : mm_build_rr_sync_hplmn_req |
498 +--------------------------------------------------------------------+
499
500 PURPOSE : This function is used to synchronize RR information
501 with changed AHPLMN in MM.
502 The function mm_build_rr_sync_hplmn_req() is used especially
503 to inform RR about the change of the status of RPLMN to AHPLMN.
504
505 */
506
507 GLOBAL void mm_build_rr_sync_hplmn_req (void)
508 {
509 GET_INSTANCE_DATA;
510
511 PALLOC (rr_sync_hplmn_req, RR_SYNC_HPLMN_REQ); /* T_RR_SYNC_HPLMN_REQ */
512
513 TRACE_FUNCTION ("mm_build_rr_sync_hplmn_req()");
514
515 rr_sync_hplmn_req->plmn.v_plmn = mm_data->reg.acting_hplmn.v_plmn;
516 memcpy(&rr_sync_hplmn_req->plmn.mcc, &mm_data->reg.acting_hplmn.mcc, SIZE_MCC);
517 memcpy(&rr_sync_hplmn_req->plmn.mnc, &mm_data->reg.acting_hplmn.mnc, SIZE_MNC);
518
519 PSENDX(RR,rr_sync_hplmn_req);
520 }
521
522
523 /*
524 +--------------------------------------------------------------------+
525 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
526 | STATE : code ROUTINE : mm_check_critical_error |
527 +--------------------------------------------------------------------+
528
529 PURPOSE : This function checks wheter a critical error has been
530 detected in the air message. Critical errors which prevent
531 the treatment of an air message are
532 - invalid Message ID
533 - mandatory IE missing
534 - IE coded as comprehension required missing
535 */
536
537 GLOBAL BOOL mm_check_critical_error (void)
538 {
539 GET_INSTANCE_DATA;
540 TRACE_FUNCTION ("mm_check_critical_error ()");
541 if (mm_data->error EQ RC_INVALID_MAND_MESSAGE OR
542 mm_data->error EQ RC_MESSAGE_TYPE_NOT_IMPLEM OR
543 mm_data->error EQ RC_CONDITIONAL_IE OR
544 mm_data->error EQ RC_SERVICE_NOT_SUPPORTED OR
545 mm_data->error EQ RC_MESSAGE_INCOMPAT OR
546 mm_data->error EQ RC_MESSAGE_TYPE_INCOMPAT)
547 {
548 return (TRUE);
549 }
550 return (FALSE);
551 }
552
553
554 /*
555 +--------------------------------------------------------------------+
556 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
557 | STATE : code ROUTINE : mm_send_status |
558 +--------------------------------------------------------------------+
559
560 PURPOSE : This function checks wheter a critical error has been
561 detected requiring
562 - to abort the AIM processing and
563 - to send a STATUS message.
564 The error can be detected by CCD or within the AIM processing itself.
565 If any, the message is send, using the value found in mm_data->error as cause.
566 */
567
568 GLOBAL BOOL mm_send_status_on_error (void)
569 {
570 GET_INSTANCE_DATA;
571 TRACE_FUNCTION ("mm_send_status_on_error ()");
572 if (mm_check_critical_error())
573 {
574
575 /* Implements Measure 29 and streamline encoding */
576 mm_send_status(mm_data->error);
577 mm_for_set_error (0);
578 return (TRUE);
579 }
580 return (FALSE);
581 }
582
583
584 /*
585 +--------------------------------------------------------------------+
586 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
587 | STATE : code ROUTINE : mm_check_error_flag |
588 +--------------------------------------------------------------------+
589
590 PURPOSE : This function checks wheter a critical error has been
591 detected in the air message. Critical errors which prevent
592 the treatment of an air message are all errors except
593 an error in an optional information element.
594 [In calls of this function it is checked whether the
595 error is an RC_INVALID_MAND_MESSAGE, only this case is
596 treated as error in the caller's code. The code could be
597 simplified here if mm_check_error_flag() was a function
598 returning a BOOLEAN, indicating whether the message is valid
599 or not. This is done this way in the CC entitity.]
600
601 */
602
603 GLOBAL void mm_check_error_flag (void)
604 {
605 GET_INSTANCE_DATA;
606 TRACE_FUNCTION ("mm_check_error_flag ()");
607 if (mm_data->error NEQ 0 AND
608 mm_data->error NEQ OPTIONAL_INFO_ERROR)
609 {
610 /* Implements Measure 29 and streamline encoding */
611 mm_send_status(mm_data->error);
612 }
613 }
614
615 /*
616 +--------------------------------------------------------------------+
617 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
618 | STATE : code ROUTINE : mm_clear_mob_ident |
619 +--------------------------------------------------------------------+
620
621 PURPOSE : This function zeroes out the mobile identity.
622
623
624 */
625
626 GLOBAL void mm_clear_mob_ident (T_imsi_struct*mob_ident)
627 {
628 TRACE_FUNCTION ("mm_clear_mob_ident ()");
629
630 memset (mob_ident, 0, sizeof (T_imsi_struct));
631 }
632
633 /*
634 +--------------------------------------------------------------------+
635 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
636 | STATE : code ROUTINE : mm_clear_reg_data |
637 +--------------------------------------------------------------------+
638
639 PURPOSE : This function clears some variables in the registration
640 data. This is done in a way that the SIM data is not lost,
641 the SIM data is only disabled by setting a software flag
642 indicating MM shall not use the SIM data until it is
643 requested to do so by upper layers.
644
645 */
646
647 GLOBAL void mm_clear_reg_data (void)
648 {
649 GET_INSTANCE_DATA;
650 TRACE_FUNCTION ("mm_clear_reg_data ()");
651
652 mm_data->reg.op.func = FUNC_LIM_SERV_ST_SRCH;
653 mm_data->reg.op.sim_ins = SIM_NO_INSRT;
654 mm_data->first_attach = TRUE;
655 }
656
657 /*
658 +--------------------------------------------------------------------+
659 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
660 | STATE : code ROUTINE : mm_copy_rr_act_cnf_data |
661 +--------------------------------------------------------------------+
662
663 PURPOSE : This function copies the data delivered by RR_ACTIVATE_CNF
664 or RR_ACTIVATE_IND into the internal MM data structures.
665
666 */
667
668 GLOBAL void mm_copy_rr_act_cnf_data (T_RR_ACTIVATE_CNF *rr_activate_cnf)
669 {
670 GET_INSTANCE_DATA;
671 TRACE_FUNCTION ("mm_copy_rr_act_cnf_data ()");
672
673 mm_data->mm.mm_info = rr_activate_cnf->mm_info; /* Stucture copy */
674 memcpy (mm_data->mm.lai.mcc, rr_activate_cnf->plmn.mcc, SIZE_MCC);
675 memcpy (mm_data->mm.lai.mnc, rr_activate_cnf->plmn.mnc, SIZE_MNC);
676 mm_data->mm.lai.lac = rr_activate_cnf->lac;
677 mm_data->mm.cid = rr_activate_cnf->cid;
678
679 EM_CELL_SELECTION_RESELECTION;
680
681 #ifdef GPRS
682 mm_data->mm.gprs_indication= rr_activate_cnf->gprs_indication;
683 #endif /* GPRS */
684
685 // Write-only variable, eliminated HM 20.07.00
686 // mm_data->mm.lac = rr_activate_cnf->lac;
687
688 /*
689 * Until now we have only knowledge that chinese networks
690 * seem to have special problems we have to deal with,
691 * but maybe other countries have these special problems, too.
692 */
693 poor_quality_network =
694 ((rr_activate_cnf->plmn.mcc[0] EQ 4) AND
695 (rr_activate_cnf->plmn.mcc[1] EQ 6) AND
696 (rr_activate_cnf->plmn.mcc[2] EQ 0));
697 }
698
699
700 /*
701 +--------------------------------------------------------------------+
702 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
703 | STATE : code ROUTINE : mm_count_connections |
704 +--------------------------------------------------------------------+
705
706 PURPOSE : Count the number of connections which connection state
707 equals to the parameter conn_type. In case conn_type
708 is CM_NOT_IDLE, all connections not idle are counted.
709
710 */
711
712 GLOBAL SHORT mm_count_connections (UBYTE conn_type)
713 {
714 GET_INSTANCE_DATA;
715 UBYTE cm;
716 UBYTE ti;
717 SHORT count = 0;
718
719 TRACE_FUNCTION ("mm_count_connections ()");
720
721 for (cm = 0; cm < NUM_OF_CM_ENT; cm++)
722 {
723 for (ti = 0; ti < NUM_OF_CONN_PER_CM_ENT; ti++)
724 {
725 if (((conn_type EQ CM_NOT_IDLE) AND (CMSTATE(cm, ti) NEQ CM_IDLE)) OR
726 (CMSTATE(cm, ti) EQ conn_type))
727 {
728 #if defined (WIN32)
729 (void)CM_GET_STATE(cm, ti);
730 #endif
731 count++;
732 }
733 }
734 }
735 return (count);
736 }
737
738 /*
739 +--------------------------------------------------------------------+
740 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
741 | STATE : code ROUTINE : mm_create_est_message |
742 +--------------------------------------------------------------------+
743
744 PURPOSE : This functinon creates the establishment message,
745 either for MM services or for CM services.
746 If the entitity requiring service is a CM component,
747 the CM entitity will be remembered in mm_data->last_comp.
748
749 */
750
751 GLOBAL void mm_create_est_message (USHORT est_cause,
752 UBYTE service,
753 UBYTE ti,
754 USHORT *bit_size_message)
755 {
756 GET_INSTANCE_DATA;
757 TRACE_FUNCTION ("mm_create_est_message ()");
758
759 TRACE_EVENT_P1 (" ESTCS = %x", est_cause);
760 TRACE_EVENT_P7 (" REG: MCC=%X%X%X MNC=%X%X%X LAC=%04X",
761 mm_data->reg.lai.mcc[0],
762 mm_data->reg.lai.mcc[1],
763 mm_data->reg.lai.mcc[2],
764 mm_data->reg.lai.mnc[0],
765 mm_data->reg.lai.mnc[1],
766 mm_data->reg.lai.mnc[2],
767 mm_data->reg.lai.lac);
768 TRACE_EVENT_P7 (" MM: MCC=%X%X%X MNC=%X%X%X LAC=%04X",
769 mm_data->mm.lai.mcc[0],
770 mm_data->mm.lai.mcc[1],
771 mm_data->mm.lai.mcc[2],
772 mm_data->mm.lai.mnc[0],
773 mm_data->mm.lai.mnc[1],
774 mm_data->mm.lai.mnc[2],
775 mm_data->mm.lai.lac);
776
777 if (est_cause NEQ ESTCS_SERV_REQ_BY_MM)
778 {
779 UBYTE comp;
780
781 /*
782 * Set the CM component requiring CM service
783 */
784 switch (service)
785 {
786 case CALL_SERVICE:
787 case EMERGENCY_SERVICE:
788 comp = CC_COMP;
789 break;
790
791 case SS_SERVICE:
792 comp = SS_COMP;
793 break;
794
795 case SMS_SERVICE:
796 comp = SMS_COMP;
797 break;
798
799 default: /* Request for MM service */
800 TRACE_ERROR ("Illegal service");
801 comp = CC_COMP; /* Just to say something */
802 break;
803 }
804
805 mm_data->pend_conn.ti = ti;
806 mm_data->pend_conn.comp = comp;
807 mm_data->pend_conn.service = service;
808 mm_data->pend_conn.cause = est_cause;
809 if (est_cause EQ ESTCS_CAL_REEST)
810 {
811 CM_SET_STATE (comp, ti, CM_REEST_PENDING);
812 }
813 else
814 {
815 CM_SET_STATE (comp, ti, CM_PENDING);
816 }
817 }
818
819 mm_data->rej_cause = 0;
820
821 switch (est_cause)
822 {
823 case ESTCS_CAL_REEST:
824 {
825 MCAST (cm_reestab_req, U_CM_REESTAB_REQ); /* T_U_CM_REESTAB_REQ */
826
827 *bit_size_message = BSIZE_U_CM_REESTAB_REQ;
828 cm_reestab_req->msg_type = U_CM_REESTAB_REQ;
829 cm_reestab_req->ciph_key_num.key_seq = mm_data->reg.cksn;
830 cm_reestab_req->v_loc_area_ident = FALSE;
831
832 csf_read_mobile_class_2 (&cm_reestab_req->mob_class_2);
833 cm_reestab_req->mob_class_2.rf_pow_cap = mm_data->rf_power;
834
835 if (mm_fill_ident_for_est (&cm_reestab_req->mob_id) EQ ID_TYPE_TMSI)
836 {
837 /* TMSI used. Include also location area to make this unambiguous */
838 cm_reestab_req->v_loc_area_ident = TRUE;
839 cm_reestab_req->loc_area_ident = mm_data->reg.lai; /* Struct copy */
840 }
841 }
842 break;
843
844 case ESTCS_SERV_REQ_BY_MM:
845 {
846 MCAST (loc_upd_req, U_LOC_UPD_REQ); /* T_U_LOC_UPD_REQ */
847
848 *bit_size_message = BSIZE_U_LOC_UPD_REQ;
849 loc_upd_req->msg_type = U_LOC_UPD_REQ;
850 loc_upd_req->loc_upd_type = mm_data->loc_upd_type; /* Struct copy */
851 loc_upd_req->ciph_key_num.key_seq = mm_data->reg.cksn;
852 loc_upd_req->loc_area_ident = mm_data->reg.lai; /* Struct copy */
853 if (loc_upd_req->loc_area_ident.mnc[2] EQ 0xF)
854 loc_upd_req->loc_area_ident.c_mnc = 2;
855 csf_read_mobile_class_1 (&loc_upd_req->mob_class_1);
856 loc_upd_req->mob_class_1.rf_pow_cap = mm_data->rf_power;
857 mm_fill_ident_for_est (&loc_upd_req->mob_id);
858 }
859 break;
860
861 default:
862 {
863 MCAST (cm_serv_req, U_CM_SERV_REQ); /* T_U_CM_SERV_REQ */
864
865 EM_CM_SERVICE_REQUESTED;
866
867 #if defined (WIN32)
868 {
869 char buf [40];
870 sprintf (buf, "detected power = %d", mm_data->rf_power);
871 TRACE_FUNCTION (buf);
872 }
873 #endif
874
875 *bit_size_message = BSIZE_U_CM_SERV_REQ;
876 cm_serv_req->msg_type = U_CM_SERV_REQ;
877 cm_serv_req->cm_serv_type = service;
878 cm_serv_req->ciph_key_num.key_seq = mm_data->reg.cksn;
879
880 csf_read_mobile_class_2 (&cm_serv_req->mob_class_2);
881 cm_serv_req->mob_class_2.rf_pow_cap = mm_data->rf_power;
882
883 mm_fill_ident_for_est (&cm_serv_req->mob_id);
884 }
885 break;
886 }
887 }
888 /*
889 +--------------------------------------------------------------------+
890 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
891 | STATE : code ROUTINE : mm_create_imsi_detach_message |
892 +--------------------------------------------------------------------+
893
894 PURPOSE : This function creates the IMSI DETACH message. This may
895 either be forwarded to the network by the means of
896 RR_ESTABLISH_REQ or RR_DATA_REQ if a network connection
897 already exists.
898
899 */
900
901 GLOBAL void mm_create_imsi_detach_message (void)
902 {
903 GET_INSTANCE_DATA;
904 MCAST (imsi_detach, U_IMSI_DETACH_IND);
905
906 TRACE_FUNCTION ("mm_create_imsi_detach_message ()");
907
908 imsi_detach->msg_type = U_IMSI_DETACH_IND;
909 csf_read_mobile_class_1 (&imsi_detach->mob_class_1);
910 imsi_detach->mob_class_1.rf_pow_cap = mm_data->rf_power;
911 mm_fill_ident_for_est (&imsi_detach->mob_id);
912
913 EM_IMSI_DETACH;
914 }
915
916 /*
917 +--------------------------------------------------------------------+
918 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
919 | STATE : code ROUTINE : mm_delete_entry |
920 +--------------------------------------------------------------------+
921
922 PURPOSE : The purpose of this function is to delete a stored entry
923 previously written by the mm_write_entry() function.
924 There are some types of entries which may be stored in
925 the T_STORE data structure.
926 - Establish attempts by the CM sublayer (MMXX_ESTABLISH_REQ)
927 - Net requests by MMI (MMXXX_NET_REQ, AT+COPS=?)
928 - Expired timers (TIMEOUT)
929 - primitives incoming
930 In case the content type is set to PRIMITIVE_ENTRY currently
931 nothing is done, because no delete case was necessary so far.
932
933 */
934
935 GLOBAL void mm_delete_entry (UBYTE comp, UBYTE ti)
936 {
937 GET_INSTANCE_DATA;
938 USHORT i;
939 USHORT j;
940
941 TRACE_FUNCTION ("mm_delete_entry ()");
942
943 /*
944 * Find stored entry in table
945 */
946 for (i = 0; i < MAX_STORE_ENTRIES; i++)
947 {
948 if (mm_data->store[i].content_type EQ EVENT_ENTRY)
949 {
950
951 if (mm_data->store[i].use NEQ ENTRY_FREE AND
952 mm_data->store[i].content.event.comp EQ comp AND
953 mm_data->store[i].content.event.ti EQ ti)
954 {
955 TRACE_EVENT_P2 ("Delete entry: comp=%d, ti=%d", comp, ti);
956
957 for (j = i; j < MAX_STORE_ENTRIES - 1; j++)
958 {
959 mm_data->store[j] = mm_data->store[j + 1]; /* Struct copy */
960 }
961 mm_data->store[MAX_STORE_ENTRIES - 1].use = ENTRY_FREE;
962 mm_data->store[MAX_STORE_ENTRIES - 1].content_type = NO_ENTRY;
963
964 if (comp < NUM_OF_CM_ENT)
965 {
966 /* Establish request for any CM entity has been deleted */
967 CM_SET_STATE(comp, ti, CM_IDLE);
968 }
969 return;
970 } /*IF comp ti*/
971 } /*IF content_type*/
972 } /*FOR*/
973 }
974
975 /*
976 +--------------------------------------------------------------------+
977 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
978 | STATE : code ROUTINE : mm_set_follow_on_request |
979 +--------------------------------------------------------------------+
980
981 PURPOSE : set the follow on request if at least one connection
982 attempt is stored.
983
984 */
985
986 GLOBAL BOOL mm_set_follow_on_request (void)
987 {
988 GET_INSTANCE_DATA;
989 TRACE_FUNCTION ("mm_set_follow_on_request()");
990
991 if (mm_count_connections (CM_STORE) NEQ 0 AND mm_cm_est_allowed())
992 {
993 mm_data->loc_upd_type.follow = FOR_PENDING_YES;
994 return TRUE;
995 }
996 else
997 {
998 mm_data->loc_upd_type.follow = FOR_PENDING_NO;
999 return FALSE;
1000 }
1001 }
1002
1003
1004 /*
1005 +--------------------------------------------------------------------+
1006 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1007 | STATE : code ROUTINE : mm_init |
1008 +--------------------------------------------------------------------+
1009
1010 PURPOSE : This function initializes the MM data structures.
1011
1012 */
1013
1014 GLOBAL void mm_init (void)
1015 {
1016 GET_INSTANCE_DATA;
1017 TRACE_FUNCTION ("mm_init()");
1018
1019 TIMERSTOP (T_REGISTRATION);
1020 TIMERSTOP (T3210);
1021 TIMERSTOP (T3211);
1022 TIMERSTOP (T3212);
1023 mm_data->t3212_timeout = FALSE;
1024 TIMERSTOP (T3213);
1025 mm_data->t3213_restart = 0;
1026 TIMERSTOP (T3220);
1027 TIMERSTOP (T3230);
1028 TIMERSTOP (T3240);
1029 #ifdef REL99
1030 TIMERSTOP (T3241);
1031 #endif
1032
1033 memset (mm_data, 0, sizeof (T_MM_DATA));
1034 mm_data->limited_cause = MMCS_SIM_REMOVED; /* MMCS_SIM_INVAL_NOSIM */
1035
1036 mm_data->last_auth_req_id = NOT_PRESENT_8BIT;
1037 mm_data->first_attach = TRUE;
1038 mm_data->first_attach_mem = FALSE;
1039
1040 mm_data->t3212_cfg_counter = 0;
1041 mm_data->idle_entry = RRCS_INT_NOT_PRESENT;
1042 mm_data->ciphering_on = CIPH_NOT_PRES; /* Initialize ciphering indicator */
1043
1044
1045 mm_data->reg.length_mnc = 2;
1046 mm_data->net_search_count = 0;
1047 mm_data->ef_indicator = 0; /* Initialize for EF indication to SIM */
1048 mm_data->reg.is_cingular_sim = FALSE; /*This flag is specially for cingular n/w*/
1049
1050 reg_init ();
1051
1052 poor_quality_network = FALSE;
1053
1054 #ifdef GPRS
1055 SET_STATE (STATE_REG_TYPE, REG_GPRS_INACTIVE);
1056 SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_IDLE);
1057 #endif /* GPRS */
1058 }
1059
1060
1061 /*
1062 +--------------------------------------------------------------------+
1063 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1064 | STATE : code ROUTINE : mm_calculate_digits |
1065 +--------------------------------------------------------------------+
1066
1067 PURPOSE : This function calculates the length of the IMSI.
1068 (The digits delivered to this function are the digits of
1069 an IMSI, but this doesn't become obvious from the function's
1070 or parameter's name.)
1071
1072 */
1073
1074 GLOBAL UBYTE mm_calculate_digits (const UBYTE *digits)
1075 {
1076 UBYTE i = 0;
1077
1078 TRACE_FUNCTION ("mm_calculate_digits()");
1079
1080 while (digits[i] < 0x0A AND i < 16)
1081 i++;
1082
1083 return i;
1084 }
1085
1086
1087 /*
1088 +--------------------------------------------------------------------+
1089 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1090 | STATE : code ROUTINE : mm_loc_upd_rej |
1091 +--------------------------------------------------------------------+
1092
1093 PURPOSE : This function is called if LOCATION UPDATING REJECT has
1094 been received and then after the RR connection has been
1095 released or aborted, after leaving MM_LUP_REJECTED state.
1096 It is also used if MMGMM_ATTACH_REJ_REQ is received by GMM.
1097 It is also used if MMGMM_NREG_REQ is received with
1098 cs EQ CS_DISABLE and certain mmgmm_error_cause values.
1099 Maybe the name "mm_network_rejected()" would be a
1100 better name for the function now.
1101
1102 NOTE: For MM's own location updating, every non-defined
1103 cause is mapped into RC_SERVICE_ORDER (0x22).
1104 If the network sends some GPRS only defined cause
1105 by means of the LOCATION UPDATING REJECT message,
1106 we catch this in the default.
1107
1108 */
1109
1110 GLOBAL void mm_loc_upd_rej (void)
1111 {
1112 GET_INSTANCE_DATA;
1113 T_plmn hplmn;
1114
1115 TRACE_FUNCTION ("mm_loc_upd_rej ()");
1116
1117 reg_extract_hplmn (&hplmn);
1118
1119 TRACE_EVENT_P1 ("rej_cause = %04X", mm_data->rej_cause);
1120
1121 /*
1122 * T3212 is stopped if a LOCATION UPDATING ACCEPT or
1123 * LOCATION UPDATING REJECT message is received.
1124 * [GSM 04.08 subclause 4.4.2]
1125 * Exception: MMGMM_ERRCS_GPRS_NOT_ALLOWED_IN_PLMN as this shall not
1126 * have any influence on T3212.
1127 */
1128 #ifdef GPRS
1129 if (mm_data->rej_cause NEQ GMMCS_GPRS_NOT_ALLOWED_IN_PLMN)
1130 #endif /* #ifdef GPRS */
1131 {
1132 TIMERSTOP (T3212);
1133 mm_data->t3212_timeout = FALSE;
1134 }
1135
1136 switch (mm_data->rej_cause)
1137 {
1138 case MMCS_PLMN_NOT_ALLOWED: /* #11 + Ofs */
1139 #ifdef GPRS
1140 case GMMCS_PLMN_NOT_ALLOWED:
1141 #endif /* #ifdef GPRS */
1142 mm_data->attempt_cnt = 0;
1143 mm_data->loc_upd_type.lut = NOT_RUNNING;
1144 if (reg_plmn_equal_hplmn (&mm_data->reg.actual_plmn) EQ FALSE)
1145 {
1146 /*
1147 * The PLMN is only added to forbidden list if not the HPLMN.
1148 * An internal error of the HPLMN would otherwise invalidate
1149 * the SIM for the HPLMN even after SIM removal/SIM insertion.
1150 */
1151 reg_plmn_add_bad (mm_data->reg.forb_plmn,
1152 MAX_FORB_PLMN_ID,
1153 &mm_data->reg.actual_plmn);
1154 mm_build_rr_sync_req_cause (SYNCCS_LIMITED_SERVICE);
1155 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1156
1157 /* Delete EPLMN List */
1158 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1159 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1160 #ifdef REL99
1161 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1162 #else
1163 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1164 #endif
1165 /* Set the new MM state before calling reg_mm_failure() */
1166 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
1167 reg_mm_failure (FORB_PLMN_INCLUDED);
1168 }
1169 else
1170 {
1171 /*
1172 * Cause #11 for the HPLMN. This is a network failure.
1173 */
1174
1175 // Call mm_lup_restart() instead? Makes no sense this way...
1176
1177 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1178
1179 /* Delete EPLMN List */
1180 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1181 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1182
1183 #ifdef REL99
1184 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1185 #else
1186 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1187 #endif
1188 /* Set the new MM state before calling reg_mm_failure() */
1189 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
1190 reg_mm_failure (FORB_PLMN_NOT_INCLUDED);
1191 }
1192
1193 USE_STORED_ENTRIES();
1194 break;
1195
1196 case MMCS_LA_NOT_ALLOWED: /* #12 + Ofs */
1197 #ifdef GPRS
1198 case GMMCS_LA_NOT_ALLOWED:
1199 #endif /* #ifdef GPRS */
1200 /*
1201 * There is no list of "forbidden location areas for regional
1202 * provision of service" supported by G23. Compare this with the
1203 * requirements of GSM 04.08 subclause 4.4.4.7.
1204 * The non-implementation of this list should not cause any
1205 * harm for cause #12.
1206 */
1207 mm_data->attempt_cnt = 0;
1208 mm_build_rr_sync_req_cause (SYNCCS_LAI_NOT_ALLOW);
1209 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1210
1211 mm_data->loc_upd_type.lut = NOT_RUNNING;
1212 #ifdef REL99
1213 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1214 #else
1215 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1216 #endif
1217 /* Set the new MM state before calling reg_mm_failure() */
1218 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
1219 reg_mm_failure (FORB_PLMN_NOT_INCLUDED);
1220 USE_STORED_ENTRIES();
1221 break;
1222
1223
1224 #ifdef GPRS
1225 case GMMCS_ROAMING_NOT_ALLOWED:
1226 #ifdef REL99
1227 /* Invalidate the TMSI, CKSN, KC in RR */
1228 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1229 case GMMCS_ROAMING_NOT_ALLOWED_WITH_RAU_REJ: /* #13 + Ofs GMM sent for GPRS RAU rejected case*/
1230 /* GMM sent cause value 13 becauseof 'Normal/periodic RAU Rejected' or
1231 * 'Combined RAU Rejected by the network'.*/
1232 /*FALLTHROUGH*/
1233 #endif
1234 /*FALLTHROUGH*/
1235 //lint -fallthrough
1236 #endif /* #ifdef GPRS */
1237 case MMCS_ROAMING_NOT_ALLOWED: /* #13 + Ofs */
1238 /* MM received cause value 13 because of 'LU rejected' by the network*/
1239 /*
1240 * For the cause 13 handling as per the specification 24.008 v3.15.0,
1241 * If Cause value 13 received because of 'LU rejected' or 'Normal/periodic RAU
1242 * Rejected' or 'Combined RAU Rejected by the network' MM will
1243 * - store the LAI in the list of "forbidden location areas for roaming".
1244 * - set the update status to U3 ROAMING NOT ALLOWED and shall reset the
1245 * location update attempt counter
1246 * - The mobile station shall perform a PLMN selection instead of a cell
1247 * selection when back to the MM IDLE state according to 3GPP TS 23.122.
1248 *
1249 * If cause value 13 received because of 'GPRS attach rejected' or 'Combined
1250 * GPRS rejected' or 'Network initiated GPRS detach' MM will
1251 * - Do the above steps
1252 * - Additionally MM will any TMSI and ciphering key sequence number.
1253 */
1254 mm_data->attempt_cnt = 0;
1255 mm_data->loc_upd_type.lut = NOT_RUNNING;
1256
1257 /* Remember the PLMN which sent this reject cause, it's low prio now */
1258 mm_data->reg.low_prio_plmn = mm_data->reg.actual_plmn; /* Struct copy */
1259
1260 /* Enter the location area in RR into the list of
1261 * "forbidden location areas for roaming" for reject cause #13.
1262 * This list is maintained in RR */
1263 mm_build_rr_sync_req_cause (SYNCCS_LAI_NOT_ALLOW_FOR_ROAMING);
1264
1265 /* Inform RR about the limited service condition */
1266 mm_build_rr_sync_req_cause (SYNCCS_LIMITED_SERVICE);
1267
1268 /* As RR_SYNC_REQ (SYNCCS_LIMITED_SERVICE) clears the PLMN in RR,
1269 * we do the same with the actual PLMN in MM. */
1270 reg_clear_plmn (&mm_data->reg.actual_plmn);
1271 #ifndef REL99
1272 /* Invalidate the TMSI, CKSN, KC in RR */
1273 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1274 #endif
1275 /* Delete EPLMN List */
1276 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1277 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1278
1279 #ifdef REL99
1280 #ifdef GPRS
1281 /* Following will check if the TMSI, CKSN, KC needs to be deleted */
1282 if(mm_data->rej_cause EQ GMMCS_ROAMING_NOT_ALLOWED)
1283 {
1284 /*
1285 * Update the MM state with invalidate the TMSI, CKSN, KC in MM
1286 * and send indication to SIM.
1287 */
1288 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1289 }
1290 else
1291 #endif /* #ifdef GPRS */
1292 {
1293 /*
1294 * update the MM state but don't delete the TMSI, CKSN, KC
1295 * and send indication to SIM.
1296 */
1297 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, TRUE);
1298 }
1299
1300 #else
1301 /* Inform the SIM */
1302 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1303 #endif
1304 /* Set the new MM state before calling reg_mm_failure() */
1305 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
1306 reg_mm_failure (FORB_PLMN_NOT_INCLUDED);
1307 USE_STORED_ENTRIES();
1308 break;
1309
1310 #ifdef REL99
1311 #ifdef GPRS
1312 case GMMCS_NO_SUITABLE_CELL_IN_LA: /* #15 + Ofs GMM sent for GPRS attach rejected case*/
1313 /* GMM sent cause value 15 because of 'GPRS attach rejected' or 'Combined GPRS rejected'
1314 * or 'Network initiated GPRS detach'.*/
1315 /* Invalidate the TMSI, CKSN, KC in RR */
1316 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1317 /*FALLTHROUGH*/
1318 case GMMCS_NO_SUITABLE_CELL_IN_LA_WITH_RAU_REJ: /* #15 + Ofs GMM sent for GPRS RAU rejected case*/
1319 /* GMM sent cause value 15 because of 'Normal/periodic RAU Rejected' or
1320 * 'Combined RAU Rejected by the network'.*/
1321 /*FALLTHROUGH*/
1322 //lint -fallthrough
1323 #endif
1324 case MMCS_NO_SUITABLE_CELL_IN_LA: /* #15 + Ofs MM received in LU rejected message*/
1325 /*MM received cause value 15 because of 'LU rejected' by the network*/
1326 /*
1327 * For cause 15 handling as per the specification 24.008 v3.15.0,
1328 * If Cause value 15 received because of 'LU rejected' or 'Normal/periodic RAU
1329 * Rejected' or 'Combined RAU Rejected by the network' MM will
1330 * - store the LAI in the list of "forbidden location areas for roaming".
1331 * - set the update status to U3 ROAMING NOT ALLOWED and shall reset the
1332 * location update attempt counter
1333 * - The MS shall search for a suitable cell in another location area in
1334 * the same PLMN according to 3GPP TS 03.22 and 3GPP TS 25.304.
1335 * If cause value 15 received because of 'GPRS attach rejected' or 'Combined
1336 * GPRS rejected' or 'Network initiated GPRS detach' MM will
1337 * - Do the above steps
1338 * - Additionally will delete any TMSI and ciphering key sequence number.
1339 */
1340 mm_data->attempt_cnt = 0;
1341 mm_data->loc_upd_type.lut = NOT_RUNNING;
1342 /*
1343 * Enter the location area in RR into the list of "forbidden location areas for roaming"
1344 * for reject cause #15. This list is maintained in RR.
1345 */
1346 mm_build_rr_sync_req_cause (SYNCCS_LAI_NOT_ALLOW_FOR_ROAMING);
1347
1348 /* Set the new MM state MM_IDLE_LIMITED_SERVICE*/
1349 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
1350 /* Following will check if the TMSI, CKSN, KC needs to be deleted */
1351 #ifdef GPRS
1352 if(mm_data->rej_cause EQ GMMCS_NO_SUITABLE_CELL_IN_LA)
1353 {
1354 /*
1355 * Update the MM state with invalidate the TMSI, CKSN, KC in MM
1356 * and send indication to SIM.
1357 */
1358 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1359 }
1360 else
1361 #endif /* #ifdef GPRS */
1362 {
1363 /*
1364 * update the MM state but don't delete the TMSI, CKSN, KC
1365 * and send indication to SIM.
1366 */
1367 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, TRUE);
1368 }
1369
1370 /* MM should send primitive MMGMM_REG_REJ to GMM only in case if cause 15 is received
1371 * because of its own failure i.e if there was either a RR failure or a MM failure
1372 * (e.g. LOCATION UPDATING reject). It should then inform GMM about failure. Upon
1373 * reception of MMGMM_REG_REJ primitive, GMM send failure information to MMI.
1374 */
1375 if(GET_CAUSE_ORIGIN_ENTITY (mm_data->rej_cause) EQ MM_ORIGINATING_ENTITY)
1376 {
1377 /* MM sends primitive MMGMM_REG_REJ to GMM */
1378 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
1379 SEARCH_RUNNING,
1380 FORB_PLMN_NOT_INCLUDED);
1381 }
1382 else
1383 {
1384 /*Do not send NREG Indication. GMM is already unregistered*/
1385 }
1386 /*
1387 * Start PLMN serch, try the PLMN in the list i.e. search
1388 * another location area in the same PLMN.
1389 */
1390 mm_mmr_reg_req (FUNC_PLMN_SRCH);
1391
1392 /*Responce back with confirmation if MMGMM_NREG_REQ was received.*/
1393 if (mm_data->nreg_request)
1394 {
1395 mm_mmgmm_nreg_cnf (mm_data->nreg_cause);
1396 }
1397
1398 USE_STORED_ENTRIES();
1399 break;
1400 #endif
1401
1402 case MMCS_IMSI_IN_HLR: /* #2 + Ofs */
1403 #ifdef GPRS
1404 case GMMCS_IMSI_UNKNOWN:
1405 if (!mm_lup_allowed_by_gmm())
1406 {
1407 /*
1408 * The "IMSI unknown in HLR" was received by a GMM request and
1409 * not by a LOCATION UPDATING REJECT message.
1410 * MM must not enter MM_IDLE_NO_IMSI here, as the SIM
1411 * is still valid for the GPRS side and MM still has to deliver
1412 * some services for GMM which it cannot deliver in service state
1413 * "NO IMSI". The relevant testcases here are (Release 1999):
1414 * GSM 11.10 subclause 44.2.1.2.2, GSM 11.10 subclause 44.2.3.2.3.
1415 * What is tested there is that after an ATTACH ACCEPT/
1416 * ROUTING AREA UPDATING ACCEPT message the mobile doesn't
1417 * respond to packet paging with IMSI anymore and that no DETACH
1418 * is performed for GSM.
1419 * What is not tested is that the mobile station doesn't respond to
1420 * paging with IMSI on the old channels after entering an area where
1421 * we have network mode II/III or that the mobile rejects a manual
1422 * switch to mobile class CS without switch off.
1423 * What is done here may not be perfect, but should be sufficient.
1424 * In fact, #2 may never be seen in field, as the network providers
1425 * may not want to sell GPRS subscriptions without GSM subscriptions.
1426 */
1427
1428 /* Release all waiting CM requests */
1429 mm_mmxx_rel_ind (mm_data->rej_cause, CM_NOT_IDLE);
1430
1431 /*
1432 * Invalidate TMSI and ciphering parameters in RR.
1433 * RR remains in full service for GPRS.
1434 */
1435 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1436
1437 /* Delete EPLMN List */
1438 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1439 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1440
1441 /* Invalidate the update state */
1442 #ifdef REL99
1443 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1444 #else
1445 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1446 #endif
1447
1448 /* If the deregistration was caused by a MMGMM_NREG_REQ,
1449 * confirm it properly */
1450 if (mm_data->nreg_request)
1451 mm_mmgmm_nreg_cnf (mm_data->nreg_cause);
1452
1453 /* Next state is a parking state */
1454 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
1455 break;
1456 }
1457 /*
1458 * However, if #2 is received by LOCATION UPDATING REJECT message,
1459 * GSM 04.08 subclause 4.4.4.7 claims that the SIM shall be considered
1460 * as invalid for "the mobile station" (and not only for the GSM part).
1461 * There is no distinction between causes #2, #3 and #6 there.
1462 */
1463 /*FALLTHROUGH*/
1464 //lint -fallthrough
1465 #endif /* #ifdef GPRS */
1466 case MMCS_ILLEGAL_MS: /* #3 + Ofs */
1467 case MMCS_ILLEGAL_ME: /* #6 + Ofs */
1468 #ifdef GPRS
1469 case GMMCS_ILLEGAL_MS:
1470 case GMMCS_ILLEGAL_ME:
1471 case GMMCS_GSM_GPRS_NOT_ALLOWED: /* #8 + Ofs */
1472 #endif /* #ifdef GPRS */
1473 mm_clear_mob_ident (&mm_data->reg.imsi_struct);
1474 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG);
1475
1476 /* Delete EPLMN List */
1477 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1478 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1479
1480 // Debug patch >>>
1481 if (mm_data->mm_idle_no_imsi_marker EQ 0)
1482 mm_data->mm_idle_no_imsi_marker = 19;
1483 // End debug patch
1484
1485 mm_data->loc_upd_type.lut = NOT_RUNNING;
1486 #ifdef REL99
1487 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED, FALSE);
1488 #else
1489 reg_invalidate_upd_state (MS_LA_NOT_ALLOWED);
1490 #endif
1491 /* Invalidate SIM data after indirect call to reg_build_sim_update() */
1492 mm_clear_reg_data ();
1493 mm_data->reg.plmn_cnt = 0; /* Delete list of available PLMNs */
1494 /* Set the new MM state before calling reg_mm_failure */
1495 SET_STATE (STATE_MM, MM_IDLE_NO_IMSI);
1496 reg_mm_failure (FORB_PLMN_NOT_INCLUDED);
1497 USE_STORED_ENTRIES();
1498 break;
1499
1500 #ifdef GPRS
1501 case GMMCS_GPRS_NOT_ALLOWED_IN_PLMN: /* #14 + Ofs */
1502 /*
1503 * We assume this cause will not be sent by the HPLMN.
1504 *
1505 * "The MS shall store the PLMN identity in the "forbidden PLMNs for
1506 * GPRS service" list. A GPRS MS operating in MS operation mode C
1507 * shall perform a PLMN selection instead of a cell selection."
1508 * [3GPP TS 04.08 version 7.13.0 and others]
1509 */
1510 reg_plmn_add_bad (mm_data->reg.gprs_forb_plmn,
1511 MAX_GPRS_FORB_PLMN_ID,
1512 &mm_data->reg.actual_plmn);
1513
1514 if (mm_data->reg.op.m EQ MODE_AUTO AND
1515 mm_data->gprs.mobile_class EQ MMGMM_CLASS_CG AND
1516 !reg_plmn_equal_hplmn (&mm_data->reg.actual_plmn))
1517 {
1518 if (mm_data->reg.plmn_cnt EQ 0)
1519 {
1520 /* A PLMN list is not present */
1521 reg_extract_hplmn (&mm_data->reg.actual_plmn);
1522 mm_data->reg.plmn_cnt = 0; /* Delete list of available PLMNs */
1523 mm_mmr_reg_req (FUNC_PLMN_SRCH);
1524 }
1525 else
1526 {
1527 /* A PLMN list is present */
1528 if (mm_data->reg.plmn_cnt > mm_data->reg.plmn_index)
1529 {
1530 /*
1531 * There are still untried entries in the PLMN list.
1532 * Try the next PLMN in the list.
1533 */
1534 reg_unpack_plmn (&mm_data->reg.actual_plmn,
1535 mm_data->reg.plmn, mm_data->reg.plmn_index);
1536 mm_data->reg.plmn_index++;
1537 mm_data->attempt_cnt = 0;
1538 mm_mmr_reg_req (FUNC_PLMN_SRCH);
1539 }
1540 else
1541 {
1542 /*
1543 * There is no signalization to signal the end of search to
1544 * GMM here. Maybe this has to be introduced.
1545 */
1546 }
1547 }
1548 }
1549 break;
1550 #endif /* #ifdef GPRS */
1551
1552 case MMCS_NETWORK_FAILURE: /* #17 + Ofs */
1553 #ifdef GPRS
1554 case GMMCS_NET_FAIL:
1555 #endif /* #ifdef GPRS */
1556 /*FALLTHROUGH*/
1557 default:
1558
1559 /* Delete EPLMN List */
1560 if (reg_clear_plmn_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE))
1561 mm_build_rr_sync_req_cause(SYNCCS_EPLMN_LIST);
1562
1563 mm_lup_restart ();
1564 break;
1565 }
1566 }
1567
1568
1569
1570 /*
1571 +--------------------------------------------------------------------+
1572 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1573 | STATE : code ROUTINE : mm_lup_restart |
1574 +--------------------------------------------------------------------+
1575
1576 PURPOSE : The purpose of this function is to perform the actions
1577 required after a location updating attempt has failed.
1578 Either T3211 or T3212 are started by this function,
1579 so a new location updating attempt will be started
1580 after expiry.
1581
1582 */
1583
1584 GLOBAL void mm_lup_restart (void)
1585 {
1586 GET_INSTANCE_DATA;
1587 TRACE_FUNCTION ("mm_lup_restart ()");
1588
1589 mm_data->last_rej_cause = 0;
1590 if (mm_data->attempt_cnt < 4)
1591 mm_data->attempt_cnt++;
1592 if (mm_data->attempt_cnt < 4 AND
1593 mm_check_lai (&mm_data->reg.lai, &mm_data->mm.lai) AND
1594 mm_data->reg.update_stat EQ MS_UPDATED)
1595 {
1596 /*
1597 * - The update status is UPDATED, and the stored LAI is equal to the one
1598 * received on the BCCH from the current serving cell and the
1599 * attempt counter is smaller than 4:
1600 *
1601 * The mobile station shall keep the update status to UPDATED, the MM IDLE
1602 * sub-state after the RR connection release is NORMAL SERVICE.
1603 * (GSM 04.08 4.4.4.9)
1604 */
1605 TIMERSTART (T3211, T_3211_VALUE);
1606 SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE);
1607
1608 #ifdef GPRS
1609 if (mm_data->gprs.sim_physically_removed)
1610 {
1611 mm_sim_removed_gprs_active ();
1612 return;
1613 }
1614 #endif /* #ifdef GPRS */
1615
1616 }
1617 else
1618 {
1619 /*
1620 * - Either the update status is different from UPDATED, or the stored
1621 * LAI is different from the one received by the on the BCCH from the
1622 * serving cell, or the attempt counter is greater or equal to 4:
1623 *
1624 * The mobile station shall delete any LAI, TMSI, ciphering key sequence
1625 * number stored in the SIM, set the update status to NOT UPDATED and
1626 * enter the MM IDLE sub-state ATTEMPTING TO UPDATE or optionally the
1627 * MM IDLE sub-state PLMN SEARCH in order to perform a PLMN selection
1628 * according to 3GPP TS 23.122 when the RR connection is released. If
1629 * the attempt counter is smaller than 4, the mobile station shall
1630 * memorize that timer T3211 is to be started when the RR connection is
1631 * released, otherwise it shall memorize that timer T3212 is to be started
1632 * when the RR connection is released.
1633 * (GSM 24.008 4.4.4.9)
1634 */
1635 mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL);
1636 #ifdef REL99
1637 reg_invalidate_upd_state (MS_NOT_UPDATED, FALSE);
1638 #else
1639 reg_invalidate_upd_state (MS_NOT_UPDATED);
1640 #endif
1641
1642 /* Set the new state now, vital for reg_plmn_select() */
1643 SET_STATE (STATE_MM, MM_IDLE_ATTEMPT_TO_UPDATE);
1644
1645 #ifdef GPRS
1646 if (mm_data->gprs.sim_physically_removed)
1647 {
1648 mm_sim_removed_gprs_active ();
1649 return;
1650 }
1651 #endif /* #ifdef GPRS */
1652
1653 if (mm_data->attempt_cnt < 4)
1654 {
1655 TIMERSTART (T3211, T_3211_VALUE);
1656 }
1657 else
1658 {
1659 mm_mmxx_rel_ind (MMCS_NO_REGISTRATION, CM_NOT_IDLE);
1660 mm_start_t3212_bcch ();
1661 mm_data->loc_upd_type.lut = NOT_RUNNING;
1662
1663 if (mm_lup_allowed_by_gmm())
1664 {
1665 if (mm_data->reg.plmn_cnt > mm_data->reg.plmn_index)
1666 {
1667 /*
1668 * Select the next PLMN in the list, if available.
1669 * This is recommended in GSM 03.22 subclause 4.4.4.
1670 * "When in Automatic Network Selection mode and the MS is in the
1671 * "not updated" state with one or more suitable cells to camp on;
1672 * then after the maximum allowed unsuccessful LR requests (controlled
1673 * by the specific attempt counters) the MS may continue (or start if
1674 * not running) the user reselection procedure of 4.4.3.2 A."
1675 */
1676 reg_plmn_select (FORB_PLMN_NOT_INCLUDED);
1677 }
1678 else if (mm_data->reg.op.m EQ MODE_AUTO AND
1679 mm_data->reg.op.sim_ins EQ SIM_INSRT AND
1680 mm_data->reg.quick_hplmn_search EQ TRUE)
1681 {
1682 /* The state PLMN SEARCH is also entered in the following cases:
1683 * - optionally, when the mobile station is in the ATTEMPTING TO UPDATE
1684 * state and is in Automatic Network Selection mode and location update
1685 * attempt counter is greater than or equal to 4.
1686 * (GSM 24.008 4.2.1.2)
1687 */
1688 /* optionally the MM IDLE sub-state PLMN SEARCH in order to perform a
1689 * PLMN selection according to 3GPP TS 23.122
1690 * (GSM 24.008 4.4.4.9)
1691 */
1692 mm_data->plmn_scan_mm = TRUE;
1693 mm_data->reg.quick_hplmn_search = FALSE;
1694 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
1695 SEARCH_RUNNING,
1696 FORB_PLMN_NOT_INCLUDED);
1697 mm_func_mmgmm_net_req();
1698 }
1699 else
1700 {
1701 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
1702 SEARCH_NOT_RUNNING,
1703 FORB_PLMN_NOT_INCLUDED);
1704 mm_data->reg.quick_hplmn_search = TRUE;
1705 }
1706 }
1707
1708
1709 if (mm_data->reg.op.sim_ins EQ SIM_INSRT AND
1710 mm_data->reg.op.ts EQ TS_NO_AVAIL)
1711 {
1712 /*
1713 * If there is no test SIM inserted and after 4 unsuccessfull
1714 * registration attempts, the registration timer is started.
1715 * On timeout of the registration timer, *one* normal location
1716 * updating is started.
1717 * Without this, MM may stay in MM_IDLE_ATTEMPT_TO_UPDATE
1718 * for an infinite time. (No call attempt, no cell selection,
1719 * no periodic location updating)
1720 */
1721 TIMERSTART (T_REGISTRATION, T_REG_VALUE);
1722 }
1723 }
1724 }
1725 reg_check_hplmn_tim (mm_data->reg.thplmn);
1726 USE_STORED_ENTRIES();
1727 }
1728
1729 /*
1730 +--------------------------------------------------------------------+
1731 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1732 | STATE : code ROUTINE : mm_mdl_rel_req |
1733 +--------------------------------------------------------------------+
1734
1735 PURPOSE : This function sends an MDL_RELEASE_REQ for SAPI 0 to the
1736 data link layer. Usually this is done after RR_RELEASE_IND
1737 or RR_ABORT_IND is received by RR.
1738 One really good question is why this is handled in MM and
1739 not in RR. But this doesn't matter as it works the way it
1740 is implemented.
1741
1742 */
1743
1744 GLOBAL void mm_mdl_rel_req (void)
1745 {
1746 PALLOC (mdl_release_req, MDL_RELEASE_REQ); /* T_MDL_RELEASE_REQ */
1747 TRACE_FUNCTION ("mm_mdl_rel_req ()");
1748
1749 mdl_release_req->sapi = SAPI_0;
1750 mdl_release_req->ch_type = NOT_PRESENT_8BIT;
1751
1752 PSENDX (DL, mdl_release_req);
1753 }
1754
1755 /*
1756 +--------------------------------------------------------------------+
1757 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1758 | STATE : code ROUTINE : mm_mdl_rel_req_sapi_3 |
1759 +--------------------------------------------------------------------+
1760
1761 PURPOSE : This function sends an MDL_RELEASE_REQ for SAPI 3 to the
1762 data link layer. Usually this is done after RR_RELEASE_IND
1763 or RR_ABORT_IND is received by RR.
1764 One really good question is why this is handled in MM and
1765 not in RR. But this doesn't matter as it works the way it
1766 is implemented.
1767
1768 */
1769
1770 GLOBAL void mm_mdl_rel_req_sapi_3 (void)
1771 {
1772 PALLOC (mdl_release_req, MDL_RELEASE_REQ);
1773
1774 TRACE_FUNCTION ("mm_mdl_rel_req_sapi_3 ()");
1775
1776 mdl_release_req->sapi = SAPI_3;
1777 mdl_release_req->ch_type = NOT_PRESENT_8BIT;
1778
1779 PSENDX (DL, mdl_release_req);
1780 }
1781
1782
1783 /*
1784 +--------------------------------------------------------------------+
1785 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1786 | STATE : code ROUTINE : mm_mmsms_rel_ind |
1787 +--------------------------------------------------------------------+
1788
1789 PURPOSE : This functions releases the SMS connections (SAPI 3)
1790 of the required connection type to the SMS entitity. This
1791 function is used if MM receives a RR_RELEASE_IND primitive
1792 for SAPI 3.
1793
1794 */
1795
1796 GLOBAL void mm_mmsms_rel_ind (USHORT cause, UBYTE conn_typ)
1797 {
1798 GET_INSTANCE_DATA;
1799 UBYTE ti;
1800
1801 TRACE_FUNCTION ("mm_mmsms_rel_ind ()");
1802
1803 for (ti = 0; ti < NUM_OF_CONN_PER_CM_ENT; ti++)
1804 {
1805 switch (conn_typ)
1806 {
1807 case CM_PENDING:
1808 case CM_ACTIVE:
1809 case CM_REEST_PENDING:
1810 if (mm_data->conn_state[SMS_COMP][ti] NEQ conn_typ)
1811 continue;
1812 /*FALLTHROUGH*/
1813 //lint -fallthrough
1814 default: /* all connections */
1815 if (mm_data->conn_state[SMS_COMP][ti] EQ CM_IDLE)
1816 continue;
1817 CM_SET_STATE (SMS_COMP, ti, CM_IDLE);
1818 mm_mmxx_release_ind (SMS_COMP, ti, cause);
1819 mm_delete_entry (SMS_COMP, ti);
1820 break;
1821 }
1822 }
1823 }
1824
1825 /*
1826 +--------------------------------------------------------------------+
1827 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1828 | STATE : code ROUTINE : mm_mmxx_err_ind |
1829 +--------------------------------------------------------------------+
1830
1831 PURPOSE : This function is called if a radio link error occurs,
1832 this means, the RR_ABORT_IND primitive was received
1833 while active connections existed. Upper layers are
1834 notificated about the failure. The function returns the
1835 number of active connections found (CM_ACTIVE).
1836
1837 */
1838
1839 GLOBAL SHORT mm_mmxx_err_ind (USHORT cause)
1840 {
1841 GET_INSTANCE_DATA;
1842 UBYTE count = 0;
1843 UBYTE cm;
1844 UBYTE ti;
1845
1846 TRACE_FUNCTION ("mm_mmxx_err_ind ()");
1847 for (cm = 0; cm < NUM_OF_CM_ENT; cm++)
1848 {
1849 for ( ti = 0; ti < NUM_OF_CONN_PER_CM_ENT; ti++)
1850 {
1851 if (CMSTATE(cm, ti) EQ CM_ACTIVE)
1852 {
1853 count++;
1854 switch (cm)
1855 {
1856 case CC_COMP:
1857 {
1858 PALLOC (mmcm_error_ind, MMCM_ERROR_IND);
1859 mmcm_error_ind->ti = ti;
1860 mmcm_error_ind->cause = cause;
1861 PSENDX (CC, mmcm_error_ind);
1862 break;
1863 }
1864 case SS_COMP:
1865 {
1866 PALLOC (mmss_error_ind, MMSS_ERROR_IND);
1867 mmss_error_ind->ti = ti;
1868 mmss_error_ind->cause = cause;
1869 PSENDX (SS, mmss_error_ind);
1870 break;
1871 }
1872 case SMS_COMP:
1873 {
1874 PALLOC (mmsms_error_ind, MMSMS_ERROR_IND);
1875 mmsms_error_ind->ti = ti;
1876 mmsms_error_ind->cause = cause;
1877 PSENDX (SMS, mmsms_error_ind);
1878 break;
1879 }
1880 default:
1881 TRACE_ERROR ("Illegal cm comp");
1882 break;
1883 }
1884 }
1885 }
1886 }
1887 return (count);
1888 }
1889
1890 /*
1891 +--------------------------------------------------------------------+
1892 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1893 | STATE : code ROUTINE : mm_mmxx_est_cnf |
1894 +--------------------------------------------------------------------+
1895
1896 PURPOSE : Handle CM SERVICE ACCEPT / completion of ciphering mode
1897 setting for connections requested by CM entities.
1898 Two different cases, call establishment and
1899 call reestablishment are handled here.
1900
1901 */
1902
1903 GLOBAL void mm_mmxx_est_cnf (void)
1904 {
1905 GET_INSTANCE_DATA;
1906 UBYTE ti;
1907
1908 TRACE_FUNCTION ("mm_mmxx_est_cnf ()");
1909 {
1910 if (mm_count_connections (CM_REEST_PENDING) EQ 0)
1911 {
1912 /*
1913 * No connections waiting for reestablishment. The establishment
1914 * was confirmed for a pending connection. Set the state of the
1915 * pending connection to CM_ACTIVE as it is now not pending anymore.
1916 * Notify the CM entitity which requested the connection
1917 * about the successful establishment.
1918 * (There can only be one pending connection at a given time).
1919 */
1920
1921 CM_SET_STATE (mm_data->pend_conn.comp,
1922 mm_data->pend_conn.ti, CM_ACTIVE);
1923
1924 switch (mm_data->pend_conn.comp)
1925 {
1926 case CC_COMP:
1927 {
1928 PALLOC (mmcm_establish_cnf, MMCM_ESTABLISH_CNF);
1929 mmcm_establish_cnf->ti = mm_data->pend_conn.ti;
1930 PSENDX (CC, mmcm_establish_cnf);
1931 }
1932 break;
1933 case SS_COMP:
1934 {
1935 PALLOC (mmss_establish_cnf, MMSS_ESTABLISH_CNF);
1936 mmss_establish_cnf->ti = mm_data->pend_conn.ti;
1937 PSENDX (SS, mmss_establish_cnf);
1938 }
1939 break;
1940 case SMS_COMP:
1941 {
1942 PALLOC (mmsms_establish_cnf, MMSMS_ESTABLISH_CNF);
1943 mmsms_establish_cnf->ti = mm_data->pend_conn.ti;
1944 PSENDX (SMS, mmsms_establish_cnf);
1945 }
1946 break;
1947 default:
1948 TRACE_ERROR (UNEXPECTED_DEFAULT); /* Cannot happen */
1949 break;
1950 }
1951 }
1952 else
1953 {
1954 /*
1955 * Reestablishment pending. Only the CM entitiy CC can perform call
1956 * reestablishment, so only CC needs to be treated here.
1957 */
1958 for (ti = 0; ti < NUM_OF_CONN_PER_CM_ENT; ti++)
1959 {
1960 if (mm_data->conn_state[CC_COMP][ti] EQ CM_REEST_PENDING)
1961 {
1962 PALLOC (mmcm_reestablish_cnf, MMCM_REESTABLISH_CNF);
1963 CM_SET_STATE (CC_COMP, ti, CM_ACTIVE);
1964 mmcm_reestablish_cnf->ti = ti;
1965 PSENDX (CC, mmcm_reestablish_cnf);
1966 }
1967 }
1968 }
1969 }
1970 }
1971
1972
1973 /*
1974 +--------------------------------------------------------------------+
1975 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
1976 | STATE : code ROUTINE : mm_mmxx_release_ind |
1977 +--------------------------------------------------------------------+
1978
1979 PURPOSE : Send either MMCM_RELEASE_IND, MMSS_RELEASE_IND or
1980 MMSMS_RELEASE_IND, dependend of the CM component.
1981
1982 */
1983
1984 GLOBAL void mm_mmxx_release_ind (UBYTE comp, UBYTE ti, USHORT relcs)
1985 {
1986 TRACE_FUNCTION ("mm_mmxx_release_ind()");
1987
1988 switch (comp)
1989 {
1990 case CC_COMP:
1991 {
1992 PALLOC (mmcm_release_ind, MMCM_RELEASE_IND); /* T_MMCC_RELEASE_IND */
1993 mmcm_release_ind->ti = ti;
1994 mmcm_release_ind->cause = relcs;
1995 PSENDX (CC, mmcm_release_ind);
1996 }
1997 break;
1998
1999 case SS_COMP:
2000 {
2001 PALLOC (mmss_release_ind, MMSS_RELEASE_IND); /* T_MMSS_RELEASE_IND */
2002 mmss_release_ind->ti = ti;
2003 mmss_release_ind->cause = relcs;
2004 PSENDX (SS, mmss_release_ind);
2005 }
2006 break;
2007
2008 case SMS_COMP:
2009 {
2010 PALLOC (mmsms_release_ind, MMSMS_RELEASE_IND); /* T_MMSMS_RELEASE_IND */
2011 mmsms_release_ind->ti = ti;
2012 mmsms_release_ind->cause = relcs;
2013 PSENDX (SMS, mmsms_release_ind);
2014 }
2015 break;
2016
2017 default:
2018 TRACE_ERROR (UNEXPECTED_PARAMETER);
2019 break;
2020 }
2021 }
2022
2023
2024 /*
2025 +--------------------------------------------------------------------+
2026 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2027 | STATE : code ROUTINE : mm_mmxx_rel_ind |
2028 +--------------------------------------------------------------------+
2029
2030 PURPOSE : The mm_mmxx_rel_ind() function releases all CM connections
2031 of a given ´given type. Type may be CM_PENDING,
2032 CM_ACTIVE, CM_REEST_PENDING and CM_NOT_IDLE.
2033
2034 */
2035
2036 GLOBAL void mm_mmxx_rel_ind (USHORT cause, UBYTE conn_typ)
2037 {
2038 GET_INSTANCE_DATA;
2039 UBYTE comp;
2040 UBYTE ti;
2041
2042 TRACE_FUNCTION ("mm_mmxx_rel_ind ()");
2043
2044 for (comp = 0; comp < NUM_OF_CM_ENT; comp++)
2045 {
2046 for (ti = 0; ti < NUM_OF_CONN_PER_CM_ENT; ti++)
2047 {
2048 switch (conn_typ)
2049 {
2050 case CM_PENDING:
2051 case CM_ACTIVE:
2052 case CM_REEST_PENDING:
2053 if (CMSTATE(comp, ti) NEQ conn_typ)
2054 continue;
2055 /*FALLTHROUGH*/
2056 //lint -fallthrough
2057 default: /* CM_NOT_IDLE */
2058 if (CMSTATE(comp, ti) EQ CM_IDLE)
2059 continue;
2060 CM_SET_STATE (comp, ti, CM_IDLE);
2061 mm_mmxx_release_ind (comp, ti, cause);
2062 mm_delete_entry (comp, ti);
2063 }
2064 }
2065 }
2066 }
2067
2068
2069 /*
2070 +--------------------------------------------------------------------+
2071 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2072 | STATE : code ROUTINE : mm_power_off |
2073 +--------------------------------------------------------------------+
2074
2075 PURPOSE : This function deactivates the lower layers
2076 and enters the MM NULL state.
2077
2078 */
2079
2080 GLOBAL void mm_power_off (void)
2081 {
2082 GET_INSTANCE_DATA;
2083 USHORT index;
2084
2085 TRACE_FUNCTION ("mm_power_off ()");
2086
2087 /* Send RR_DEACTIVATE_REQ */
2088 {
2089 PALLOC (rr_deactivate_req, RR_DEACTIVATE_REQ);
2090 PSENDX (RR, rr_deactivate_req);
2091 }
2092
2093 /* Invalidate the registration data temporary only without deleting it. */
2094 mm_clear_reg_data ();
2095
2096 /* Stop all MM timers */
2097 for (index = 0; index < NUM_OF_MM_TIMERS; index++)
2098 {
2099 TIMERSTOP (index);
2100 }
2101
2102 mm_data->t3212_timeout = FALSE;
2103
2104 /* MM enters MM_NULL state, but the important MM data is still alive. */
2105 SET_STATE (STATE_MM, MM_NULL);
2106 #ifdef GPRS
2107 SET_STATE (STATE_REG_TYPE, REG_GPRS_INACTIVE);
2108 SET_STATE (STATE_GPRS_CM_EST, CM_GPRS_EST_OK);
2109 #endif /* GPRS */
2110 }
2111
2112 /*
2113 +--------------------------------------------------------------------+
2114 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2115 | STATE : code ROUTINE : mm_random |
2116 +--------------------------------------------------------------------+
2117
2118 PURPOSE : A random number generator.
2119
2120 */
2121
2122 GLOBAL USHORT mm_random (USHORT n)
2123 {
2124 GET_INSTANCE_DATA;
2125 T_TIME actual_time;
2126
2127 TRACE_FUNCTION ("mm_random ()");
2128
2129 vsi_t_time (VSI_CALLER &actual_time);
2130 mm_data->rand_base += actual_time;
2131 return ((USHORT) mm_data->rand_base % n);
2132 }
2133
2134 /*
2135 +--------------------------------------------------------------------+
2136 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2137 | STATE : code ROUTINE : mm_read_entry |
2138 +--------------------------------------------------------------------+
2139
2140 PURPOSE : This functions reads the entries which are flagged as
2141 "USE" and executes them. This is done by:
2142 - rebuilding the original primitives and sending them to
2143 the MM entitity in case of content_type "EVENT_ENTRY".
2144 - calling the respective timeout handling routine for
2145 timers (content_type "EVENT_ENTRY"),
2146 - resending the stored primitive (content_type "PRIMITIVE_ENTRY")
2147
2148 */
2149
2150 GLOBAL void mm_read_entry (void)
2151 {
2152 GET_INSTANCE_DATA;
2153 TRACE_FUNCTION ("mm_read_entry ()");
2154
2155 if (mm_data->store[0].use EQ USE)
2156 {
2157 USHORT i;
2158 T_STORE current;
2159
2160 current = mm_data->store[0]; /* Struct copy */
2161
2162 for (i = 0; i < MAX_STORE_ENTRIES - 1; i++)
2163 {
2164 mm_data->store[i] = mm_data->store[i + 1]; /* Struct copy */
2165 }
2166 mm_data->store[MAX_STORE_ENTRIES - 1].use = ENTRY_FREE;
2167 mm_data->store[MAX_STORE_ENTRIES - 1].content_type = NO_ENTRY;
2168
2169 TRACE_EVENT_P2 ("Read entry: comp=%d, ti=%d", current.content.event.comp, current.content.event.ti);
2170
2171 if (current.content_type EQ EVENT_ENTRY)
2172 {
2173 switch (current.content.event.comp)
2174 {
2175 case TIMEOUT:
2176 switch (current.content.event.ti) /* TI used as timer index here */
2177 {
2178 case T3210: tim_t3210 (); break;
2179 case T3211: tim_t3211 (); break;
2180 case T3212: tim_t3212 (); break;
2181 case T3213: tim_t3213 (); break;
2182 case T3220: tim_t3220 (); break;
2183 case T3230: tim_t3230 (); break;
2184 case T3240: tim_t3240 (); break;
2185 #ifdef REL99
2186 case T3241: tim_t3241 (); break;
2187 #endif
2188 default:
2189 TRACE_EVENT (UNEXPECTED_DEFAULT);
2190 break;
2191 }
2192 break;
2193
2194 case REG_COMP:
2195 mm_func_mmgmm_net_req ();
2196 break;
2197
2198 case SS_COMP:
2199 case SMS_COMP:
2200 current.content.event.estcs = 0; /* Override estcs */
2201 /*FALLTHROUGH*/
2202 //lint -fallthrough
2203 case CC_COMP:
2204 CM_SET_STATE (current.content.event.comp, current.content.event.ti, CM_IDLE);
2205 mm_mmxx_establish_req (current.content.event.comp, current.content.event.ti, current.content.event.estcs, current.info);
2206 break;
2207
2208 default:
2209 TRACE_ERROR (UNEXPECTED_DEFAULT);
2210 break;
2211 } /* switch comp */
2212 } /* if content_type */
2213 else
2214 {
2215 /* the following code will be used if additional primitives
2216 * will be stored this way or a generic handling for storage
2217 * and retrieval of elements is requested.
2218 */
2219 switch (((T_PRIM_HEADER *)current.content.primitive)->opc)
2220 {
2221 case RR_ACTIVATE_IND:
2222 mm_rr_activate_ind((T_RR_ACTIVATE_IND *) P2D(current.content.primitive));
2223 break;
2224
2225 case RR_ABORT_IND:
2226 mm_rr_abort_ind((T_RR_ABORT_IND *) P2D(current.content.primitive));
2227 break;
2228
2229 default:
2230 TRACE_ERROR (UNEXPECTED_DEFAULT);
2231 break;
2232 }
2233 }/* if content_type */
2234 } /* if use */
2235 }
2236
2237
2238 /*
2239 +--------------------------------------------------------------------+
2240 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2241 | STATE : code ROUTINE : mm_reest |
2242 +--------------------------------------------------------------------+
2243
2244 PURPOSE :
2245
2246 */
2247
2248 GLOBAL void mm_reest (UBYTE ti)
2249 {
2250 GET_INSTANCE_DATA;
2251 TRACE_FUNCTION ("mm_reest ()");
2252 if (mm_data->reg.op.func EQ FUNC_LIM_SERV_ST_SRCH)
2253 {
2254 mm_mmxx_rel_ind (MMCS_NO_REGISTRATION, CM_NOT_IDLE);
2255 mm_sim_set_imsi_marker( MSG_MM_REE);
2256 }
2257 else
2258 {
2259 mm_rr_est_req (ESTCS_CAL_REEST, CALL_SERVICE, ti);
2260 SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_MM);
2261 }
2262 }
2263
2264
2265 /*
2266 +--------------------------------------------------------------------+
2267 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2268 | STATE : code ROUTINE : mm_release_rr_connection |
2269 +--------------------------------------------------------------------+
2270
2271 PURPOSE : This functions releases the RR connection after a
2272 CM connection / CM connection attempt or after a
2273 successfull location updating procedure.
2274 It can be assumed that if this function is entered MM
2275 has better service than no service at all (no state 19.5).
2276 It can also be assumed that the mobile is not currently
2277 performing a network search, so the following IDLE state
2278 will not be one of the IDLE search states 19.7 and 19.8.
2279
2280 */
2281
2282 GLOBAL void mm_release_rr_connection (UBYTE resumption)
2283 {
2284 GET_INSTANCE_DATA;
2285 TRACE_FUNCTION ("mm_release_rr_connection ()");
2286
2287 /*
2288 * We are here after either an CM service (attempt) or
2289 * after a successfull location updating procedure.
2290 * The possible remaining states from this point are:
2291 *
2292 * - MM_IDLE_NORMAL_SERVICE, 19.1
2293 * - MM_IDLE_ATTEMPT_TO_UPDATE, 19.2
2294 * - MM_IDLE_LIMITED_SERVICE, 19.3
2295 * - MM_IDLE_NO_IMSI, 19.4
2296 * - MM_IDLE_LUP_NEEDED, 19.6 (GPRS only)
2297 */
2298
2299 #ifdef GPRS
2300 if (mm_data->gprs.reg_cnf_on_idle_entry AND
2301 mm_count_connections (CM_NOT_IDLE) EQ 0)
2302 {
2303 /* Inform GMM about successful end of registration procedure */
2304 mm_data->reg.full_service_indicated = FALSE; /* Force MMGMM_REG_CNF */
2305 mm_mmgmm_reg_cnf ();
2306 }
2307
2308 switch (GET_STATE (STATE_REG_TYPE))
2309 {
2310 case REG_GPRS_INACTIVE:
2311 break; /* No further signalling for GMM needed. GPRS is off */
2312
2313 case REG_REMOTE_CONTROLLED:
2314 if (mm_data->gprs.sim_physically_removed AND mm_normal_upd_needed())
2315 {
2316 /*
2317 * Indicate end of RC update to GMM after SIM removal while also
2318 * engaged in a call, the MS is not updated in the location area.
2319 */
2320 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
2321 SEARCH_NOT_RUNNING,
2322 FORB_PLMN_NOT_INCLUDED);
2323 }
2324 break;
2325
2326 case REG_CELL_SEARCH_ONLY:
2327 /* Inform GMM about release of last CM connection, if any */
2328 mm_mmgmm_cm_release_ind (resumption);
2329 break;
2330
2331 default:
2332 TRACE_ERROR (UNEXPECTED_DEFAULT);
2333 break;
2334 }
2335 #endif /* GPRS */
2336
2337 if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT)
2338 {
2339 /*
2340 * The SIM is considered invalid or is not present at all.
2341 */
2342 if (mm_data->idle_substate NEQ MM_IDLE_NO_IMSI)
2343 {
2344 /*
2345 * The SIM has recently been invalidated,
2346 * Indicate the new service to MMI
2347 */
2348 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
2349 SEARCH_NOT_RUNNING,
2350 FORB_PLMN_NOT_INCLUDED);
2351 }
2352
2353 // Find original place where MM entered MM_IDLE_NO_IMSI state >>>
2354 if (mm_data->mm_idle_no_imsi_marker EQ 0)
2355 mm_data->mm_idle_no_imsi_marker = 4;
2356 // End of debugging patch <<<
2357 SET_STATE (STATE_MM, MM_IDLE_NO_IMSI);
2358 USE_STORED_ENTRIES();
2359 return;
2360 }
2361
2362 /*
2363 * If we are here the next state is not MM_IDLE_NO_IMSI.
2364 */
2365
2366 if (mm_data->idle_substate EQ MM_IDLE_LIMITED_SERVICE)
2367 {
2368 /*
2369 * If we are here we come from an emergency call (attempt)
2370 * and had previously limited service only. So we have to
2371 * re-enter limited service state here.
2372 */
2373 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
2374 USE_STORED_ENTRIES();
2375 return;
2376 }
2377
2378 #ifdef GPRS
2379 if (!mm_lup_allowed_by_gmm () AND
2380 (mm_normal_upd_needed () OR mm_attach_upd_needed ()))
2381 {
2382 /*
2383 * MM needs location updating, but is not allowed by GMM to start it.
2384 */
2385 if (mm_data->rej_cause EQ MMCS_IMSI_IN_VLR)
2386 {
2387 /*
2388 * Mobile has no registration in VLR.
2389 * Normal update after CM SERVICE REJECT with RC_IMSI_IN_VLR needed.
2390 */
2391
2392 /* Throw out all calls to force sending of MMGMM_CM_RELEASE_IND. */
2393 mm_mmxx_rel_ind (mm_data->rej_cause, CM_NOT_IDLE);
2394 mm_mmgmm_cm_release_ind (resumption);
2395
2396 /* Reset the exceptional condition */
2397 mm_data->rej_cause = 0;
2398
2399 /* Inform GMM about lost registration in network */
2400 mm_mmgmm_lup_needed_ind (MMGMM_IMSI_IN_VLR);
2401 }
2402
2403 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
2404 USE_STORED_ENTRIES();
2405 return;
2406 }
2407 #endif /* GPRS */
2408
2409 /*
2410 * Here the remaining possible states are:
2411 *
2412 * - MM_IDLE_NORMAL_SERVICE, 19.1
2413 * - MM_IDLE_ATTEMPT_TO_UPDATE, 19.2
2414 * - MM_IDLE_LIMITED_SERVICE, 19.3 (?) // This is not possible
2415 */
2416
2417 /* After CM connection (attempt), restart T3212 if necessary */
2418 mm_start_t3212_bcch ();
2419
2420 /*
2421 * Find appropriate IDLE state:
2422 * Updated anywhere => MM_IDLE_NORMAL_SERVICE
2423 * Updated nowhere => MM_IDLE_ATTEMPT_TO_UPDATE
2424 */
2425 if (mm_data->reg.update_stat EQ MS_UPDATED)
2426 {
2427 SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE);
2428 }
2429 else
2430 {
2431 SET_STATE (STATE_MM, MM_IDLE_ATTEMPT_TO_UPDATE);
2432 }
2433
2434 // There may be still some problems if we have a clash
2435 // RR_ESTABLISH_REQ -> RR_ACTIVATE_IND -> RR_ESTABLISH_CNF -> RR_RELEASE_IND
2436 // It could be a good idea to repeat the RR_ACTIVATE_IND in this case at
2437 // exactly this place and return. To be checked...
2438
2439 /*
2440 * Check whether T3211 or T3213 are running, if so, the updating
2441 * will be delayed until the respective timer expires.
2442 */
2443 if (!TIMERACTIVE (T3211) AND !TIMERACTIVE(T3213))
2444 {
2445 mm_continue_running_update ();
2446 }
2447 USE_STORED_ENTRIES();
2448 }
2449
2450
2451 /*
2452 +--------------------------------------------------------------------+
2453 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2454 | STATE : code ROUTINE : mm_rr_act_req |
2455 +--------------------------------------------------------------------+
2456
2457 PURPOSE : This function activates the RR sublayer
2458
2459 */
2460
2461 GLOBAL void mm_rr_act_req (void)
2462 {
2463 GET_INSTANCE_DATA;
2464
2465
2466 PALLOC (rr_activate_req, RR_ACTIVATE_REQ); /* T_RR_ACTIVATE_REQ */
2467
2468 TRACE_FUNCTION ("mm_rr_act_req()");
2469
2470 TIMERSTOP (T3211);
2471 TIMERSTOP (T3213);
2472 mm_data->t3213_restart = 0;
2473
2474 memcpy (&rr_activate_req->op, &mm_data->reg.op, sizeof (T_op));
2475 rr_activate_req->op.service = 0; /* not used */
2476 rr_activate_req->cell_test = mm_data->reg.cell_test;
2477 rr_activate_req->check_hplmn = CHECK_PLMN_NOT_PRES;
2478
2479
2480 switch (rr_activate_req->op.func)
2481 {
2482 case FUNC_LIM_SERV_ST_SRCH:
2483 mm_data->loc_upd_type.lut = NOT_RUNNING;
2484
2485 //lint -fallthrough
2486 case FUNC_ST_PWR_SCAN:
2487 case FUNC_NET_SRCH_BY_MMI:
2488 rr_activate_req->cksn = CKSN_RES;
2489 rr_activate_req->accc = 0;
2490 memset (&rr_activate_req->plmn, 0x0F,
2491 sizeof (T_plmn));
2492 rr_activate_req->plmn.v_plmn = V_PLMN_NOT_PRES;
2493 memset (&rr_activate_req->kcv, 0,
2494 sizeof (T_kcv));
2495 memset (&rr_activate_req->imsi_struct, 0,
2496 sizeof (T_imsi_struct));
2497 memset (&rr_activate_req->tmsi_struct, 0,
2498 sizeof (T_tmsi_struct));
2499 memset (&rr_activate_req->bcch_info, 0,
2500 sizeof (T_bcch_info));
2501
2502 break;
2503
2504 case FUNC_PLMN_SRCH:
2505 rr_activate_req->cksn = mm_data->reg.cksn;
2506 rr_activate_req->accc = mm_data->reg.acc_class;
2507 memcpy (&rr_activate_req->plmn, &mm_data->reg.actual_plmn,
2508 sizeof (T_plmn));
2509 rr_activate_req->kcv.v_kc = V_KC_PRES;
2510 memcpy (rr_activate_req->kcv.kc, mm_data->reg.kc, 8);
2511 rr_activate_req->accc = mm_data->reg.acc_class;
2512 memcpy (&rr_activate_req->imsi_struct, &mm_data->reg.imsi_struct,
2513 sizeof (T_imsi_struct));
2514
2515 memset (rr_activate_req->tmsi_struct.id, 0,
2516 sizeof (rr_activate_req->tmsi_struct.id));
2517 if (mm_data->reg.tmsi EQ TMSI_INVALID_VALUE)
2518 {
2519 rr_activate_req->tmsi_struct.v_mid = V_MID_NOT_PRES;
2520 rr_activate_req->tmsi_struct.id_type = TYPE_NO_ID;
2521 rr_activate_req->tmsi_struct.tmsi_dig = 0;
2522 }
2523 else
2524 {
2525 rr_activate_req->tmsi_struct.v_mid = V_MID_PRES;
2526 rr_activate_req->tmsi_struct.id_type = TYPE_TMSI;
2527 rr_activate_req->tmsi_struct.tmsi_dig = mm_data->reg.tmsi;
2528 }
2529
2530
2531 // Question: Did these testcases fail only because there was a bug?
2532 // This has still to be tested on the Anite! ...
2533 // And bcch_encode is suspect here. Maybe the variable could be
2534 // eliminated and instead the expression
2535 // "(mm_data->reg.update_stat EQ MS_UPDATED AND
2536 // !reg_plmn_empty (&last_plmn))" be used. ...
2537
2538 /*
2539 * stored cell selection only in the field
2540 * else 20.4 and 20.5 on the Anite will fail
2541 * Exception: the boolean variable 'config_use_stored_bcch' is set to a
2542 * value of TRUE by the config command: CONFIG USE_STORED_BCCH
2543 * or the AT command: AT%CPRIM="MM","CONFIG USE_STORED_BCCH"
2544 */
2545 if (mm_data->reg.bcch_encode AND
2546 ((mm_data->reg.op.ts EQ TS_NO_AVAIL) OR
2547 (mm_data->config_use_stored_bcch)))
2548 {
2549 /*
2550 * use SIM data only the first time.
2551 */
2552 mm_data->reg.bcch_encode = FALSE;
2553
2554 // Patch HM 14.03.01 >>>
2555 // memcpy (&rr_activate_req->bcch_info, &mm_data->reg.bcch, 17);
2556 // rr_activate_req->bcch_info.v_bcch = TRUE;
2557 rr_activate_req->bcch_info.v_bcch = V_BCCH_PRES;
2558 memcpy (rr_activate_req->bcch_info.bcch, mm_data->reg.bcch, SIZE_BCCH);
2559 // Patch HM 14.03.01 <<<
2560
2561 TRACE_EVENT ("with BCCH information");
2562 }
2563 else
2564 memset (&rr_activate_req->bcch_info, 0,
2565 sizeof (T_bcch_info));
2566
2567 /* restart HPLMN timer for 6 min if we change to a PLMN not the HPLMN */
2568 if (!reg_best_plmn_in_country(&rr_activate_req->plmn))
2569 {
2570 reg_check_hplmn_tim(1);
2571 }
2572 /* reg_stop_hplmn_tim (); */
2573
2574 /* Not Power ON Scenario AND Not a Test SIM */
2575 if (mm_data->first_attach EQ FALSE)
2576 {
2577 /* set the hplmn flag to true only if MM is in substate
2578 Limited service or No cell available*/
2579 if (((GET_STATE(STATE_MM)) EQ MM_IDLE_NO_CELL_AVAILABLE) OR
2580 ((GET_STATE(STATE_MM)) EQ MM_IDLE_LIMITED_SERVICE))
2581 {
2582 /* check_hplmn set to true */
2583 rr_activate_req->check_hplmn = CHECK_PLMN_PRES;
2584 }
2585 }
2586 break;
2587
2588 default:
2589 TRACE_ERROR (UNEXPECTED_DEFAULT);
2590 break;
2591 }
2592
2593 /* Tell RR whether we are interested in GPRS */
2594 if (mm_gsm_alone())
2595 rr_activate_req->gprs_indication = GPRS_NO;
2596 else
2597 rr_activate_req->gprs_indication = GPRS_YES;
2598
2599 if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT)
2600 {
2601 /*
2602 * Without valid SIM, some informations are not present.
2603 * Ensure SIM specific data will be deleted from RR_ACTIVATE_REQ
2604 * if SIM data present, but not considered as valid by MM.
2605 */
2606 memset (&rr_activate_req->plmn, 0x0F, sizeof (T_plmn));
2607 rr_activate_req->plmn.v_plmn = V_PLMN_NOT_PRES;
2608 rr_activate_req->op.sim_ins = SIM_NO_INSRT;
2609 rr_activate_req->op.ts = TS_NO_AVAIL;
2610 rr_activate_req->cksn = CKSN_RES;
2611 memset (&rr_activate_req->kcv, 0x00, sizeof (T_kcv));
2612 rr_activate_req->accc = 0x0000;
2613 mm_clear_mob_ident (&rr_activate_req->imsi_struct);
2614 mm_clear_mob_ident ((T_imsi_struct*) &rr_activate_req->tmsi_struct);
2615 memset (&rr_activate_req->bcch_info, 0, sizeof (T_bcch_info));
2616 rr_activate_req->cell_test = CELL_TEST_DISABLE;
2617 /* rr_activate_req->gprs_indic = GPRS_NO; */
2618 }
2619
2620 /* Add Equiavlent PLMN list to the activation data */
2621 memcpy (&rr_activate_req->eq_plmn_list,
2622 &mm_data->reg.eqv_plmns.eqv_plmn_list,
2623 sizeof (EPLMNLIST_SIZE*UBYTES_PER_PLMN));
2624 /*added by jennifer for 134 sim card issue */
2625 if((rr_activate_req->plmn.mcc[0]==4)
2626 && (rr_activate_req->plmn.mcc[1]==6)
2627 &&(rr_activate_req->plmn.mcc[2]==0)
2628 &&(rr_activate_req->plmn.mnc[0]==0)
2629 &&(rr_activate_req->plmn.mnc[1]==2))
2630 {
2631 rr_activate_req->plmn.mnc[1]=0;
2632 }
2633 /*added by jennifer for 134 sim card issue*/
2634
2635 TRACE_EVENT_P7 ("RR_ACT_REQ (%d) MCC=%X%X%X MNC=%X%X%X",
2636 rr_activate_req->op.func,
2637 rr_activate_req->plmn.mcc[0],
2638 rr_activate_req->plmn.mcc[1],
2639 rr_activate_req->plmn.mcc[2],
2640 rr_activate_req->plmn.mnc[0],
2641 rr_activate_req->plmn.mnc[1],
2642 rr_activate_req->plmn.mnc[2]);
2643
2644 PSENDX (RR, rr_activate_req);
2645 }
2646
2647
2648 /*
2649 +--------------------------------------------------------------------+
2650 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2651 | STATE : code ROUTINE : mm_rr_data_req |
2652 +--------------------------------------------------------------------+
2653
2654 PURPOSE : This function sends the CM_SERVICE_REQUEST message to the
2655 network if a CM entity is requesting an additional connection.
2656
2657 */
2658
2659 GLOBAL void mm_rr_data_req (USHORT est_cause, UBYTE service, UBYTE ti)
2660 {
2661 GET_INSTANCE_DATA;
2662 USHORT bit_size_message = 0;
2663
2664 TRACE_FUNCTION ("mm_rr_data_req ()");
2665
2666 mm_create_est_message (est_cause,
2667 service,
2668 ti,
2669 &bit_size_message);
2670 for_data_req (bit_size_message);
2671 mm_data->wait_for_accept = TRUE;
2672 }
2673
2674
2675 /*
2676 +--------------------------------------------------------------------+
2677 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2678 | STATE : code ROUTINE : mm_rr_est_req |
2679 +--------------------------------------------------------------------+
2680
2681 PURPOSE : This functions creates and sends the RR_ESTABLISH_REQ
2682 primitive. A RR connection is requested.
2683
2684 */
2685
2686 GLOBAL void mm_rr_est_req (USHORT est_cause,
2687 UBYTE service,
2688 UBYTE ti)
2689 {
2690 GET_INSTANCE_DATA;
2691 USHORT bit_size_message = 0;
2692 MCAST (loc_upd_req, U_LOC_UPD_REQ);
2693
2694 TRACE_FUNCTION ("mm_rr_est_req ()");
2695
2696 if (est_cause EQ ESTCS_SERV_REQ_BY_MM)
2697 {
2698 /* LOCATION UPDATING only, IMSI DETACH not handled here */
2699
2700 mm_create_est_message (est_cause, service, ti,
2701 &bit_size_message);
2702
2703 if (mm_data->reg.update_stat EQ MS_NOT_UPDATED)
2704 loc_upd_req->ciph_key_num.key_seq = CKSN_RES;
2705
2706 for_est_req (est_cause, bit_size_message);
2707 }
2708 else
2709 {
2710 /* All the CM stuff */
2711
2712 #ifdef GPRS
2713 assert (GET_STATE (STATE_GPRS_CM_EST) EQ REG_GPRS_INACTIVE OR
2714 GET_STATE (STATE_GPRS_CM_EST) EQ CM_GPRS_EST_OK);
2715 #endif
2716
2717 mm_create_est_message (est_cause, service, ti,
2718 &bit_size_message);
2719
2720 for_est_req (est_cause, bit_size_message);
2721 }
2722 }
2723
2724
2725 /*
2726 +--------------------------------------------------------------------+
2727 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2728 | STATE : code ROUTINE : mm_start_loc_upd |
2729 +--------------------------------------------------------------------+
2730
2731 PURPOSE : This function starts a location update.
2732 The type of the location update will be given in
2733 loc_upd_type and is one of NORMAL_LUP, PERIODIC_LUP or
2734 IMSI_ATTACH_LUP.
2735
2736 */
2737 GLOBAL void mm_start_loc_upd (UBYTE loc_upd_type)
2738 {
2739 GET_INSTANCE_DATA;
2740 TRACE_FUNCTION ("mm_start_loc_upd ()");
2741
2742 TRACE_EVENT_P1 ("attempt #%x", mm_data->attempt_cnt + 1);
2743
2744 /* Set the actual plmn to the PLMN selected by RR */
2745 // Added here by HM 13.11.00
2746 mm_data->reg.actual_plmn.v_plmn = V_PLMN_PRES;
2747 memcpy (mm_data->reg.actual_plmn.mcc, mm_data->mm.lai.mcc, SIZE_MCC);
2748 memcpy (mm_data->reg.actual_plmn.mnc, mm_data->mm.lai.mnc, SIZE_MNC);
2749
2750 mm_set_follow_on_request ();
2751 // mm_data->t3212_timeout = FALSE;
2752 mm_data->idle_entry = RRCS_INT_NOT_PRESENT;
2753 mm_data->loc_upd_type.lut = loc_upd_type;
2754 mm_data->limited_cause = MMCS_INT_NOT_PRESENT;
2755
2756 EM_RR_CONECTION_REQUESTED;
2757
2758 /*
2759 * Remember the idle substate MM may have to enter afterwards.
2760 *
2761 * This implementation of MM lacks the implementation of MM_IDLE_LUP_NEEDED
2762 * for the GSM only protocol stack.
2763 * So, we have to use MM_IDLE_NORMAL_SERVICE and MM_IDLE_ATTEMPT_TO_UPDATE
2764 * not as foreseen by ETSI in some certain situations as replacement for
2765 * the missing state MM_IDLE_LUP_NEEDED.
2766 */
2767
2768 #if 0 /* Bodybag 2004-01-15; remove latest 2004-07-15 */
2769 // The old code:
2770 // Problem: Remembers MM_IDLE_ATTEMPT_TO_UPDATE even if IMSI ATTACH.
2771 // This is wrong, compare this with GSM 04.08 subclause 4.2.3.
2772 // Problem 2.) Didn't handle GPRS.
2773 switch (GET_STATE(STATE_MM))
2774 {
2775 case MM_IDLE_ATTEMPT_TO_UPDATE:
2776 case MM_WAIT_FOR_RR_ACTIVE:
2777 mm_data->idle_substate = MM_IDLE_ATTEMPT_TO_UPDATE;
2778 break;
2779
2780 default:
2781 mm_data->idle_substate = MM_IDLE_NORMAL_SERVICE;
2782 break;
2783 }
2784 #endif
2785
2786 if (mm_data->reg.update_stat EQ MS_UPDATED)
2787 mm_data->idle_substate = MM_IDLE_NORMAL_SERVICE;
2788 else
2789 mm_data->idle_substate = MM_IDLE_ATTEMPT_TO_UPDATE;
2790
2791 if (mm_data->rej_cause NEQ RRCS_RND_ACC_FAIL)
2792 mm_data->last_rej_cause = mm_data->rej_cause;
2793
2794 mm_rr_est_req (ESTCS_SERV_REQ_BY_MM, NO_CM_SERVICE, 0);
2795
2796 TIMERSTOP (T3211);
2797 TIMERSTOP (T3213);
2798 mm_data->t3213_restart = 0;
2799
2800 SET_STATE (STATE_MM, MM_WAIT_FOR_RR_CONN_LUP);
2801 }
2802
2803
2804 /*
2805 +--------------------------------------------------------------------+
2806 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2807 | STATE : code ROUTINE : mm_continue_running_update |
2808 +--------------------------------------------------------------------+
2809
2810 PURPOSE : This function continues a running location update.
2811
2812 */
2813 GLOBAL void mm_continue_running_update (void)
2814 {
2815 GET_INSTANCE_DATA;
2816 TRACE_FUNCTION ("mm_continue_running_update()");
2817
2818 switch (mm_data->loc_upd_type.lut)
2819 {
2820 case NORMAL_LUP:
2821 mm_normal_loc_upd ();
2822 break;
2823 case PERIODIC_LUP:
2824 mm_periodic_loc_upd ();
2825 break;
2826 case IMSI_ATTACH_LUP:
2827 mm_attach_loc_upd ();
2828 break;
2829 default: /* No updating procedure in progress */
2830 break;
2831 }
2832 }
2833
2834
2835 /*
2836 +--------------------------------------------------------------------+
2837 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2838 | STATE : code ROUTINE : mm_start_net_req |
2839 +--------------------------------------------------------------------+
2840
2841 PURPOSE : This function starts a network request.
2842
2843 */
2844
2845 GLOBAL void mm_start_net_req (void)
2846 {
2847 GET_INSTANCE_DATA;
2848 TRACE_FUNCTION ("mm_start_net_req ()");
2849
2850 mm_data->reg.op.func = FUNC_NET_SRCH_BY_MMI;
2851 mm_rr_act_req ();
2852
2853 /*
2854 * 19.7 PLMN SEARCH
2855 * The mobile station is searching for PLMNs, and the conditions for
2856 * state 19.8 are not met. This state is ended when either a cell is
2857 * selected (the new state is 19.1, 19.3 or 19.6),
2858 * or when it is concluded that no cell is available for the moment
2859 * (the new state is 19.5). [GSM 04.08 subclause 4.1.2.1.2]
2860 */
2861
2862 /*
2863 * 19.8 PLMN SEARCH, NORMAL SERVICE
2864 * Valid subscriber data are available, update status is U1, a cell is
2865 * selected which belongs to the LA where the subscriber is registered,
2866 * and the mobile station is searching for PLMNs. This state is ended
2867 * when either a cell is selected (the new state is 19.1, 19.3 or 19.6),
2868 * or when it is concluded that no cell is available for the moment
2869 * (the new state is 19.5). [GSM 04.08 subclause 4.1.2.1.2]
2870 */
2871
2872 /*
2873 * MM will enter MM_PLMN_SEARCH_NORMAL_SERVICE in the current implementation
2874 * also if update state is different from U1 e.g. if MM is in state
2875 * MM_IDLE_ATTEMPT_TO_UPDATE. This makes sense, as the update state can be
2876 * queried to find this condition.
2877 */
2878
2879 switch (GET_STATE (STATE_MM))
2880 {
2881 case MM_IDLE_NORMAL_SERVICE: /* 19.1 */
2882 case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */
2883 #ifdef GPRS
2884 case MM_IDLE_LUP_NEEDED: /* 19.6 */
2885 #endif /* GPRS */
2886 /* Remember the type of IDLE state MM had before network search */
2887 mm_data->idle_substate = GET_STATE (STATE_MM);
2888 SET_STATE (STATE_MM, MM_PLMN_SEARCH_NORMAL_SERVICE);
2889 break;
2890
2891 case MM_IDLE_PLMN_SEARCH: /* 19.7 */
2892 break; /* No state change */
2893
2894 case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */
2895 break; /* No state change */
2896
2897 case MM_IDLE_LIMITED_SERVICE: /* 19.3 */
2898 case MM_IDLE_NO_IMSI: /* 19.4 */
2899 /* Remember the type of IDLE state MM had before network search */
2900 mm_data->idle_substate = GET_STATE (STATE_MM);
2901 SET_STATE (STATE_MM, MM_IDLE_PLMN_SEARCH);
2902 break;
2903
2904 case MM_NULL:
2905 case MM_WAIT_FOR_RR_ACTIVE: /* 18 */
2906 case MM_IDLE_NO_CELL_AVAILABLE: /* 19.5 */
2907 mm_data->idle_substate = MM_IDLE_NO_CELL_AVAILABLE;
2908 SET_STATE (STATE_MM, MM_IDLE_PLMN_SEARCH);
2909 break;
2910
2911 #ifdef GPRS
2912 case MM_LOCATION_UPDATING_PENDING:
2913 case MM_IMSI_DETACH_PENDING:
2914 /* What is happening here? Re-think again about this ... */
2915 TRACE_EVENT ("Interesting protocol sequence");
2916
2917 /* Back to last IDLE substate */
2918 SET_STATE (STATE_MM, mm_data->idle_substate);
2919
2920 /* Repeat this in old IDLE state */
2921 mm_start_net_req ();
2922 return;
2923 #endif /* GPRS */
2924
2925 default:
2926 TRACE_EVENT ("No IDLE state at network search. Observe this"); // ...
2927 mm_data->idle_substate = MM_IDLE_NO_CELL_AVAILABLE;
2928 SET_STATE (STATE_MM, MM_IDLE_PLMN_SEARCH);
2929 break;
2930 }
2931 }
2932
2933
2934 /*
2935 +--------------------------------------------------------------------+
2936 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2937 | STATE : code ROUTINE : mm_start_t3212_bcch |
2938 +--------------------------------------------------------------------+
2939
2940 PURPOSE : Start the periodic location updating timer T3212 with the
2941 broadcasted value. This is done in two situations: First,
2942 after power on and no IMSI ATTACH / NORMAL UPDATE is needed
2943 and second at return to IDLE state after network contact.
2944 The case where no periodic update timer exists is
2945 handled also, in this case T3212 is stopped.
2946 If T3212 is running it is left alone and not restarted,
2947 so it is ensured that no periodic location updating is
2948 missed if a dedicated connection to the network is released
2949 in e.g. state MM_WAIT_FOR_NW_COMMAND, but the conditions in
2950 GSM 04.08 subclause 4.4.2 were not met to stop the timer (e.g.
2951 no MM message received or emergeny call and the previous
2952 IDLE state was MM_IDLE_LIMITED_SERVICE.
2953
2954 */
2955
2956 GLOBAL void mm_start_t3212_bcch (void)
2957 {
2958 GET_INSTANCE_DATA;
2959 T_TIME t3212_time;
2960
2961 TRACE_FUNCTION ("mm_start_t3212_bcch()");
2962
2963 #ifdef GPRS
2964 if ((mm_data->mm.mm_info.t3212 EQ 0) OR mm_data->gprs.combined_procedures)
2965 #else
2966 if (mm_data->mm.mm_info.t3212 EQ 0)
2967 #endif /* GPRS */
2968 {
2969 /*
2970 * No periodic location updating timer
2971 */
2972 TIMERSTOP (T3212);
2973 mm_data->t3212_timeout = FALSE;
2974 }
2975 else
2976 {
2977 /*
2978 * Start T3212 with broadcasted value only if not already running
2979 */
2980 if (!TIMERACTIVE (T3212))
2981 {
2982 TRACE_EVENT ("T3212 start BCCH");
2983 if (mm_data->t3212_cfg_counter NEQ 0)
2984 t3212_time = T_T3212_TIC_VALUE * mm_data->t3212_cfg_counter;
2985 else
2986 t3212_time = T_T3212_TIC_VALUE * 36 * mm_data->mm.mm_info.t3212;
2987 TIMERSTART (T3212, t3212_time);
2988 }
2989 }
2990 }
2991
2992
2993 /*
2994 +--------------------------------------------------------------------+
2995 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2996 | STATE : code ROUTINE : mm_change_t3212 |
2997 +--------------------------------------------------------------------+
2998
2999 PURPOSE : This function starts/restarts the periodic updating timer
3000 with a new value if a change of the broadcasted value
3001 was detected, either by receiving RR_ACTIVATE_CNF,
3002 RR_ACTIVATE_IND or RR_SYNC_IND.
3003
3004 */
3005
3006 GLOBAL void mm_change_t3212 (void)
3007 {
3008 GET_INSTANCE_DATA;
3009 T_TIME t3212_time;
3010
3011 TRACE_FUNCTION ("mm_change_t3212 ()");
3012
3013 #ifdef GPRS
3014 if ((mm_data->mm.mm_info.t3212 EQ 0) OR mm_data->gprs.combined_procedures)
3015 #else
3016 if (mm_data->mm.mm_info.t3212 EQ 0)
3017 #endif /* GPRS */
3018 {
3019 /*
3020 * No periodic location updating timer
3021 */
3022 TIMERSTOP (T3212);
3023 mm_data->t3212_timeout = FALSE;
3024 }
3025 else
3026 {
3027 if (TIMERACTIVE(T3212) OR mm_data->t3212_timeout)
3028 {
3029 if (!mm_data->t3212_timeout)
3030 {
3031 T_TIME remaining_time;
3032 /*
3033 * T3212 is running and there maybe changes.
3034 * Restart T3212 with remaining time modulo BCCH value.
3035 * Nothing will happen here if the BCCH time is
3036 * greater or equal the remaining time (modulo operator),
3037 * so we avoid TIMERSTOP / TIMERSTART in this case also.
3038 */
3039 #if defined (NEW_FRAME)
3040 TIMER_STATUS (mm_handle, T3212, &remaining_time);
3041 #else
3042 TIMER_STATUS (mm_handle, mm_data->t_handle[T3212], &remaining_time);
3043 #endif
3044 t3212_time =
3045 remaining_time % (mm_data->mm.mm_info.t3212 * 36 * T_T3212_TIC_VALUE);
3046 if (t3212_time NEQ remaining_time)
3047 {
3048 TRACE_EVENT ("T3212 restart modulo");
3049 TIMERSTOP (T3212); // Neccessary ?
3050 #ifdef WIN32
3051 vsi_o_ttrace(VSI_CALLER TC_EVENT,
3052 "Modulo time = %d", t3212_time);
3053 #endif
3054 TIMERSTART (T3212, t3212_time);
3055 }
3056 }
3057 }
3058 else
3059 {
3060 if (mm_data->first_attach)
3061 {
3062 /*
3063 * First activation after power on and no IMSI ATTACH,
3064 * start T3212 with broadcasted value.
3065 */
3066 mm_start_t3212_bcch ();
3067 }
3068 else
3069 {
3070 /*
3071 * changes detected, T3212 is not running and it is not the first
3072 * activation. Restart T3212 with random value between 0 and BCCH.
3073 */
3074 TRACE_EVENT ("T3212 restart random");
3075 if (mm_data->t3212_cfg_counter NEQ 0)
3076 {
3077 t3212_time = mm_data->t3212_cfg_counter;
3078 }
3079 else
3080 {
3081 t3212_time =
3082 T_T3212_TIC_VALUE *
3083 mm_random ((USHORT)(mm_data->mm.mm_info.t3212 * 36));
3084 }
3085 TIMERSTART (T3212, t3212_time);
3086 }
3087 }
3088 }
3089 }
3090
3091 /*
3092 +--------------------------------------------------------------------+
3093 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3094 | STATE : code ROUTINE : mm_use_entry |
3095 +--------------------------------------------------------------------+
3096
3097 PURPOSE : This functions marks all entries in the stored event table
3098 which are marked as "STORED" as "USE". Then these events
3099 are processed by mm_read_entry(). mm_read_entry() will
3100 re-build the respective primitive for each event which
3101 is marked as "USE" and sent it to MM, giving it a new
3102 chance to be processed by MM. For timers, the respective
3103 handling function will be called.
3104
3105 */
3106
3107 GLOBAL void mm_use_entry (void)
3108 {
3109 GET_INSTANCE_DATA;
3110 SHORT i;
3111
3112 TRACE_FUNCTION ("mm_use_entry ()");
3113
3114 for (i = 0; i < MAX_STORE_ENTRIES; i++)
3115 {
3116 if (mm_data->store[i].use EQ STORED)
3117 mm_data->store[i].use = USE;
3118 }
3119
3120 while (mm_data->store[0].use EQ USE)
3121 mm_read_entry ();
3122 }
3123
3124 /*
3125 +--------------------------------------------------------------------+
3126 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3127 | STATE : code ROUTINE : mm_write_entry |
3128 +--------------------------------------------------------------------+
3129
3130 PURPOSE : SDL SAVE
3131 This function saves a primitive which cannot be used
3132 in the current state, but may be used after the next
3133 state transition. If content_type is given as EVENT_ENTRY
3134 storing is done for the data component, TI and establ. cause.
3135 If another primitive is to be stored, the pointer is set to
3136 the T_PRIM_HEADER and stored.
3137 */
3138
3139 GLOBAL void mm_write_entry (UBYTE comp,
3140 UBYTE ti,
3141 USHORT estcs,
3142 U8 content_type,
3143 void *primitive,
3144 U8 info)
3145 {
3146 GET_INSTANCE_DATA;
3147 USHORT i;
3148
3149 TRACE_FUNCTION ("mm_write_entry ()");
3150
3151 for (i = 0; i < MAX_STORE_ENTRIES; i++)
3152 {
3153 if (mm_data->store[i].use EQ ENTRY_FREE)
3154 {
3155 TRACE_EVENT_P2 ("Write entry: comp=%d, ti=%d", comp, ti);
3156
3157 mm_data->store[i].use = STORED;
3158 mm_data->store[i].content_type = content_type;
3159 if (content_type EQ EVENT_ENTRY)
3160 {
3161 mm_data->store[i].content.event.ti = ti;
3162 mm_data->store[i].content.event.estcs = estcs;
3163 mm_data->store[i].content.event.comp = comp;
3164 mm_data->store[i].info = info;
3165 if (comp < NUM_OF_CM_ENT)
3166 {
3167 CM_SET_STATE (comp, ti, CM_STORE);
3168 }
3169 }
3170 else
3171 {
3172 mm_data->store[i].content.primitive = D2P(primitive);
3173 }
3174 return;
3175 }
3176 }
3177 }
3178
3179 /*
3180 +--------------------------------------------------------------------+
3181 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3182 | STATE : code ROUTINE : mm_check_lai |
3183 +--------------------------------------------------------------------+
3184
3185 PURPOSE : This function checks whether two given location areas
3186 identifications (MCC, MNC and LAC) are identical.
3187 Returns TRUE if LAIs are identical, otherwise FALSE.
3188
3189 */
3190
3191 GLOBAL BOOL mm_check_lai (const T_loc_area_ident * lai1,
3192 const T_loc_area_ident * lai2)
3193 {
3194 TRACE_FUNCTION ("mm_check_lai ()");
3195
3196 return ((memcmp (lai1->mcc, lai2->mcc, SIZE_MCC) EQ 0) AND
3197 (memcmp (lai1->mnc, lai2->mnc, SIZE_MNC) EQ 0) AND
3198 lai1->lac EQ lai2->lac);
3199 }
3200
3201
3202 /*
3203 +--------------------------------------------------------------------+
3204 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3205 | STATE : code ROUTINE : mm_check_lai_from_RR |
3206 +--------------------------------------------------------------------+
3207
3208 PURPOSE : This function compares the PLMN and location area in the
3209 form delivered by RR and in and T_plmn structure
3210 for equality. Returns TRUE if the PLMNs and location areas
3211 are equal, otherwise FALSE.
3212
3213 */
3214
3215 GLOBAL BOOL mm_check_lai_from_RR (const T_loc_area_ident * lai1,
3216 const T_plmn * plmn2,
3217 USHORT lac2)
3218 {
3219 TRACE_FUNCTION ("mm_check_lai_from_RR ()");
3220
3221 return (memcmp (lai1->mcc, plmn2->mcc, SIZE_MCC) EQ 0 AND
3222 memcmp (lai1->mnc, plmn2->mnc, SIZE_MNC) EQ 0 AND
3223 lai1->lac EQ lac2);
3224 }
3225
3226
3227 /*
3228 +--------------------------------------------------------------------+
3229 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3230 | STATE : code ROUTINE : mm_normal_upd_needed |
3231 +--------------------------------------------------------------------+
3232
3233 PURPOSE : This function returns TRUE if a normal updating is needed.
3234
3235 */
3236
3237 GLOBAL BOOL mm_normal_upd_needed (void)
3238 {
3239 GET_INSTANCE_DATA;
3240 TRACE_FUNCTION ("mm_normal_upd_needed()");
3241
3242 if (mm_data->reg.update_stat EQ MS_UPDATED AND
3243 mm_check_lai (&mm_data->reg.lai, &mm_data->mm.lai))
3244 return FALSE;
3245 return TRUE;
3246 }
3247
3248
3249 /*
3250 +--------------------------------------------------------------------+
3251 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3252 | STATE : code ROUTINE : mm_attach_upd_needed |
3253 +--------------------------------------------------------------------+
3254
3255 PURPOSE : This function returns TRUE if an IMSI ATTACH is needed.
3256
3257 */
3258
3259 GLOBAL BOOL mm_attach_upd_needed (void)
3260 {
3261 GET_INSTANCE_DATA;
3262 TRACE_FUNCTION ("mm_attach_upd_needed()");
3263
3264 if (mm_data->mm.mm_info.att EQ ATT_ALLOW AND mm_data->first_attach)
3265 return TRUE;
3266 return FALSE;
3267 }
3268
3269
3270 /*
3271 +--------------------------------------------------------------------+
3272 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3273 | STATE : code ROUTINE : mm_periodic_upd_needed |
3274 +--------------------------------------------------------------------+
3275
3276 PURPOSE : This function returns TRUE if a periodic location update
3277 is immediately needed. This can happen if T3212 expired
3278 in a no coverage situation.
3279
3280 */
3281
3282 GLOBAL BOOL mm_periodic_upd_needed (void)
3283 {
3284 GET_INSTANCE_DATA;
3285 TRACE_FUNCTION ("mm_periodic_upd_needed()");
3286
3287 if (mm_data->t3212_timeout AND mm_data->mm.mm_info.t3212 NEQ 0)
3288 return TRUE;
3289 return FALSE;
3290 }
3291
3292
3293 /*
3294 +--------------------------------------------------------------------+
3295 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3296 | STATE : code ROUTINE : mm_end_of_detach |
3297 +--------------------------------------------------------------------+
3298
3299 PURPOSE : This function performs all actions which are done
3300 at the end of a detach operation. This function may
3301 be called due reception of the primitives RR_RELEASE_IND or
3302 RR_ABORT_IND. In case the end of the IMSI DETACH procedure
3303 was caused by a timeout of T3220, the RR connection has been
3304 aborted normally and this function is called after the
3305 release has been acknowledged by RR_RELEASE_IND from RR.
3306
3307 */
3308
3309 GLOBAL void mm_end_of_detach (void)
3310 {
3311 GET_INSTANCE_DATA;
3312 TRACE_FUNCTION ("mm_end_of_detach()");
3313
3314 TIMERSTOP (T3220);
3315
3316 switch (mm_data->nreg_cause)
3317 {
3318 case CS_SIM_REM:
3319 /* Send RR_ABORT_REQ with ABCS_SIM_REM to invalidate SIM in RR */
3320 mm_abort_connection (ABCS_SIM_REM);
3321
3322 // This may be done instead RR_ABORT_REQ
3323 // mm_build_rr_sync_req_cause (SYNCCS_TMSI_CKSN_KC_INVAL_NO_PAG);
3324
3325 mm_clear_reg_data ();
3326
3327 // Find original place where MM entered MM_IDLE_NO_IMSI state >>>
3328 if (mm_data->mm_idle_no_imsi_marker EQ 0)
3329 mm_data->mm_idle_no_imsi_marker = 5;
3330 // End of debugging patch <<<
3331 SET_STATE (STATE_MM, MM_IDLE_NO_IMSI);
3332
3333 reg_end_of_deregistration (mm_data->nreg_cause, LIMITED_SERVICE);
3334 break;
3335
3336 case CS_POW_OFF:
3337 case CS_SOFT_OFF:
3338 mm_power_off ();
3339 reg_end_of_deregistration (mm_data->nreg_cause, NO_SERVICE);
3340 break;
3341
3342 #ifdef GPRS
3343 case CS_DISABLE:
3344 /* Remember MM may have to perform IMSI ATTACH if reactivated */
3345 mm_data->first_attach = TRUE;
3346
3347 /*
3348 * Find appropriate IDLE state after disabling of CS GSM.
3349 * If there was really an IMSI DETACH before, the new state
3350 * will be MM_IDLE_LUP_NEEDED as the old state was
3351 * MM_IDLE_LIMITED_SERVICE and now at least an IMSI ATTACH
3352 * is needed again, but if not really a DETACH was performed,
3353 * also another IDLE state may be entered.
3354 */
3355 if (mm_data->reg.op.sim_ins EQ SIM_NO_INSRT)
3356 {
3357 SET_STATE (STATE_MM, MM_IDLE_NO_IMSI);
3358 }
3359 else if (mm_data->idle_substate EQ MM_IDLE_LIMITED_SERVICE)
3360 {
3361 SET_STATE (STATE_MM, MM_IDLE_LIMITED_SERVICE);
3362 }
3363 else if (mm_normal_upd_needed () OR mm_attach_upd_needed())
3364 {
3365 SET_STATE (STATE_MM, MM_IDLE_LUP_NEEDED);
3366 }
3367 else
3368 {
3369 SET_STATE (STATE_MM, MM_IDLE_NORMAL_SERVICE);
3370 }
3371
3372 /* Confirm the requested deregistration */
3373 mm_mmgmm_nreg_cnf (mm_data->nreg_cause);
3374 break;
3375 #endif /* GPRS */
3376
3377 default:
3378 TRACE_ERROR (UNEXPECTED_DEFAULT);
3379 break;
3380 }
3381 }
3382
3383
3384 /*
3385 +--------------------------------------------------------------------+
3386 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3387 | STATE : code ROUTINE : mm_get_service_state |
3388 +--------------------------------------------------------------------+
3389
3390 PURPOSE : This function is used to get the service state from
3391 the MM main state and/or the service state.
3392 The return value of this function is expected to be in the
3393 range of states 19.1..19.6 for GPRS and 19.1..19.5 for GSM.
3394 The function shall only be used if leaving idle state and
3395 entering some sort of dedicated state.
3396
3397 */
3398
3399 GLOBAL UBYTE mm_get_service_state (void)
3400 {
3401 GET_INSTANCE_DATA;
3402 TRACE_FUNCTION ("mm_get_service_state()");
3403
3404 switch (GET_STATE (STATE_MM))
3405 {
3406 case MM_NULL: /* 0 */
3407 /*
3408 * In MM_NULL state, the mobile is switched off, so there is no cell.
3409 */
3410 return MM_IDLE_NO_CELL_AVAILABLE;
3411
3412 case MM_WAIT_FOR_RR_CONN_LUP: /* 13 */
3413 case MM_WAIT_FOR_RR_ACTIVE: /* 18 */
3414 /*
3415 * MM has a cell which may be good for full service.
3416 * MM has also a valid SIM (IMSI).
3417 *
3418 * This implementation of MM lacks the implementation of
3419 * state MM_IDLE_LUP_NEEDED for the GSM only protocol stack.
3420 * MM_IDLE_LUP_NEEDED is only used in this implementation if MM needs
3421 * an update with GPRS, but GPRS has not yet triggered the updating.
3422 * So we have to use MM_IDLE_NORMAL_SERVICE and MM_IDLE_ATTEMPT_TO_UPDATE
3423 * not as foreseen by ETSI in some certain situations as replacement for
3424 * the missing state MM_IDLE_LUP_NEEDED.
3425 */
3426 if (mm_data->reg.update_stat EQ MS_UPDATED)
3427 return MM_IDLE_NORMAL_SERVICE;
3428 else
3429 return MM_IDLE_ATTEMPT_TO_UPDATE;
3430
3431 case MM_IDLE_NORMAL_SERVICE: /* 19.1 */
3432 case MM_IDLE_ATTEMPT_TO_UPDATE: /* 19.2 */
3433 case MM_IDLE_LIMITED_SERVICE: /* 19.3 */
3434 case MM_IDLE_NO_IMSI: /* 19.4 */
3435 case MM_IDLE_NO_CELL_AVAILABLE: /* 19.5 */
3436 #ifdef GPRS
3437 case MM_IDLE_LUP_NEEDED: /* 19.6, not used by GSM only stack */
3438 #endif /* GPRS */
3439 /*
3440 * In the cases of 19.1..19.5 (GSM only) or 19.1..19.6 (GPRS also)
3441 * the service state is simply the appropriate MM IDLE state.
3442 */
3443 return GET_STATE (STATE_MM);
3444
3445 case MM_IDLE_PLMN_SEARCH: /* 19.7 */
3446 case MM_PLMN_SEARCH_NORMAL_SERVICE: /* 19.8 */
3447 /*
3448 * For the searching IDLE states, no respective service state exists.
3449 * This is due to the fact that the information that RR is searching
3450 * for a network can be obtained by reading the MM main state.
3451 * It is more interesting if CM wants to perform a call to know the
3452 * IDLE state before the mobile has started network search.
3453 */
3454 return mm_data->idle_substate;
3455
3456 default:
3457 /*
3458 * Some sort of dedicated state. This cannot/need not be used to
3459 * determine the service state.
3460 */
3461 return mm_data->idle_substate;
3462 }
3463 }
3464
3465
3466 /*
3467 +----------------------------------------------------------------------------+
3468 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3469 | STATE : code ROUTINE : mm_full_service_pplmn_scan |
3470 +----------------------------------------------------------------------------+
3471
3472 PURPOSE : This states according to MM main state whether the PPLMN
3473 rescan procedure could be applicable.
3474
3475
3476 */
3477
3478 GLOBAL BOOL mm_full_service_pplmn_scan (void)
3479 {
3480 GET_INSTANCE_DATA;
3481 switch (GET_STATE (STATE_MM))
3482 {
3483 /*
3484 * The 'normal' cases : idle updated states
3485 */
3486 case MM_IDLE_NORMAL_SERVICE:
3487 case MM_PLMN_SEARCH_NORMAL_SERVICE:
3488 /* new introduced
3489 * We also might be in full service but without a valid registration.
3490 */
3491 case MM_IDLE_ATTEMPT_TO_UPDATE:
3492 /*
3493 * RR connection active, which is either for a CM connection which imply
3494 * that we are updated (unless it is an emergency call!) or for a MM
3495 * procedure. If MM procedure fails consistently then we will lose the
3496 * registration data and the timer will be stopped anyway.
3497 */
3498 case MM_WAIT_FOR_OUTG_MM_CONN:
3499 case MM_CONN_ACTIVE:
3500 case MM_PROCESS_PROMPT:
3501 case MM_WAIT_FOR_NW_CMD:
3502 #ifdef REL99
3503 case MM_RR_CONN_RELEASE_NOT_ALLOWED:
3504 #endif
3505 case MM_WAIT_FOR_RR_CONN_MM:
3506 case MM_WAIT_FOR_REESTABLISH:
3507
3508 /*
3509 * It is important not to stop the timer when in this state (check of
3510 * conditions can be done during LUP procedure!)
3511 */
3512 case MM_LUP_INITIATED:
3513 return TRUE;
3514
3515 /*
3516 * If we currently have no or limited service then the standard PLMN
3517 * reselection procedure will apply if automatic mode.
3518 */
3519 case MM_NULL:
3520 case MM_IDLE_LIMITED_SERVICE:
3521 case MM_IDLE_NO_CELL_AVAILABLE:
3522 case MM_IDLE_PLMN_SEARCH:
3523 case MM_WAIT_FOR_RR_ACTIVE:
3524
3525 /*
3526 * We also might be in full service but without a valid registration. No
3527 * point to carry on as HPLMN timer would be started after succesfull GSM
3528 * attach or LUP procedure.
3529 */
3530 case MM_WAIT_FOR_RR_CONN_LUP:
3531 case MM_LUP_REJECTED:
3532 #if defined(GPRS)
3533 case MM_LOCATION_UPDATING_PENDING:
3534 #endif
3535
3536 /*
3537 * No IMSI, detached or in the process to do it. HPLMN rescan does not
3538 * make sense so disregard it.
3539 */
3540 case MM_IMSI_DETACH_INIT:
3541 #if defined(GPRS)
3542 case MM_IMSI_DETACH_PENDING:
3543 #endif
3544 case MM_IDLE_NO_IMSI:
3545 case MM_WAIT_FOR_RR_CONN_DETACH:
3546 return FALSE;
3547
3548 /*
3549 * 3GPP 23.122 clause 4.4.3.4 may apply here and makes life easy:
3550 * "The investigation scan is restricted to automatic selection mode and
3551 * shall only be performed by an MS that is capable of both voice and
3552 * packet data."
3553 */
3554 #ifdef GPRS
3555 case MM_IDLE_LUP_NEEDED:
3556 return FALSE;
3557 #endif /* #ifdef GPRS */
3558
3559 default:
3560 TRACE_ERROR (UNEXPECTED_DEFAULT);
3561 return FALSE;
3562 }
3563 }
3564
3565 /*
3566 +--------------------------------------------------------------------+
3567 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3568 | STATE : code ROUTINE : mm_read_ffs_init |
3569 +--------------------------------------------------------------------+
3570
3571 PURPOSE : This function is the initial read of ffs by MM.
3572 */
3573
3574 const char eplmn_list_name[] = "/gsm/l3/eplmn";
3575 /* added by jennifer to write simloci to FFS */
3576 //int Writesimloci = 1;
3577 //if(Writesimloci)
3578 const char simloci_name[] = "/gsm/l3/simloci";
3579 T_loc_info loc_info_ffs;
3580 /* added by jennifer to write simloci to FFS */
3581
3582 const char imsi_name[] = "/gsm/l3/imsi";
3583 T_imsi_struct imsi_in_ffs;
3584
3585
3586 GLOBAL void mm_read_ffs_init(void)
3587 {
3588 GET_INSTANCE_DATA;
3589
3590 TRACE_FUNCTION ("mm_read_ffs_init()");
3591
3592 /* If MM has to create the directories for FFS, there is no point in carry on with the */
3593 /* initialisation */
3594 if(mm_check_ffs_dirs())
3595 return;
3596
3597 if(mm_read_ffs())
3598 {
3599 /*Successful read*/
3600
3601 /*
3602 * Compare IMSIs...
3603 */
3604 if(!(reg_imsi_equal(&mm_data->reg.eqv_plmns.eqv_plmn_imsi,
3605 &mm_data->reg.imsi_struct)))
3606 {
3607 /*
3608 * Remove old EPLMN list
3609 */
3610 memset (&mm_data->reg.eqv_plmns.eqv_plmn_list, 0xFF, EPLMNLIST_SIZE*UBYTES_PER_PLMN);
3611
3612 /*
3613 * Write the new IMSI
3614 */
3615 mm_data->reg.eqv_plmns.eqv_plmn_imsi = mm_data->reg.imsi_struct; /*Struct Copy*/
3616 mm_write_eplmn_to_ffs();
3617 }
3618 }
3619 }
3620
3621 /*
3622 +--------------------------------------------------------------------+
3623 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3624 | STATE : code ROUTINE : mm_read_ffs |
3625 +--------------------------------------------------------------------+
3626
3627 PURPOSE : This function reads the EPLMN from the ffs by MM.
3628 */
3629
3630 GLOBAL BOOL mm_read_ffs(void)
3631 {
3632 GET_INSTANCE_DATA;
3633 TRACE_FUNCTION ("mm_read_ffs()");
3634
3635 return (mm_handle_ffs_read_result(ffs_file_read (eplmn_list_name,
3636 &mm_data->reg.eqv_plmns,
3637 sizeof(T_ffs_eplmn_imsi))));
3638 }
3639
3640 /*
3641 +--------------------------------------------------------------------+
3642 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3643 | STATE : code ROUTINE : mm_read_ffs |
3644 +--------------------------------------------------------------------+
3645
3646 PURPOSE : This function resets the EPLMN data and writes the empty
3647 data to the FFS
3648 */
3649
3650 GLOBAL void mm_reset_ffs(void)
3651 {
3652 GET_INSTANCE_DATA;
3653 TRACE_FUNCTION ("mm_reset_ffs()");
3654
3655 memset (&mm_data->reg.eqv_plmns.eqv_plmn_list,
3656 0xFF,
3657 EPLMNLIST_SIZE*UBYTES_PER_PLMN);
3658
3659 mm_write_eplmn_to_ffs();
3660 }
3661
3662 /*
3663 +--------------------------------------------------------------------+
3664 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3665 | STATE : code ROUTINE : mm_write_eplmn_to_ffs |
3666 +--------------------------------------------------------------------+
3667
3668 PURPOSE : This function writes the current EPLMN list to the
3669 FFS
3670 */
3671
3672 GLOBAL void mm_write_eplmn_to_ffs(void)
3673 {
3674 GET_INSTANCE_DATA;
3675 TRACE_FUNCTION ("mm_write_eplmn_to_ffs()");
3676
3677 mm_check_ffs_dirs();
3678 mm_handle_ffs_write_result(ffs_file_write (eplmn_list_name,
3679 &mm_data->reg.eqv_plmns,
3680 sizeof(T_ffs_eplmn_imsi),
3681 FFS_O_CREATE | FFS_O_RDWR));
3682 }
3683 /*add by TISH 0418 to write imsi to FFS*/
3684
3685 GLOBAL void mm_write_imsi_to_ffs(void)
3686 {
3687 GET_INSTANCE_DATA;
3688 TRACE_FUNCTION ("mm_write_imsi_to_ffs()");
3689 mm_check_ffs_dirs();
3690 mm_handle_ffs_write_result(ffs_file_write (imsi_name,
3691 &mm_data->reg.imsi_struct,
3692 sizeof(T_imsi_struct),
3693 FFS_O_CREATE | FFS_O_RDWR));
3694 }
3695
3696 GLOBAL BOOL mm_read_ffs_imsi(void)
3697 {
3698
3699 TRACE_FUNCTION ("mm_read_ffs_imsi");
3700
3701 return (mm_handle_ffs_read_result(ffs_file_read (imsi_name,
3702 &imsi_in_ffs,
3703 sizeof(T_imsi_struct))));
3704 }
3705 /*add by TISH 0418 to write imsi to FFS*/
3706
3707
3708 /* added by TISH 0418 to write simloci to FFS */
3709
3710 GLOBAL void mm_write_simloci_to_ffs(void)
3711 {
3712 GET_INSTANCE_DATA;
3713
3714 ULONG tmsi_binary;
3715
3716 TRACE_FUNCTION ("mm_write_simloci_to_ffs()");
3717
3718 tmsi_binary = mm_data->reg.tmsi;
3719 loc_info_ffs.c_loc = SIZE_LOC_INFO;
3720 loc_info_ffs.loc[0] = (UBYTE)(tmsi_binary >> 24);
3721 loc_info_ffs.loc[1] = (UBYTE)(tmsi_binary >> 16);
3722 loc_info_ffs.loc[2] = (UBYTE)(tmsi_binary >> 8);
3723 loc_info_ffs.loc[3] = (UBYTE)tmsi_binary;
3724 loc_info_ffs.loc[4] = mm_data->reg.lai.mcc[1] << 4;
3725 loc_info_ffs.loc[4] += mm_data->reg.lai.mcc[0];
3726 loc_info_ffs.loc[5] = mm_data->reg.lai.mnc[2] << 4;
3727 loc_info_ffs.loc[5] += mm_data->reg.lai.mcc[2];
3728 loc_info_ffs.loc[6] = mm_data->reg.lai.mnc[1] << 4;
3729 loc_info_ffs.loc[6] += mm_data->reg.lai.mnc[0];
3730 loc_info_ffs.loc[7] = mm_data->reg.lai.lac >> 8;
3731 loc_info_ffs.loc[8] = mm_data->reg.lai.lac & 0xff;
3732 loc_info_ffs.loc[9] = 0;
3733 loc_info_ffs.loc[10] = mm_data->reg.update_stat;
3734
3735 TRACE_EVENT_P7("writelocinfo:%d,%d,%d,%d,%d,%d,%d", loc_info_ffs.loc[4], loc_info_ffs.loc[5], loc_info_ffs.loc[6], loc_info_ffs.loc[7],
3736 loc_info_ffs.loc[8], loc_info_ffs.loc[9], loc_info_ffs.loc[10]);
3737 mm_check_ffs_dirs();
3738 mm_handle_ffs_write_result(ffs_file_write (simloci_name,
3739 &loc_info_ffs,
3740 sizeof(T_loc_info),
3741 FFS_O_CREATE | FFS_O_RDWR));
3742
3743 }
3744
3745 GLOBAL BOOL mm_read_ffs_simloci(void)
3746 {
3747
3748 TRACE_FUNCTION ("mm_read_ffs_simloci");
3749
3750 return (mm_handle_ffs_read_result(ffs_file_read (simloci_name,
3751 &loc_info_ffs,
3752 sizeof(T_loc_info))));
3753 }
3754 /* added by TISH 0418 to write simloci to FFS */
3755
3756 /*
3757 +--------------------------------------------------------------------+
3758 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3759 | STATE : code ROUTINE : mm_check_ffs_dirs |
3760 +--------------------------------------------------------------------+
3761
3762 PURPOSE : This routine creates the /gsm/l3 directory for the eplmn
3763 file in the FFS. The return result indicates whether either
3764 directories existed or not. There is no error handling.
3765 */
3766
3767 LOCAL BOOL mm_check_ffs_dirs( void )
3768 {
3769 const char gsm_name[] = "/gsm";
3770 const char gsm_l3_name[] = "/gsm/l3";
3771 BOOL x, y;
3772
3773 x = mm_create_ffs_dirs(gsm_name);
3774 y = mm_create_ffs_dirs(gsm_l3_name);
3775 return(x&&y);
3776 }
3777
3778 /*
3779 +--------------------------------------------------------------------+
3780 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3781 | STATE : code ROUTINE : mm_create_ffs_dirs |
3782 +--------------------------------------------------------------------+
3783
3784 PURPOSE : This routine calls the ffs_mkdir() routine to create a
3785 specified directory. It returns whether the directory
3786 existed or not prior to creation.
3787 */
3788 LOCAL BOOL mm_create_ffs_dirs(const char *dir_name)
3789 {
3790 T_FFS_RET status;
3791 BOOL dirs_present = FALSE;
3792
3793 status=ffs_mkdir(dir_name);
3794 switch(status)
3795 {
3796 case EFFS_EXISTS:
3797 dirs_present = TRUE;
3798 break;
3799
3800 case EFFS_OK:
3801 break;
3802
3803 default: /*Error*/
3804 TRACE_EVENT_P1("Create Dir error - %x",status);
3805 break;
3806 }
3807 return dirs_present;
3808 }
3809
3810 /*
3811 +--------------------------------------------------------------------+
3812 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3813 | STATE : code ROUTINE : mm_handle_ffs_read_result |
3814 +--------------------------------------------------------------------+
3815
3816 PURPOSE : This function checks the status from FFS and returns
3817 TRUE if there is no error and FALSE if there is
3818 */
3819 LOCAL BOOL mm_handle_ffs_read_result(T_FFS_SIZE status_read)
3820 {
3821 if(status_read)
3822 {
3823 TRACE_EVENT ("FFS Read OK");
3824 return TRUE;
3825 }
3826 else
3827 {
3828 TRACE_EVENT_P1("EPLMN Read ERROR - %x", status_read);
3829 return FALSE;
3830 }
3831 }
3832
3833 /*
3834 +--------------------------------------------------------------------+
3835 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3836 | STATE : code ROUTINE : mm_handle_ffs_write_result |
3837 +--------------------------------------------------------------------+
3838
3839 PURPOSE : This function checks the status from FFS and returns
3840 TRUE if there is no error and FALSE if there is
3841 */
3842 LOCAL BOOL mm_handle_ffs_write_result(T_FFS_RET status_write)
3843 {
3844 if(status_write >= EFFS_OK)
3845 {
3846 TRACE_EVENT("FFS Write OK");
3847 if(status_write)
3848 TRACE_EVENT_P1 ("Bytes written: %d",status_write);
3849
3850 return(TRUE);
3851 }
3852 else
3853 {
3854 TRACE_EVENT_P1 ("FFS Write Error - Status: %x",status_write);
3855 return(FALSE);
3856 }
3857 }
3858
3859 /*
3860 +--------------------------------------------------------------------+
3861 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3862 | STATE : code ROUTINE : mm_display_eplmn |
3863 +--------------------------------------------------------------------+
3864
3865 PURPOSE : This function displays the current EPLMN list
3866
3867 */
3868
3869 GLOBAL void mm_display_eplmn(void)
3870 {
3871 GET_INSTANCE_DATA;
3872 TRACE_EVENT ("EPLMN List");
3873 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[0],
3874 mm_data->reg.eqv_plmns.eqv_plmn_list[1],
3875 mm_data->reg.eqv_plmns.eqv_plmn_list[2]);
3876 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[3],
3877 mm_data->reg.eqv_plmns.eqv_plmn_list[4],
3878 mm_data->reg.eqv_plmns.eqv_plmn_list[5]);
3879 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[6],
3880 mm_data->reg.eqv_plmns.eqv_plmn_list[7],
3881 mm_data->reg.eqv_plmns.eqv_plmn_list[8]);
3882 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[9],
3883 mm_data->reg.eqv_plmns.eqv_plmn_list[10],
3884 mm_data->reg.eqv_plmns.eqv_plmn_list[11]);
3885 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[12],
3886 mm_data->reg.eqv_plmns.eqv_plmn_list[13],
3887 mm_data->reg.eqv_plmns.eqv_plmn_list[14]);
3888 TRACE_EVENT_P3 ("%x, %x, %x", mm_data->reg.eqv_plmns.eqv_plmn_list[15],
3889 mm_data->reg.eqv_plmns.eqv_plmn_list[16],
3890 mm_data->reg.eqv_plmns.eqv_plmn_list[17]);
3891
3892 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[0],
3893 mm_data->reg.eqv_plmns.eqv_plmn_list[1],
3894 mm_data->reg.eqv_plmns.eqv_plmn_list[2]);
3895 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[3],
3896 mm_data->reg.eqv_plmns.eqv_plmn_list[4],
3897 mm_data->reg.eqv_plmns.eqv_plmn_list[5]);
3898 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[6],
3899 mm_data->reg.eqv_plmns.eqv_plmn_list[7],
3900 mm_data->reg.eqv_plmns.eqv_plmn_list[8]);
3901 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[9],
3902 mm_data->reg.eqv_plmns.eqv_plmn_list[10],
3903 mm_data->reg.eqv_plmns.eqv_plmn_list[11]);
3904 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[12],
3905 mm_data->reg.eqv_plmns.eqv_plmn_list[13],
3906 mm_data->reg.eqv_plmns.eqv_plmn_list[14]);
3907 TRACE_EVENT_P3 ("%c, %c, %c", mm_data->reg.eqv_plmns.eqv_plmn_list[15],
3908 mm_data->reg.eqv_plmns.eqv_plmn_list[16],
3909 mm_data->reg.eqv_plmns.eqv_plmn_list[17]);
3910
3911 }
3912
3913 /* Implements Measure 29 and streamline encoding */
3914 /*
3915 +--------------------------------------------------------------------+
3916 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
3917 | STATE : code ROUTINE : mm_send_status |
3918 +--------------------------------------------------------------------+
3919
3920 PURPOSE : This function builts and sends status
3921
3922 */
3923 GLOBAL void mm_send_status (UBYTE cause)
3924 {
3925 TRACE_FUNCTION ("mm_send_status ()");
3926
3927 {
3928 MSG_CAST (mm_status, T_B_MM_STATUS);
3929 mm_build_mm_status (cause, mm_status);
3930 for_data_req (BSIZE_B_MM_STATUS);
3931 }
3932 }
3933 #endif