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