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