comparison g23m-gsm/mm/mm_mmf.c @ 0:75a11d740a02

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