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

gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 28 Sep 2014 23:20:04 +0000
parents
children 105ac33aa5a1
comparison
equal deleted inserted replaced
672:0dc6f9e8e980 673:2f7df7a314f8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : GSM-PS (8410)
4 | Modul : MM_REGF
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 registration
18 | capability of the module Mobility Management.
19 +-----------------------------------------------------------------------------
20 */
21
22 #define MM_REGF_C
23 #define ENTITY_MM
24
25 /*==== INCLUDES ===================================================*/
26 #if defined (NEW_FRAME)
27
28 #include <string.h>
29 #include <stdlib.h>
30 #include <stddef.h>
31 #include "typedefs.h"
32 #include "pcm.h"
33 #include "pconst.cdg"
34 #include "mconst.cdg"
35 #include "message.h"
36 #include "ccdapi.h"
37 #include "vsi.h"
38 #include "custom.h"
39 #include "gsm.h"
40 #include "prim.h"
41 #include "cnf_mm.h"
42 #include "mon_mm.h"
43 #include "pei.h"
44 #include "tok.h"
45 #include "mm.h"
46
47 #else
48
49 #include <string.h>
50 #include <stdlib.h>
51 #include <stddef.h>
52 #include "stddefs.h"
53 #include "pcm.h"
54 #include "pconst.cdg"
55 #include "mconst.cdg"
56 #include "message.h"
57 #include "ccdapi.h"
58 #include "custom.h"
59 #include "gsm.h"
60 #include "prim.h"
61 #include "cnf_mm.h"
62 #include "mon_mm.h"
63 #include "vsi.h"
64 #include "pei.h"
65 #include "tok.h"
66 #include "mm.h"
67
68 #endif
69
70 /*==== EXPORT =====================================================*/
71
72 /*==== PRIVAT =====================================================*/
73
74 /*==== VARIABLES ==================================================*/
75 /* added by TISH 0418 to write simloci to FFS */
76 extern T_loc_info loc_info_ffs;
77 extern T_imsi_struct imsi_in_ffs;
78 /* added by TISH 0418 to write simloci to FFS */
79
80 /*==== TEST =====================================================*/
81
82 /*==== FUNCTIONS ==================================================*/
83
84 LOCAL void reg_pack_plmn_fn (USHORT i,
85 const T_RR_ABORT_IND *rr_abort_ind);
86
87 /*==== LOCALS ==================================================*/
88 /* first and last colums are dummies to staisf T_plmn structure*/
89 LOCAL const T_plmn cingular_plmn_list[]=
90 {
91 { 0x1, {0x00, 0x00 ,0x00}, {0x01, 0x08 ,0x00}, 0x1},
92 { 0x1, {0x03, 0x01 ,0x00}, {0x01, 0x05 ,0x00}, 0x1},
93 { 0x1, {0x03, 0x01 ,0x00}, {0x01, 0x07 ,0x00}, 0x1},
94 { 0x1, {0x03, 0x01 ,0x00}, {0x03, 0x08 ,0x00}, 0x1},
95 { 0x1, {0x03, 0x01 ,0x00}, {0x04, 0x01 ,0x00}, 0x1},
96 { 0x1, {0x03, 0x01 ,0x00}, {0x09, 0x08 ,0x00}, 0x1},
97 { 0x1, {0x03, 0x04 ,0x02}, {0x08, 0x01 ,0x00}, 0x1},
98 { 0x1, {0x03, 0x04 ,0x04}, {0x09, 0x03 ,0x00}, 0x1},
99 { 0x1, {0x03, 0x05 ,0x00}, {0x01, 0x00 ,0x0F}, 0x1},
100 { 0x1, {0x03, 0x05 ,0x02}, {0x03, 0x00 ,0x0F}, 0x1},
101 { 0x1, {0x03, 0x05 ,0x08}, {0x03, 0x00 ,0x0F}, 0x1},
102 { 0x1, {0x03, 0x06 ,0x00}, {0x01, 0x00 ,0x0F}, 0x1},
103 { 0x1, {0x03, 0x06 ,0x06}, {0x02, 0x00 ,0x0F}, 0x1}
104 };
105
106 #if !defined(GPRS)
107
108 /*
109 +----------------------------------------------------------------------------+
110 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
111 | STATE : code ROUTINE : reg_send_mmr_reg_cnf |
112 +----------------------------------------------------------------------------+
113
114 PURPOSE : This function builds and sends a MMR_REG_CNF primitive to the MMR SAP.
115 This is only done if G23 is compiled as a GSM only protocol stack
116 without GPRS. Otherwise this function is deactivated.
117
118 */
119
120 GLOBAL void reg_send_mmr_reg_cnf (UBYTE bootup_cause)
121 {
122 GET_INSTANCE_DATA;
123 PALLOC (mmr_reg_cnf, MMR_REG_CNF); /* T_MMR_REG_CNF */
124
125 TRACE_FUNCTION ("reg_send_mmr_reg_cnf()");
126
127 if (bootup_cause NEQ PWR_SCAN_START)
128 {
129 mmr_reg_cnf->plmn.v_plmn = V_PLMN_PRES;
130 memcpy (mmr_reg_cnf->plmn.mcc, mm_data->mm.lai.mcc, SIZE_MCC);
131 memcpy (mmr_reg_cnf->plmn.mnc, mm_data->mm.lai.mnc, SIZE_MNC);
132 }
133 else
134 {
135 mmr_reg_cnf->plmn.v_plmn = V_PLMN_NOT_PRES;
136 }
137 mmr_reg_cnf->lac = mm_data->mm.lai.lac;
138 mmr_reg_cnf->cid = mm_data->mm.cid;
139 mmr_reg_cnf->bootup_cause = bootup_cause;
140 PSENDX (MMI, mmr_reg_cnf);
141 }
142
143 /*
144 +----------------------------------------------------------------------------+
145 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
146 | STATE : code ROUTINE : reg_build_mmr_reg_cnf |
147 +----------------------------------------------------------------------------+
148
149 PURPOSE : This function indicates change in service or change in PLMN to the MMR SAP.
150 This is only done if G23 is compiled as a GSM only protocol stack
151 without GPRS. Otherwise this function is deactivated.
152
153 */
154
155 GLOBAL void reg_build_mmr_reg_cnf (void)
156 {
157 GET_INSTANCE_DATA;
158 TRACE_FUNCTION ("reg_build_mmr_reg_cnf()");
159
160 if ((mm_data->reg.full_service_indicated EQ FALSE) OR
161 (mm_data->reg.new_cell_ind EQ TRUE))
162 {
163 /*
164 * Either no full service was indicated to the MMI,
165 * or the PLMN has changed from that what was indicated before.
166 */
167 reg_send_mmr_reg_cnf (REG_END);
168
169 mm_data->reg.full_service_indicated = TRUE;
170 mm_data->reg.new_cell_ind = FALSE;
171 }
172 }
173
174
175 /*
176 +--------------------------------------------------------------------+
177 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
178 | STATE : code ROUTINE : reg_build_mmr_nreg_ind |
179 +--------------------------------------------------------------------+
180
181 PURPOSE : This functions sends an MMR_NREG_IND to the MMR SAP.
182 This is only done if G23 is compiled as a GSM only protocol stack
183 without GPRS. Otherwise this function is deactivated.
184
185 */
186
187 GLOBAL void reg_build_mmr_nreg_ind (UBYTE service,
188 UBYTE search_running,
189 UBYTE forb_ind)
190 {
191 GET_INSTANCE_DATA;
192 PALLOC (mmr_nreg_ind, MMR_NREG_IND); /* T_MMR_NREG_IND */
193
194 TRACE_FUNCTION ("reg_build_mmr_nreg_ind");
195
196 mmr_nreg_ind->service = service;
197 mmr_nreg_ind->search_running = search_running;
198
199 if (forb_ind EQ FORB_PLMN_INCLUDED)
200 {
201 mmr_nreg_ind->new_forb_plmn.v_plmn = V_PLMN_PRES;
202 memcpy (mmr_nreg_ind->new_forb_plmn.mcc, mm_data->mm.lai.mcc, SIZE_MCC);
203 memcpy (mmr_nreg_ind->new_forb_plmn.mnc, mm_data->mm.lai.mnc, SIZE_MNC);
204 }
205 else
206 {
207 mmr_nreg_ind->new_forb_plmn.v_plmn = V_PLMN_NOT_PRES;
208 memset (mmr_nreg_ind->new_forb_plmn.mcc, 0x0f, SIZE_MCC);
209 memset (mmr_nreg_ind->new_forb_plmn.mnc, 0x0f, SIZE_MNC);
210 }
211
212 mmr_nreg_ind->cause = mm_data->limited_cause;
213
214 PSENDX (MMI, mmr_nreg_ind);
215
216 /*
217 * Delete the limited cause if it was not fatal, as
218 * on the next cell selection the reason may be another than
219 * the one now indicated.
220 */
221 if (mm_data->reg.op.sim_ins EQ SIM_INSRT)
222 mm_data->limited_cause = MMCS_INT_NOT_PRESENT;
223
224 mm_data->reg.full_service_indicated = FALSE;
225 }
226
227 /*
228 +--------------------------------------------------------------------+
229 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
230 | STATE : code ROUTINE : reg_build_mmr_nreg_cnf |
231 +--------------------------------------------------------------------+
232
233 PURPOSE : This functions sends an MMR_NREG_CNF to the MMR SAP.
234 This is only done if G23 is compiled as a GSM only protocol stack
235 without GPRS. Otherwise this function is deactivated.
236
237 */
238
239 GLOBAL void reg_build_mmr_nreg_cnf (UBYTE cause)
240 {
241 GET_INSTANCE_DATA;
242 TRACE_FUNCTION ("reg_build_mmr_nreg_cnf()");
243
244 if (mm_data->nreg_request)
245 {
246 PALLOC (mmr_nreg_cnf, MMR_NREG_CNF); /* T_MMR_NREG_CNF */
247 mmr_nreg_cnf->detach_cause = cause;
248 PSENDX (MMI, mmr_nreg_cnf);
249
250 mm_data->nreg_request = FALSE;
251 }
252 }
253
254
255 /*
256 +----------------------------------------------------------------------------+
257 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
258 | STATE : code ROUTINE : reg_build_mmr_plmn_ind |
259 +----------------------------------------------------------------------------+
260
261 PURPOSE : This function send a MMR_PLMN_IND primitive to the MMR SAP.
262 This is only done if G23 is compiled as a GSM only protocol stack
263 without GPRS. Otherwise this function is deactivated.
264
265 */
266
267 GLOBAL void reg_build_mmr_plmn_ind (USHORT cause,
268 const T_RR_ABORT_IND *rr_abort_ind)
269 {
270 GET_INSTANCE_DATA;
271 TRACE_FUNCTION ("reg_build_mmr_plmn_ind()");
272
273 if (mm_data->plmn_scan_mmi)
274 {
275 USHORT i;
276 PALLOC (mmr_plmn_ind, MMR_PLMN_IND); /* T_MMR_PLMN_IND */
277
278 mmr_plmn_ind->cause = cause;
279
280 // This memset() sets all plmn.v_plmn fields to 0xff.
281 // For ACI, file PSA_MMF.C, function psaMM_CpyPLMNLst()
282 // this indicates that the PLMN is *not* valid.
283 // This convention is used at some places in MM,
284 // but it is against all usual conventions for G23.
285 // By RR SAP definition 0xff is not a possible value in this field.
286 // RR SAP definition says:
287 // plmn.v_plmn = V_PLMN_PRES (0x01) PLMN valid
288 // plmn.v_plmn = V_PLMN_NOT_PRES (0x00) PLMN not valid
289
290 memset (&mmr_plmn_ind->plmn, NOT_PRESENT_8BIT,
291 sizeof (mmr_plmn_ind->plmn));
292
293 if (cause EQ MMCS_SUCCESS)
294 {
295 /* Create the PLMN list for the MMI and send it */
296 reg_create_plmn_list (rr_abort_ind, WITH_ALL_PLMNS);
297
298 for (i = 0 ; i < mm_data->reg.plmn_cnt; i++)
299 {
300 reg_unpack_plmn (&mmr_plmn_ind->plmn[i], mm_data->reg.plmn, i);
301 mmr_plmn_ind->forb_ind[i] =
302 reg_plmn_in_list (mm_data->reg.forb_plmn,
303 MAX_FORB_PLMN_ID,
304 &mmr_plmn_ind->plmn[i]);
305 mmr_plmn_ind->rxlevel[i] = mm_data->reg.plmn_rx [i];
306 mmr_plmn_ind->lac_list[i] = mm_data->reg.plmn_lac [i];
307 }
308
309 /* Do not consider the forbidden PLMNs for MM's internal operation */
310 reg_create_plmn_list (rr_abort_ind, WITH_OTHER_PLMNS);
311 }
312
313 PSENDX (MMI, mmr_plmn_ind);
314
315 }
316
317 reg_check_plmn_search (cause, rr_abort_ind);
318 }
319
320 /*
321 +----------------------------------------------------------------------------+
322 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
323 | STATE : code ROUTINE : reg_build_mmr_ahplmn_ind |
324 +----------------------------------------------------------------------------+
325
326 PURPOSE : This function sends a MMR_AHPLMN_IND primitive to the MMR SAP.
327 At poweron if valid AHPLMN or if MM receives valid AHPLMN request
328 from SIM, MM should inform ACI of the changed AHPLMN.
329 This is only done if G23 is compiled as a GSM only protocol stack
330 without GPRS. Otherwise this function is deactivated.
331 */
332
333 GLOBAL void reg_build_mmr_ahplmn_ind (T_plmn *acting_hplmn)
334 {
335 TRACE_FUNCTION ("reg_build_mmr_ahplmn_ind()");
336 {
337 PALLOC(mmr_ahplmn_ind, MMR_AHPLMN_IND); /* T_MMR_AHPLMN_IND */
338
339 mmr_ahplmn_ind->ahplmn.v_plmn = acting_hplmn->v_plmn;
340 memcpy (mmr_ahplmn_ind->ahplmn.mcc, acting_hplmn->mcc, SIZE_MCC);
341 memcpy (mmr_ahplmn_ind->ahplmn.mnc, acting_hplmn->mnc, SIZE_MNC);
342
343 PSENDX(MMI, mmr_ahplmn_ind);
344 }
345
346 }
347
348 #endif /* !defined(GPRS) */
349
350 /*
351 +----------------------------------------------------------------------------+
352 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
353 | STATE : code ROUTINE : reg_build_sim_update |
354 +----------------------------------------------------------------------------+
355
356 PURPOSE :
357
358 */
359
360 GLOBAL void reg_build_sim_update (void)
361 {
362 GET_INSTANCE_DATA;
363 TRACE_FUNCTION ("reg_build_sim_update()");
364
365 if (mm_data->reg.op.sim_ins EQ SIM_INSRT)
366 {
367 PALLOC (sim_mm_update_req, SIM_MM_UPDATE_REQ);
368
369 mm_write_eplmn_to_ffs();
370
371 reg_set_loc_info (sim_mm_update_req);
372 reg_set_bcch_info (sim_mm_update_req);
373 reg_set_forb_plmns (sim_mm_update_req);
374 reg_set_kc (sim_mm_update_req);
375
376 /* Sending the final EF indicator Bit pattern to SIM */
377 sim_mm_update_req->ef_indicator = mm_data->ef_indicator;
378
379 PSENDX (SIM, sim_mm_update_req);
380 /* Resetting to 0 after its info is conveyed to SIM */
381 mm_data->ef_indicator = 0;
382 }
383 }
384
385 /*
386 +--------------------------------------------------------------------+
387 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
388 | STATE : code ROUTINE : reg_copy_sim_data |
389 +--------------------------------------------------------------------+
390
391 PURPOSE : This function copies the registration data from the SIM
392 provided by the SIM_MM_INSERT_IND primitive into the
393 registration data structures. A consistency check is
394 made, if data is not consistent (e.g. TMSI present,
395 but update state is different from U1 updated), this is
396 corrected.
397
398 */
399
400 GLOBAL void reg_copy_sim_data (const T_SIM_MM_INSERT_IND *sim_mm_insert_ind)
401 {
402 GET_INSTANCE_DATA;
403 TRACE_FUNCTION ("reg_copy_sim_data()");
404
405 mm_data->reg.op.ts = TS_NO_AVAIL;
406 mm_data->reg.op.sim_ins = SIM_INSRT;
407
408 /* Clear limited service cause for MMI information */
409 mm_data->limited_cause = MMCS_INT_NOT_PRESENT;
410
411 #ifdef TM_SPECIAL
412 mm_data->reg.op.ts = TS_AVAIL;
413 #else
414 if (sim_mm_insert_ind->ad[0] >= 0x80)
415 mm_data->reg.op.ts = TS_AVAIL;
416 if (sim_mm_insert_ind->ad[0] EQ 4)
417 mm_data->reg.cell_test = CELL_TEST_ENABLE;
418 else
419 mm_data->reg.cell_test = CELL_TEST_DISABLE;
420 #endif
421
422 /* EF_AD in SIM has length of MNC as optional field. If the field
423 * is present then Length of MNC is present and hence read it.
424 */
425 if (sim_mm_insert_ind->c_ad EQ 4)
426 {
427 mm_data->reg.length_mnc = sim_mm_insert_ind->ad[3] &0x0f;
428 }
429
430 TRACE_EVENT_P1("Length of MNC = %x",
431 sim_mm_insert_ind->c_ad);
432
433 /*
434 * Copy the information of SIM_MM_INSERT_IND into the
435 * data fields of the registration
436 */
437 reg_read_imsi (&mm_data->reg.imsi_struct, &sim_mm_insert_ind->imsi_field);
438 reg_read_loc_info (&sim_mm_insert_ind->loc_info);
439 /*add by TISH 0418 to write imsi to FFS*/
440 mm_read_ffs_imsi();
441 if (reg_imsi_equal(&imsi_in_ffs, &mm_data->reg.imsi_struct))
442 {
443
444 /* added by TISH 0418 to write simloci to FFS */
445 if( mm_data->reg.update_stat NEQ MS_UPDATED)//only use value in FFS in this case
446 {
447 TRACE_EVENT("MS NOT UPDATED, readsimloci from FFS");
448 if(mm_read_ffs_simloci())
449 {
450 /*Successful read*/
451 TRACE_EVENT_P7("readlocinfo:%d,%d,%d,%d,%d,%d,%d", loc_info_ffs.loc[4], loc_info_ffs.loc[5], loc_info_ffs.loc[6], loc_info_ffs.loc[7],
452 loc_info_ffs.loc[8], loc_info_ffs.loc[9], loc_info_ffs.loc[10]);
453 reg_read_loc_info (&loc_info_ffs);
454 }
455 }
456 /* added by TISH 0418 to write simloci to FFS */
457 }
458 mm_data->reg.acc_class = sim_mm_insert_ind->acc_ctrl.acc[0] * 256 +
459 sim_mm_insert_ind->acc_ctrl.acc[1];
460 reg_read_bcch_info (sim_mm_insert_ind);
461 reg_read_kc_cksn (sim_mm_insert_ind);
462
463 reg_read_forb_plmn (&sim_mm_insert_ind->forb_plmn);
464 reg_copy_sim_ahplmn (sim_mm_insert_ind);
465
466 /* Delete the AHPLMN entry from the Forbidden list, if present*/
467 if ( mm_data->reg.acting_hplmn.v_plmn)
468 {
469 /* Remove from forbidden PLMN list if stored */
470 reg_plmn_bad_del (mm_data->reg.forb_plmn,
471 MAX_FORB_PLMN_ID,
472 &mm_data->reg.acting_hplmn);
473 }
474
475 #ifdef GPRS
476 reg_clear_plmn_list (mm_data->reg.gprs_forb_plmn, MAX_GPRS_FORB_PLMN_ID);
477 #endif /* #ifdef GPRS */
478 // sim_mm_insert_ind->phase is not needed by MM
479 mm_data->reg.thplmn = sim_mm_insert_ind->hplmn;
480 if (mm_data->reg.thplmn > HPLMN_MAX_SEARCH_PERIOD)
481 {
482 /* 3GPP 22.011 subclause 3.2.2.5 requires to use the default value
483 * if the value delivered by the SIM exceeds the allowed limit. */
484 mm_data->reg.thplmn = HPLMN_DEF_SEARCH_PERIOD;
485 }
486
487 /*
488 * If file size is indicated in SIM MM insert indication, MM shall read files from SIM.
489 */
490 if(reg_sim_files_to_be_read(sim_mm_insert_ind))
491 {
492 /*
493 * Read indicated EFs in SIM_MM_INSERT_IND from SIM.
494 */
495 reg_read_next_sim_file();
496 }
497
498 /*Re-read any valid EPLMNs..*/
499 mm_read_ffs_init();
500
501 if (mm_data->reg.update_stat NEQ MS_UPDATED)
502 {
503 /*
504 * According to GSM 04.08 subclause 4.1.2.2 the SIM does not contain
505 * any valid LAI, TMSI, ciphering key or ciphering key sequence number if
506 * the update status on the SIM not equals to U1.
507 */
508
509 /* Delete TMSI */
510 mm_data->reg.tmsi = TMSI_INVALID_VALUE;
511
512 /* Inform GMM about the TMSI change */
513 mm_mmgmm_tmsi_ind (TMSI_INVALID_VALUE);
514
515 /* Delete LAI */
516 mm_data->reg.lai.lac = LAC_INVALID_VALUE;
517 /* EF Indicator for EF LOCI - bit 1 */
518 mm_data->ef_indicator|=0x01;
519
520 /* Delete CKSN */
521 mm_data->reg.cksn = CKSN_RES;
522
523 /* Delete also KC */
524 memset (mm_data->reg.kc, 0xff, MAX_KC);
525 /* Set bit 4 in ef_indicator to indicate kc change to SIM for next SIM_MM_UPDATE_REQ */
526 mm_data->ef_indicator|=(0x01 << 3);
527 }
528 }
529
530 /*
531 +--------------------------------------------------------------------+
532 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
533 | STATE : code ROUTINE : reg_create_plmn_list |
534 +--------------------------------------------------------------------+
535
536 PURPOSE : This functions creates the list of available PLMNs from
537 the information given by the RR_ABORT_IND primitive.
538 The HPLMN is sorted to the top of the PLMN list,
539 than the PLMNs follow in th order defined in the
540 preferred PLMN list, than the PLMNs follow in the
541 order as delivered by the RR_ABORT_IND primitive.
542
543 The parameter hplmn_flag controls whether the forbidden
544 PLMNs are deleted from the list, this will be the case
545 for MM's internal operation or wheter all PLMNs found shall
546 be present in the resulting list, this will be the case
547 if the list was requested by the MMI for informational
548 purposes.
549
550 hplmn_flag may also indicate whether the HPLMN shall be
551 present in the list, this functionality may become
552 obsolete in the future.
553
554 In case MM received a location updating reject #13,
555 we remember the PLMN where we received this cause. This
556 PLMN is in this case a low priority PLMN and sorted to the
557 end of the list.
558
559
560
561 */
562
563 GLOBAL void reg_create_plmn_list (const T_RR_ABORT_IND *rr_abort_ind,
564 UBYTE include_flag)
565 {
566 GET_INSTANCE_DATA;
567 USHORT i;
568 USHORT j;
569 USHORT low_prio_index;
570 BOOL copy_plmn[MAX_PLMN_ID];
571 UBYTE plmn_avail;
572
573 TRACE_FUNCTION ("reg_create_plmn_list()");
574
575 reg_clear_plmn_list (mm_data->reg.plmn, MAX_PLMN_ID);
576 mm_data->reg.plmn_cnt = 0;
577 mm_data->reg.plmn_index = 0;
578
579 plmn_avail = rr_abort_ind->plmn_avail;
580
581 if (plmn_avail > MAX_PLMN_ID)
582 plmn_avail = MAX_PLMN_ID; /* Garbage protection, not expected to catch */
583
584 for (i = 0; i < MAX_PLMN_ID; i++)
585 copy_plmn[i] = TRUE;
586
587 if (include_flag NEQ WITH_ALL_PLMNS)
588 {
589 /*
590 * MS is in automatic mode and the list which shall be created is
591 * not for a PLMN available request,then remove the forbidden PLMNs.
592 */
593 for (i = 0; i < rr_abort_ind->plmn_avail; i++)
594 {
595 if (reg_plmn_in_list (mm_data->reg.forb_plmn,
596 MAX_FORB_PLMN_ID,
597 &rr_abort_ind->plmn[i]))
598 {
599 copy_plmn[i] = FALSE;
600 }
601
602 #ifdef GPRS
603 /*
604 * Consider also the "forbidden PLMNs for GPRS services" list,
605 * if GPRS is active.
606 */
607 if (!mm_gsm_alone () AND
608 (mm_data->gprs.mobile_class EQ MMGMM_CLASS_CG) AND
609 reg_plmn_in_list (mm_data->reg.gprs_forb_plmn,
610 MAX_GPRS_FORB_PLMN_ID,
611 &rr_abort_ind->plmn[i]))
612 {
613 copy_plmn[i] = FALSE;
614 }
615 #endif /* #ifdef GPRS */
616 }
617 }
618
619 /*
620 * In case RR delivered the PLMN where we recently received a location
621 * updating reject with cause #13, this PLMN has low priority now only.
622 * This is a different handling than described in GSM 03.22 clause 4.4.3,
623 * but needed in the field.
624 */
625 low_prio_index = NOT_PRESENT_16BIT;
626 if ((include_flag NEQ WITH_ALL_PLMNS) AND
627 (include_flag NEQ WITH_RPLMN) AND
628 !reg_plmn_empty (&mm_data->reg.low_prio_plmn))
629 {
630 for (i = 0; i < plmn_avail; i++)
631 {
632 if (copy_plmn[i] AND
633 reg_plmn_equal_sim (&rr_abort_ind->plmn[i],
634 &mm_data->reg.low_prio_plmn))
635 {
636 low_prio_index = i;
637 copy_plmn[i] = FALSE;
638 }
639 }
640
641 /* Clear the low priority PLMN */
642 reg_clear_plmn (&mm_data->reg.low_prio_plmn);
643 }
644
645 /*
646 * In case RR delivered the actual PLMN, requested by FUNC_PLMN_SRCH,
647 * as a member of the list, we filter it out, as in this case no cell
648 * of the PLMN has been recognized by RR as suitable for full service.
649 */
650 if ((include_flag NEQ WITH_ALL_PLMNS) AND
651 (include_flag NEQ WITH_RPLMN))
652 {
653 for (i = 0; i < plmn_avail; i++)
654 {
655 if (reg_plmn_equal_sim (&rr_abort_ind->plmn[i],
656 &mm_data->reg.actual_plmn))
657 {
658 /*
659 * In case of cause #12 - Location Area Not Allowed, MS shall be able
660 * to select the same PLMN if suitable cell with other LAI is avaiable.
661 * Hence while preparing PLMN list MM shall not discard that PLMN.
662 */
663 if (((mm_data->rej_cause EQ MMCS_LA_NOT_ALLOWED)
664 #ifdef GPRS
665 OR (mm_data->rej_cause EQ GMMCS_LA_NOT_ALLOWED)
666 #endif
667 )
668 AND (GET_STATE(STATE_MM) EQ MM_IDLE_LIMITED_SERVICE))
669 {
670 TRACE_EVENT ("Don't ignore actual PLMN for cause #12");
671 }
672 else
673 {
674 TRACE_EVENT ("Ignore actual PLMN");
675 copy_plmn[i] = FALSE;
676 }
677 }
678 }
679 }
680
681 /*
682 * GSM 03.22 subclause 4.4.3 gives some rules in which way the PLMN list
683 * has to be sorted. These rules apply for manual and for automatic mode.
684 * For further details, see the mentioned recommendation.
685 */
686
687 /*
688 * Find HPLMN in the list of found PLMNs. If present, set it on top
689 */
690 for (i = 0; i < plmn_avail; i++)
691 {
692 if (copy_plmn[i] AND
693 reg_plmn_equal_hplmn (&rr_abort_ind->plmn[i]))
694 {
695 reg_pack_plmn_fn (i, rr_abort_ind);
696 copy_plmn[i] = FALSE;
697 break;
698 }
699 }
700
701 /*
702 * Add the found PLMNS into MMR_PLMN_IND according to their position in the
703 * preferred PLMN list
704 */
705 for (j = 0; j < MAX_PREF_PLMN_ID; j++)
706 {
707 T_plmn pref_plmn;
708 reg_unpack_plmn (&pref_plmn, mm_data->reg.pref_plmn, j);
709
710 if (! reg_plmn_empty (&pref_plmn))
711 {
712 for (i = 0; i < plmn_avail; i++)
713 {
714 /*
715 * Use the comparison routines from GSM 03.22 Annex A (normative)
716 * Reason: Even if it is not the HPLMN, we were not able to
717 * recognize a 3-digit NA MNC network as preferred if it would still
718 * broadcast only 2-digit MNC.
719 */
720 if (copy_plmn[i] AND
721 reg_plmn_equal_sim (&rr_abort_ind->plmn[i], &pref_plmn))
722 {
723 reg_pack_plmn_fn (i, rr_abort_ind);
724 copy_plmn[i] = FALSE;
725 break;
726 }
727 }
728 }
729 }
730
731 /*
732 * Add the remaining PLMNS to MMR_PLMN_IND
733 */
734 for (i = 0; i < plmn_avail; i++)
735 {
736 if (copy_plmn[i] AND
737 ! reg_plmn_empty (&rr_abort_ind->plmn[i]))
738 {
739 reg_pack_plmn_fn (i, rr_abort_ind);
740 copy_plmn[i] = FALSE;
741 }
742 }
743
744 /*
745 * Add the low priority PLMN where we previously received LUP reject #13,
746 * if present, at the end of the list.
747 */
748 if (low_prio_index NEQ NOT_PRESENT_16BIT)
749 {
750 reg_pack_plmn_fn (low_prio_index, rr_abort_ind);
751 copy_plmn[i] = FALSE;
752 }
753
754 #ifndef NTRACE
755 TRACE_EVENT ("PLMN list");
756
757 for (i = 0; i < mm_data->reg.plmn_cnt; i++)
758 {
759 T_plmn plmn;
760
761 reg_unpack_plmn (&plmn, mm_data->reg.plmn, i);
762 TRACE_EVENT_P6 ("MCC=%x%x%x MNC=%x%x%x",
763 plmn.mcc[0],
764 plmn.mcc[1],
765 plmn.mcc[2],
766 plmn.mnc[0],
767 plmn.mnc[1],
768 plmn.mnc[2]);
769 }
770 #endif /* #ifndef NTRACE */
771 }
772
773 /*
774 +--------------------------------------------------------------------+
775 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
776 | STATE : code ROUTINE : reg_extract_hplmn |
777 +--------------------------------------------------------------------+
778
779 PURPOSE : Extracts the HPLMN out of the registration data.
780 If valid AHPLMN is present then HPLMN should be
781 read from the file, else it should be read from IMSI.
782
783 */
784
785 GLOBAL void reg_extract_hplmn (T_plmn *plmn)
786 {
787 GET_INSTANCE_DATA;
788 TRACE_FUNCTION ("reg_extract_hplmn()");
789
790 if (mm_data->reg.acting_hplmn.v_plmn)
791 {
792 plmn->v_plmn = V_PLMN_PRES;
793 memcpy(plmn->mcc,mm_data->reg.acting_hplmn.mcc,SIZE_MCC);
794 memcpy(plmn->mnc,mm_data->reg.acting_hplmn.mnc,SIZE_MNC);
795 }
796 else
797 {
798 plmn->v_plmn = V_PLMN_PRES;
799 plmn->mcc[0] = mm_data->reg.imsi_struct.id[0];
800 plmn->mcc[1] = mm_data->reg.imsi_struct.id[1];
801 plmn->mcc[2] = mm_data->reg.imsi_struct.id[2];
802 plmn->mnc[0] = mm_data->reg.imsi_struct.id[3];
803 plmn->mnc[1] = mm_data->reg.imsi_struct.id[4];
804
805 /*
806 * We cannot be sure that plmn->mnc[2] really belongs to the MNC,
807 * but the comparison routines for the HPLMN are done in a way that
808 * this doesn't matter anyway. See GSM 03.03 subclause 2.2,
809 * which is far away from being clear and GSM 03.22 version 7.1.0
810 * Release 1998 Annex A (normative). Figure A.2 in this annex makes
811 * it obvious that 3-digit-MNC isn't only a NA issue!
812 */
813 plmn->mnc[2] = mm_data->reg.imsi_struct.id[5];
814 }/* end of mm_data->reg.acting_hplmn.v_plmn */
815 }
816
817
818 /*
819 +--------------------------------------------------------------------+
820 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
821 | STATE : code ROUTINE : reg_init |
822 +--------------------------------------------------------------------+
823
824 PURPOSE : This function initializes the registration data structures.
825
826 */
827
828 GLOBAL void reg_init (void)
829 {
830 GET_INSTANCE_DATA;
831 TRACE_FUNCTION ("reg_init()");
832
833 memset (&mm_data->reg, 0, sizeof (T_REG));
834
835 mm_data->reg.update_stat = MS_NOT_UPDATED;
836 mm_data->reg.cksn = CKSN_RES;
837 mm_data->reg.full_service_indicated = FALSE;
838 mm_data->reg.sim_insert_info = NULL;
839 mm_data->reg.sim_sync_req_pending = FALSE;
840 mm_data->reg.quick_hplmn_search = TRUE;
841 }
842
843 /*
844 +--------------------------------------------------------------------+
845 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
846 | STATE : code ROUTINE : reg_plmn_add_bad |
847 +--------------------------------------------------------------------+
848
849 PURPOSE : This function adds the given PLMN to the given list of
850 forbidden PLMNs.
851 In case the PLMN is already stored in this list, no action
852 will be taken, otherwise the PLMN will be stored at the
853 first free entry of the list. If there is no free entry,
854 the first entry in the list will be deleted and the list
855 will be shifted so that the PLMN can be added at the end
856 of the list.
857
858 */
859
860 GLOBAL void reg_plmn_add_bad (UBYTE *forb_plmn_list,
861 USHORT list_size,
862 const T_plmn *plmn)
863 {
864 T_plmn forb_plmn;
865 USHORT i;
866
867 TRACE_FUNCTION ("reg_plmn_add_bad()");
868
869 /* First look whether the PLMN is already stored */
870 for (i = 0; i < list_size; i++)
871 {
872 reg_unpack_plmn (&forb_plmn, forb_plmn_list, i);
873 if (reg_plmn_equal_sim (plmn, &forb_plmn))
874 return;
875 }
876
877 /* Else look for an empty location and store the PLMN */
878 for (i = 0; i < list_size; i++)
879 {
880 reg_unpack_plmn (&forb_plmn, forb_plmn_list, i);
881 if (reg_plmn_empty (&forb_plmn))
882 {
883 reg_pack_plmn (forb_plmn_list, i, plmn);
884 return;
885 }
886 }
887
888 /* Else shift the entries down add the PLMN at the end of the list */
889 memmove (&forb_plmn_list[0],
890 &forb_plmn_list[UBYTES_PER_PLMN],
891 UBYTES_PER_PLMN * (list_size - 1)); /*lint !e807 This function is always called with constant 'list_size'*/
892 reg_pack_plmn (forb_plmn_list, (USHORT)(list_size - 1), plmn);
893 }
894
895
896 /*
897 +--------------------------------------------------------------------+
898 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
899 | STATE : code ROUTINE : reg_plmn_in_list |
900 +--------------------------------------------------------------------+
901
902 PURPOSE : This function checks whether the PLMN in question is a
903 member of the PLMN list provided. The function returns
904 TRUE if the PLMN can be found in the PLMN list, otherwise
905 the function returns FALSE.
906 */
907
908 GLOBAL BOOL reg_plmn_in_list(const UBYTE *plmn_list,
909 USHORT list_size,
910 const T_plmn *plmn)
911 {
912 T_plmn member_plmn;
913 USHORT i;
914
915 TRACE_FUNCTION ("reg_in_forb_plmn()");
916
917 for (i = 0; i < list_size; i++)
918 {
919 reg_unpack_plmn (&member_plmn, plmn_list, i);
920 if (reg_plmn_equal_sim (plmn, &member_plmn))
921 return TRUE;
922 }
923 return FALSE;
924 }
925
926
927 /*
928 +--------------------------------------------------------------------+
929 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
930 | STATE : code ROUTINE : reg_plmn_bad_del |
931 +--------------------------------------------------------------------+
932
933 PURPOSE : Remove the specified PLMN from the given list of forbidden
934 PLMNs. In case the specified PLMN is found in the list,
935 it will be deleted from the list.
936
937 */
938
939 GLOBAL void reg_plmn_bad_del (UBYTE *forb_plmn_list,
940 USHORT list_size,
941 const T_plmn *plmn)
942 {
943 GET_INSTANCE_DATA;
944 T_plmn forb_plmn;
945 USHORT i;
946 USHORT j;
947
948 TRACE_FUNCTION ("reg_plmn_bad_del()");
949
950 for (i = 0; i < list_size; i++)
951 {
952 reg_unpack_plmn (&forb_plmn, forb_plmn_list, i);
953 if (reg_plmn_equal_sim (&forb_plmn, plmn)) /* Argument order matters */
954 {
955 for (j = i; j < list_size - 1; j++)
956 {
957 memcpy (&forb_plmn_list[j * UBYTES_PER_PLMN],
958 &forb_plmn_list[(j + 1) * UBYTES_PER_PLMN],
959 UBYTES_PER_PLMN);
960 }
961 memset (&forb_plmn_list[(list_size - 1) * UBYTES_PER_PLMN],
962 0xff, UBYTES_PER_PLMN);
963 /* Set bit 3 in ef_indicator to indicate forb_plmn change to SIM */
964 mm_data->ef_indicator|=(0x01 << 2);
965 }
966 }
967 }
968
969 /*
970 +--------------------------------------------------------------------+
971 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
972 | STATE : code ROUTINE : reg_plmn_empty |
973 +--------------------------------------------------------------------+
974
975 PURPOSE : This function tests whether plmn points to an empty PLMN.
976 TRUE will be returned if plmn points to an empty PLMN,
977 otherwise FALSE.
978
979 */
980
981 GLOBAL BOOL reg_plmn_empty (const T_plmn *plmn)
982 {
983 /* TRACE_FUNCTION ("reg_plmn_empty ()"); */ /* Avoid too much output */
984
985 return ((plmn->mcc[0] & 0x0F) EQ 0x0F);
986 }
987
988
989 /*
990 +--------------------------------------------------------------------+
991 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
992 | STATE : code ROUTINE : reg_sim_ef_plmn_field_empty|
993 +--------------------------------------------------------------------+
994
995 PURPOSE : This function tests whether plmn in EF points to an empty PLMN.
996 TRUE will be returned if plmn points to an empty PLMN,
997 otherwise FALSE.
998
999 */
1000 GLOBAL BOOL reg_sim_ef_plmn_field_empty (UBYTE* plmn)
1001 {
1002 /*check if 1th digit of MCC is not present*/
1003 return ((plmn[0] & 0x0F) EQ 0x0F);
1004 }
1005
1006
1007 /*
1008 +--------------------------------------------------------------------+
1009 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1010 | STATE : code ROUTINE : reg_plmn_is_NA_plmn |
1011 +--------------------------------------------------------------------+
1012
1013 PURPOSE : This function tests whether the PLMN is a NA (North America)
1014 PLMN. The MCC code is checked to meet this decision.
1015
1016 */
1017
1018 GLOBAL BOOL reg_plmn_is_NA_plmn (const T_plmn *plmn)
1019 {
1020 /* TRACE_FUNCTION ("reg_plmn_is_NA_plmn()"); */ /* Avoid too much output */
1021
1022 /* return ((plmn->mcc[0] EQ 3) AND
1023 (plmn->mcc[1] EQ 1) AND
1024 (plmn->mcc[2] >= 0) AND (plmn->mcc[2] <= 6)); lint !e568 never
1025 less than zero*/
1026 return ((plmn->mcc[0] EQ 3) AND
1027 (plmn->mcc[1] EQ 1) AND
1028 (plmn->mcc[2] <= 6)); /*lint !e568 never
1029 less than zero*/
1030 }
1031
1032 /*
1033 +--------------------------------------------------------------------+
1034 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1035 | STATE : code ROUTINE : reg_plmn_equal_sim |
1036 +--------------------------------------------------------------------+
1037
1038 PURPOSE : This function tests whether two PLMNs are contained in
1039 Equivalent PLMN list or not
1040
1041 */
1042
1043 GLOBAL BOOL reg_plmn_equal_eqv (const T_plmn *bcch_plmn,
1044 const T_plmn *req_plmn)
1045 {
1046 GET_INSTANCE_DATA;
1047 TRACE_FUNCTION ("reg_plmn_equal_eqv()");
1048
1049 if (reg_plmn_equal_sim (bcch_plmn, req_plmn))
1050 return TRUE; /* Equal without equivalent PLMN */
1051 if (reg_plmn_in_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE, bcch_plmn) &&
1052 reg_plmn_in_list (mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE, req_plmn))
1053 {
1054 return TRUE;
1055 }
1056 return FALSE;
1057 }
1058
1059 /*
1060 +--------------------------------------------------------------------+
1061 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1062 | STATE : code ROUTINE : reg_plmn_equal_sim |
1063 +--------------------------------------------------------------------+
1064
1065 PURPOSE : This function tests whether two PLMNs are equal.
1066
1067 */
1068
1069 GLOBAL BOOL reg_plmn_equal_sim (const T_plmn *bcch_plmn,
1070 const T_plmn *sim_plmn)
1071 {
1072 /* TRACE_FUNCTION ("reg_plmn_equal_sim()"); */ /* Avoid too much output */
1073
1074 /* Check MCC */
1075 if (memcmp (sim_plmn->mcc, bcch_plmn->mcc, SIZE_MCC) NEQ 0)
1076 return FALSE;
1077
1078 /* Check first 2 MNC digits */
1079 if (memcmp (sim_plmn->mnc, bcch_plmn->mnc, 2) NEQ 0)
1080 return FALSE;
1081
1082 /* Check for full match */
1083 if (sim_plmn->mnc[2] EQ bcch_plmn->mnc[2])
1084 return TRUE;
1085
1086 /* The 3rd digit of the MNC differs. */
1087 if (reg_plmn_is_NA_plmn (bcch_plmn))
1088 {
1089 return (((sim_plmn->mnc[2] EQ 0xf) AND (bcch_plmn->mnc[2] EQ 0x0)) OR
1090 ((sim_plmn->mnc[2] EQ 0x0) AND (bcch_plmn->mnc[2] EQ 0xf)));
1091 }
1092 return (bcch_plmn->mnc[2] EQ 0xf) OR (sim_plmn->mnc[2] EQ 0xf);
1093 }
1094
1095 /*
1096 +--------------------------------------------------------------------+
1097 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1098 | STATE : code ROUTINE : reg_plmn_equal_hplmn |
1099 +--------------------------------------------------------------------+
1100
1101 PURPOSE : This function tests whether the PLMN received on the
1102 BCCH equals the HPLMN. TRUE will be returned if bcch_plmn
1103 points to a PLMN description which describes the HPLMN,
1104 otherwise FALSE will be returned.
1105
1106 */
1107
1108 GLOBAL BOOL reg_plmn_equal_hplmn (const T_plmn *bcch_plmn)
1109 {
1110 T_plmn hplmn;
1111
1112 TRACE_FUNCTION ("reg_plmn_equal_hplmn()");
1113
1114 reg_extract_hplmn (&hplmn);
1115 return (reg_plmn_equal_sim (bcch_plmn, &hplmn));
1116 }
1117
1118
1119 /*
1120 +--------------------------------------------------------------------+
1121 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1122 | STATE : code ROUTINE : reg_plmn_equal_rplmn |
1123 +--------------------------------------------------------------------+
1124
1125 PURPOSE : This function tests whether the PLMN equals the RPLMN.
1126 TRUE will be returned if PLMN points to a PLMN description
1127 which describes the RPLMN,otherwise FALSE will be returned.
1128 */
1129
1130 GLOBAL BOOL reg_plmn_equal_rplmn (T_plmn *plmn)
1131 {
1132 GET_INSTANCE_DATA;
1133
1134 T_plmn last_plmn;
1135
1136 TRACE_FUNCTION ("reg_plmn_equal_rplmn()");
1137
1138 last_plmn.v_plmn = V_PLMN_PRES;
1139 memcpy (last_plmn.mcc, mm_data->reg.lai.mcc, SIZE_MCC);
1140 memcpy (last_plmn.mnc, mm_data->reg.lai.mnc, SIZE_MNC);
1141
1142 return (reg_plmn_equal_sim (plmn, &last_plmn));
1143 }
1144
1145
1146 /*
1147 +--------------------------------------------------------------------+
1148 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1149 | STATE : code ROUTINE : reg_imsi_equal |
1150 +--------------------------------------------------------------------+
1151
1152 PURPOSE : Checks whether two given IMSIs are identical
1153
1154 */
1155
1156 GLOBAL BOOL reg_imsi_equal (const T_imsi_struct *imsi_struct1, const T_imsi_struct *imsi_struct2)
1157 {
1158 USHORT length;
1159
1160 TRACE_FUNCTION ("reg_imsi_equal()");
1161
1162 if (imsi_struct1->v_mid NEQ imsi_struct2->v_mid)
1163 return FALSE;
1164
1165 if (imsi_struct1->id_type NEQ imsi_struct2->id_type)
1166 return FALSE;
1167
1168 switch (imsi_struct1->id_type)
1169 {
1170 case TYPE_IMSI:
1171 length = mm_calculate_digits (imsi_struct1->id);
1172 if (length NEQ mm_calculate_digits (imsi_struct2->id))
1173 return FALSE;
1174 return (memcmp (imsi_struct1->id, imsi_struct2->id, length) EQ 0);
1175
1176 case TYPE_TMSI:
1177 return (imsi_struct1->tmsi_dig EQ imsi_struct2->tmsi_dig);
1178
1179 default:
1180 return TRUE;
1181 }
1182 }
1183
1184
1185 /*
1186 +--------------------------------------------------------------------+
1187 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1188 | STATE : code ROUTINE : reg_plmn_select |
1189 +--------------------------------------------------------------------+
1190
1191 PURPOSE : This function is called if there was either a RR failure
1192 or a MM failure (e.g. LOCATION UPDATING reject).
1193 MM is in state LIMITED_SERVICE.
1194
1195 */
1196
1197 GLOBAL void reg_plmn_select (UBYTE forb_ind)
1198 {
1199 GET_INSTANCE_DATA;
1200 TRACE_FUNCTION ("reg_plmn_select ()");
1201
1202 if (mm_data->reg.plmn_cnt > mm_data->reg.plmn_index AND
1203 mm_data->reg.op.m EQ MODE_AUTO AND
1204 mm_data->reg.op.sim_ins EQ SIM_INSRT)
1205 {
1206 /*
1207 * Another PLMN available, automatic mode and SIM considered as valid
1208 */
1209 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
1210 SEARCH_RUNNING,
1211 forb_ind);
1212 reg_unpack_plmn (&mm_data->reg.actual_plmn,
1213 mm_data->reg.plmn, mm_data->reg.plmn_index++);
1214 mm_data->attempt_cnt = 0;
1215 mm_mmr_reg_req (FUNC_PLMN_SRCH);
1216 }
1217 else
1218 {
1219 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
1220 SEARCH_NOT_RUNNING,
1221 forb_ind);
1222 }
1223 }
1224
1225 /*
1226 +--------------------------------------------------------------------+
1227 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1228 | STATE : code ROUTINE : reg_read_bcch_info |
1229 +--------------------------------------------------------------------+
1230
1231 PURPOSE : Read the BCCH information delivered by the SIM into the
1232 registration data structures.
1233
1234 */
1235
1236 GLOBAL void reg_read_bcch_info (const T_SIM_MM_INSERT_IND *sim_mm_insert_ind)
1237 {
1238 GET_INSTANCE_DATA;
1239 TRACE_FUNCTION ("reg_read_bcch_info ()");
1240
1241 if(memcmp(mm_data->reg.bcch, sim_mm_insert_ind->bcch_inf.bcch, SIZE_BCCH))
1242 {
1243 /* Set bit 2 in ef_indicator to indicate bcch_info change to SIM */
1244 mm_data->ef_indicator|=(0x01 << 1);
1245 }
1246 memcpy (mm_data->reg.bcch, sim_mm_insert_ind->bcch_inf.bcch, SIZE_BCCH);
1247 }
1248
1249 /*
1250 +--------------------------------------------------------------------+
1251 | PROJECT : GSM-PS MODULE : MM_REG |
1252 | STATE : code ROUTINE : reg_sim_files_to_be_read |
1253 +--------------------------------------------------------------------+
1254
1255 PURPOSE : Read the EFs size (EFu=EFPLMNwAcT, EFo=EFOPLMNwAcT, EFs=EFPLMNSEL) information delivered
1256 by the SIM into the registration data structures.
1257
1258 */
1259
1260 GLOBAL BOOL reg_sim_files_to_be_read (const T_SIM_MM_INSERT_IND *sim_mm_insert_ind)
1261 {
1262 GET_INSTANCE_DATA;
1263 TRACE_FUNCTION ("reg_sim_files_to_be_read ()");
1264 mm_data->reg.sim_read_in_progress = FALSE;
1265
1266 #ifdef REL99
1267 /*
1268 * If the SIM insert indication and file size is indicated, it MM shall read files from SIM.
1269 */
1270 if (sim_mm_insert_ind->u_ctl_plmn_sel_actech_list_sz >0)
1271 {
1272 mm_data->reg.upd_sim_ucps_at = SAT_READ_FILE;
1273 /*Set indicatort sim reading is in progress to true*/
1274 mm_data->reg.sim_read_in_progress = TRUE;
1275 /*
1276 * MM cant decide here how many PLMNs are supported GSM access Technology so
1277 * MM should read maximum number of plmn as much it can read.
1278 * At present there is a limitation in SIM read req. It cant read more than
1279 * 256 bytes in one request. May be PLMN reading can be extended using more
1280 * than one sim read req for the same EF in future.
1281 */
1282 if (sim_mm_insert_ind->u_ctl_plmn_sel_actech_list_sz > 0xFF)
1283 {
1284 /*
1285 * In SIM_READ_REQ FF represents length not present. SIM will read actual EF length
1286 * and send it to MM. At present limitaion is SIM READ CNF can sent max 256 bytes data.
1287 */
1288 mm_data->reg.sim_ucps_at_len = 0xFF;
1289 }
1290 else
1291 {
1292 mm_data->reg.sim_ucps_at_len = sim_mm_insert_ind->u_ctl_plmn_sel_actech_list_sz;
1293 }
1294 }
1295 if(sim_mm_insert_ind->o_ctl_plmn_sel_actech_list_sz > 0)
1296 {
1297 mm_data->reg.upd_sim_ocps_at = SAT_READ_FILE;
1298 /*Set indicatort sim reading is in progress to true*/
1299 mm_data->reg.sim_read_in_progress = TRUE;
1300 /*
1301 * MM cant decide here how many PLMNs are supported GSM access Technology so
1302 * MM should read maximum number of plmn as much it can read.
1303 * At present there is a limitation in SIM read req. It cant read more than
1304 * 256 bytes in one request. May be PLMN reading can be extended using more
1305 * than one sim read req for the same EF in future.
1306 */
1307 if (sim_mm_insert_ind->o_ctl_plmn_sel_actech_list_sz > 0xFF)
1308 {
1309 /*
1310 * In SIM_READ_REQ FF represents length not present. SIM will read actual EF length
1311 * and send it to MM. At present limitaion is SIM READ CNF can sent max 256 bytes data.
1312 */
1313 mm_data->reg.sim_ocps_at_len = 0xFF;
1314 }
1315 else
1316 {
1317 mm_data->reg.sim_ocps_at_len = sim_mm_insert_ind->o_ctl_plmn_sel_actech_list_sz;
1318 }
1319 }
1320 #endif
1321
1322 if (sim_mm_insert_ind->pref_plmn_list_sz >0)
1323 {
1324 mm_data->reg.upd_sim_plmnsel = SAT_READ_FILE;
1325 /*Set indicatort sim reading is in progress to true*/
1326 mm_data->reg.sim_read_in_progress = TRUE;
1327 /* MM should read MAX PREF PLMNs because this EF does not contain any Access Technology info.*/
1328 if (sim_mm_insert_ind->pref_plmn_list_sz > MAX_PREF_PLMN)
1329 {
1330 mm_data->reg.sim_plmnsel_len = MAX_PREF_PLMN; /* Garbage protection */
1331 }
1332 else
1333 {
1334 mm_data->reg.sim_plmnsel_len = sim_mm_insert_ind->pref_plmn_list_sz;
1335 }
1336 }
1337
1338 return mm_data->reg.sim_read_in_progress;
1339 }
1340
1341 /*
1342 +--------------------------------------------------------------------+
1343 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1344 | STATE : code ROUTINE : reg_read_forb_plmn |
1345 +--------------------------------------------------------------------+
1346
1347 PURPOSE : Read the forbidden PLMN into registration data
1348
1349 */
1350
1351 GLOBAL void reg_read_forb_plmn (const T_forb_plmn *forb_plmn)
1352 {
1353 GET_INSTANCE_DATA;
1354 T_plmn plmn;
1355
1356 TRACE_FUNCTION ("reg_read_forb_plmn ()");
1357
1358 reg_clear_plmn_list (mm_data->reg.forb_plmn, MAX_FORB_PLMN_ID);
1359 memcpy (mm_data->reg.forb_plmn, forb_plmn->forb,
1360 MAX_SIM_FORB_PLMN_ID * UBYTES_PER_PLMN);
1361
1362 /*
1363 * If the HPLMN is a member of the forbidden list, delete it from the list.
1364 */
1365 reg_extract_hplmn (&plmn);
1366 TRACE_EVENT_P6 ("HPLMN = %x%x%x %x%x%x",
1367 plmn.mcc[0],
1368 plmn.mcc[1],
1369 plmn.mcc[2],
1370 plmn.mnc[0],
1371 plmn.mnc[1],
1372 plmn.mnc[2]);
1373
1374 reg_plmn_bad_del (mm_data->reg.forb_plmn, MAX_SIM_FORB_PLMN_ID, &plmn);
1375
1376 #ifndef NTRACE
1377 {
1378 USHORT i;
1379
1380 for (i = 0; i < MAX_SIM_FORB_PLMN_ID; i++)
1381 {
1382 reg_unpack_plmn (&plmn, mm_data->reg.forb_plmn, i);
1383 TRACE_EVENT_P6 ("FORB = %x%x%x %x%x%x",
1384 plmn.mcc[0],
1385 plmn.mcc[1],
1386 plmn.mcc[2],
1387 plmn.mnc[0],
1388 plmn.mnc[1],
1389 plmn.mnc[2]);
1390 }
1391 }
1392 #endif /* #ifndef NTRACE */
1393 }
1394
1395
1396 /*
1397 +--------------------------------------------------------------------+
1398 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1399 | STATE : code ROUTINE : reg_copy_sim_ahplmn |
1400 +--------------------------------------------------------------------+
1401
1402 PURPOSE : Read the AHPLMN information delivered by the SIM at poweron
1403 into the registration data structures.
1404
1405 */
1406
1407 GLOBAL void reg_copy_sim_ahplmn (const T_SIM_MM_INSERT_IND *sim_mm_insert_ind)
1408 {
1409 GET_INSTANCE_DATA;
1410 TRACE_FUNCTION ("reg_copy_sim_ahplmn ()");
1411
1412 TRACE_EVENT_P1("v_act_hplmn = %x",
1413 sim_mm_insert_ind->v_act_hplmn);
1414
1415
1416 if (!sim_mm_insert_ind->v_act_hplmn)
1417 {
1418 /*Do Nothing. AHPLMN Feature not supported by SIM. Hence, ignore*/
1419 }
1420 else
1421 {
1422 reg_read_acting_hplmn(sim_mm_insert_ind->act_hplmn);
1423 /* Inform ACI & RR of the AHPLMN present in SIM */
1424 valid_acting_hplmn(&mm_data->reg.acting_hplmn);
1425 mm_build_rr_sync_hplmn_req();
1426 mm_mmgmm_ahplmn_ind(&mm_data->reg.acting_hplmn);
1427 }
1428
1429 }
1430
1431
1432 /*
1433 +--------------------------------------------------------------------+
1434 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1435 | STATE : code ROUTINE : reg_read_imsi |
1436 +--------------------------------------------------------------------+
1437
1438 PURPOSE : Reads IMSI delivered by SIM into T_imsi data structure
1439
1440 */
1441
1442 GLOBAL void reg_read_imsi (T_imsi_struct *imsi_struct, const T_imsi_field *imsi_field)
1443 {
1444 USHORT i;
1445 UBYTE digit;
1446 UBYTE length;
1447
1448 TRACE_FUNCTION ("reg_read_imsi ()");
1449
1450 imsi_struct->v_mid = V_MID_PRES;
1451 imsi_struct->id_type = TYPE_IMSI;
1452 imsi_struct->tmsi_dig = 0;
1453
1454 length = (imsi_field->c_field - 1) * 2;
1455 if ((imsi_field->field[0] & 0x08) NEQ 0)
1456 length++;
1457 for (i = 0; i < length; i++)
1458 {
1459 digit = ((i & 1) NEQ 0) ?
1460 imsi_field->field[(i + 1) / 2] & 0x0f :
1461 (imsi_field->field[(i + 1) / 2] & 0xf0) >> 4;
1462 imsi_struct->id[i] = digit;
1463 }
1464 imsi_struct->id[i] = 0xff;
1465 }
1466
1467
1468 /*
1469 +--------------------------------------------------------------------+
1470 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1471 | STATE : code ROUTINE : reg_read_kc_cksn |
1472 +--------------------------------------------------------------------+
1473
1474 PURPOSE :
1475
1476 */
1477
1478 GLOBAL void reg_read_kc_cksn (const T_SIM_MM_INSERT_IND *sim_mm_insert_ind)
1479 {
1480 GET_INSTANCE_DATA;
1481 TRACE_FUNCTION ("reg_read_kc_cksn ()");
1482
1483 if (mm_data->reg.update_stat EQ MS_NOT_UPDATED)
1484 {
1485 /*
1486 * clear cipher key, Kc and location area code
1487 */
1488 mm_data->reg.cksn = CKSN_RES;
1489 // mm_data->reg.lac = 0xfffe; // Write-only variable, deleted HM 20.07.00
1490 memset (mm_data->reg.kc, 0xFF, 8);
1491 /* Set bit 4 in ef_indicator to indicate kc change to SIM for next SIM_MM_UPDATE_REQ */
1492 mm_data->ef_indicator|=(0x01 << 3);
1493 }
1494 else
1495 {
1496 /*
1497 * copy parameter from SIM card
1498 */
1499 if(memcmp(mm_data->reg.kc, sim_mm_insert_ind->kc_n.kc, MAX_KC))
1500 {
1501 /* Set bit 4 in ef_indicator to indicate kc change to SIM for next SIM_MM_UPDATE_REQ */
1502 mm_data->ef_indicator|=(0x01 << 3);
1503 }
1504 memcpy (mm_data->reg.kc, sim_mm_insert_ind->kc_n.kc, MAX_KC);
1505 mm_data->reg.cksn = sim_mm_insert_ind->kc_n.kc[8];
1506 }
1507
1508 }
1509
1510 /*
1511 +--------------------------------------------------------------------+
1512 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1513 | STATE : code ROUTINE : reg_read_loc_info |
1514 +--------------------------------------------------------------------+
1515
1516 PURPOSE : Reads the location information delivered by the SIM card
1517 into the registration memory structures.
1518
1519 */
1520
1521 GLOBAL void reg_read_loc_info (const T_loc_info *loc_info)
1522 {
1523 GET_INSTANCE_DATA;
1524 ULONG tmsi_binary;
1525
1526 TRACE_FUNCTION ("reg_read_loc_info ()");
1527
1528 tmsi_binary = (((ULONG)loc_info->loc[0]) << 24) +
1529 (((ULONG)loc_info->loc[1]) << 16) +
1530 (((ULONG)loc_info->loc[2]) << 8) +
1531 (ULONG)loc_info->loc[3];
1532
1533 #ifdef GPRS
1534 mm_data->reg.indicated_tmsi = tmsi_binary;
1535 #endif /* #ifdef GPRS */
1536
1537 mm_data->reg.tmsi = tmsi_binary;
1538 mm_data->reg.lai.mcc[0] = loc_info->loc[4] & 0x0f;
1539 mm_data->reg.lai.mcc[1] = loc_info->loc[4] >> 4;
1540 mm_data->reg.lai.mcc[2] = loc_info->loc[5] & 0x0f;
1541 mm_data->reg.lai.mnc[2] = loc_info->loc[5] >> 4;
1542
1543 mm_data->reg.lai.mnc[0] = loc_info->loc[6] & 0x0f;
1544 mm_data->reg.lai.mnc[1] = loc_info->loc[6] >> 4;
1545 mm_data->reg.lai.lac = loc_info->loc[7] * 256 +
1546 loc_info->loc[8];
1547
1548 if (mm_data->reg.lai.mnc[2] EQ 0xF)
1549 mm_data->reg.lai.c_mnc = 2; /* 2-digit-MNC */
1550 else
1551 mm_data->reg.lai.c_mnc = 3; /* 3-digit-MNC */
1552
1553 if (mm_data->reg.lai.lac EQ 0xffffL)
1554 {
1555 mm_data->reg.lai.lac = 0;
1556 }
1557 mm_data->reg.update_stat = loc_info->loc[10];
1558 if (mm_data->reg.update_stat >= 0x07)
1559 {
1560 mm_data->reg.update_stat = MS_NOT_UPDATED;
1561 }
1562 }
1563
1564 /*
1565 +--------------------------------------------------------------------+
1566 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1567 | STATE : code ROUTINE : reg_read_pref_plmn |
1568 +--------------------------------------------------------------------+
1569
1570 PURPOSE : Reads the preferred PLMN list delivered by the SIM card
1571 into the registration memory structures.
1572
1573 */
1574
1575 GLOBAL void reg_read_pref_plmn (UBYTE* data, USHORT length)
1576 {
1577 GET_INSTANCE_DATA;
1578 USHORT index;
1579 USHORT plmnsel_plmn_count;
1580 USHORT plmn_count = 0;
1581
1582 TRACE_FUNCTION ("reg_read_pref_plmn ()");
1583 /*
1584 * If any additional which does not give complete PLMN id(length MOD UBYTES_PER_PLMN > 0),
1585 * ignore these additional bytes at the end
1586 */
1587 mm_data->reg.sim_plmnsel_len = length-length%UBYTES_PER_PLMN;
1588
1589 if (mm_data->reg.sim_plmnsel_len > MAX_PREF_PLMN_ID * UBYTES_PER_PLMN)
1590 {
1591 mm_data->reg.sim_plmnsel_len = MAX_PREF_PLMN_ID * UBYTES_PER_PLMN; /* Garbage protection */
1592 }
1593 plmnsel_plmn_count = mm_data->reg.sim_plmnsel_len/UBYTES_PER_PLMN;
1594
1595 reg_clear_plmn_list (mm_data->reg.pref_plmn, MAX_PREF_PLMN_ID);
1596
1597 /*Dont copy PLMN entry is empty in the EF*/
1598 for (index =0; index < plmnsel_plmn_count; index++)
1599 {
1600 /*Check if PLMN entry is empty in the EF*/
1601 if(!reg_sim_ef_plmn_field_empty(&data[index*UBYTES_PER_PLMN]))
1602 {
1603 memcpy (&mm_data->reg.pref_plmn[plmn_count*UBYTES_PER_PLMN],
1604 &data[index*UBYTES_PER_PLMN], UBYTES_PER_PLMN);
1605 plmn_count++;
1606 }
1607 }
1608 }
1609
1610
1611 #ifdef REL99
1612
1613 /*
1614 +-------------------------------------------------------------------------+
1615 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1616 | STATE : code ROUTINE : reg_read_ucps_acctec |
1617 +-------------------------------------------------------------------------+
1618
1619 PURPOSE : Reads the user controlled PLMN selector with access technology
1620 list delivered by the SIM card. PLMN does not support GSM access
1621 are ignored in the pref_plmn list.
1622 */
1623 GLOBAL void reg_read_ucps_acctec(UBYTE* data, USHORT length)
1624 {
1625 GET_INSTANCE_DATA;
1626 USHORT index;
1627 USHORT plmn_count=0;
1628 USHORT ucps_acctech_plmn_count;
1629 TRACE_FUNCTION ("reg_read_ucps_acctec ()");
1630
1631 /*
1632 * If any additional bytes at the end which does not give a complete PLMN id(length
1633 * MOD UBYTES_PER_PLMN_WITH_ACC_TECH > 0), ignore these additional bytes at the end
1634 */
1635 mm_data->reg.sim_ucps_at_len = length-length%UBYTES_PER_PLMN_WITH_ACC_TECH;
1636 ucps_acctech_plmn_count = mm_data->reg.sim_ucps_at_len/UBYTES_PER_PLMN_WITH_ACC_TECH;
1637 reg_clear_plmn_list (mm_data->reg.pref_plmn, MAX_PREF_PLMN_ID);
1638
1639 for( index=0; index < ucps_acctech_plmn_count; index++)
1640 {
1641 if(reg_read_plmn_support_acctec(&data[index*UBYTES_PER_PLMN_WITH_ACC_TECH]))
1642 {
1643 /*Check if PLMN entry is empty in the EF*/
1644 if(!reg_sim_ef_plmn_field_empty(&data[index*UBYTES_PER_PLMN_WITH_ACC_TECH]))
1645 {
1646 memcpy(&mm_data->reg.pref_plmn[plmn_count*UBYTES_PER_PLMN],
1647 &data[index*UBYTES_PER_PLMN_WITH_ACC_TECH], UBYTES_PER_PLMN);
1648 plmn_count++;
1649 }
1650 }
1651 if(plmn_count >= MAX_PREF_PLMN_ID)
1652 {
1653 /*MAX_PREF_PLMN_ID PLMN in pref_plmn list will be copied*/
1654 break;
1655 }
1656 }
1657 /*
1658 * Number of plmn copied in the pref_plmn list from the user
1659 * controlled PLMN selector with access technology list
1660 * delivered by the SIM card. This informaiont will be used during copy of
1661 * PLMN from Operator controlled PLMN selector with access technology list
1662 * delivered by the SIM card.
1663 */
1664 mm_data->reg.sim_ucps_at_len = plmn_count*UBYTES_PER_PLMN;
1665 }
1666
1667 /*
1668 +--------------------------------------------------------------------------+
1669 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1670 | STATE : code ROUTINE : reg_read_plmn_support_acctec |
1671 +--------------------------------------------------------------------------+
1672
1673 PURPOSE : This function tests whether plmn points to an access technology
1674 which is supported by the MS. Return TRUE if GSM access technology
1675 is supported else FALSE.
1676 */
1677
1678 GLOBAL BOOL reg_read_plmn_support_acctec (UBYTE* plmn_bytes)
1679 {
1680 /*
1681 * Check if GSM access technology is supported by the PLMN. Return TRUE
1682 * if supported else FALSE
1683 * Spec 11.11 v8.9.1 For each User/Operator controlled PLMN Selector with Access Technology
1684 * Byte 5th: 8th bit = 1: GSM access technology selected;
1685 * Byte 5th: 8th bit = 0: GSM access technology selected;
1686 */
1687
1688 return ((plmn_bytes[4] & 0x80) EQ 0x80);
1689 }
1690
1691 /*
1692 +--------------------------------------------------------------------+
1693 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1694 | STATE : code ROUTINE : reg_read_plmn_present |
1695 +--------------------------------------------------------------------+
1696
1697 PURPOSE : This function tests whether plmn points to an PLMN already
1698 exists in the pref_plmn list. TRUE will be returned if plmn
1699 already exists in the pref_plmn list, otherwise FALSE.
1700 */
1701
1702 GLOBAL BOOL reg_read_plmn_present (UBYTE* plmn_bytes)
1703 {
1704 GET_INSTANCE_DATA;
1705 USHORT index;
1706 USHORT pref_plmn_count;
1707 pref_plmn_count = mm_data->reg.sim_ucps_at_len/UBYTES_PER_PLMN;
1708 for(index=0; index < pref_plmn_count; index++)
1709 {
1710 if(((mm_data->reg.pref_plmn[index*UBYTES_PER_PLMN] EQ plmn_bytes[0]) AND
1711 (mm_data->reg.pref_plmn[index*UBYTES_PER_PLMN+1] EQ plmn_bytes[1]) AND
1712 (mm_data->reg.pref_plmn[index*UBYTES_PER_PLMN+2] EQ plmn_bytes[2])))
1713 {
1714 return TRUE;
1715 }
1716 }
1717 return FALSE;
1718 }
1719
1720
1721 /*
1722 +------------------------------------------------------------------------------+
1723 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1724 | STATE : code ROUTINE : reg_read_ocps_acctec |
1725 +------------------------------------------------------------------------------+
1726
1727 PURPOSE : Read Operator controlled PLMN selector with access technology list delivered by
1728 the SIM card. This can happens only after SIM insert indication indicates to read
1729 file from SIM.
1730 */
1731 GLOBAL void reg_read_ocps_acctec(UBYTE* data, USHORT length)
1732 {
1733 GET_INSTANCE_DATA;
1734 USHORT index;
1735 USHORT plmn_count;
1736 USHORT ocps_acctech_plmn_count;
1737 TRACE_FUNCTION ("reg_read_ocps_acctec ()");
1738 /*
1739 * If any additional bytes at the end which does not give a complete PLMN id(length
1740 * MOD UBYTES_PER_PLMN_WITH_ACC_TECH > 0), ignore these additional bytes at the end
1741 */
1742 mm_data->reg.sim_ocps_at_len = length-length%UBYTES_PER_PLMN_WITH_ACC_TECH;
1743 /*
1744 * Remember Number of plmn already copied in the pref_plmn list from the user
1745 * controlled PLMN selector with access technology list.
1746 */
1747 plmn_count = mm_data->reg.sim_ucps_at_len/UBYTES_PER_PLMN;
1748 ocps_acctech_plmn_count = mm_data->reg.sim_ocps_at_len/UBYTES_PER_PLMN_WITH_ACC_TECH;
1749
1750 for( index=0; index < ocps_acctech_plmn_count; index++)
1751 {
1752 /*Check if the PLMN supports GSM access technology*/
1753 if (reg_read_plmn_support_acctec(&data[index*UBYTES_PER_PLMN_WITH_ACC_TECH]))
1754 {
1755 /*Check if PLMN entry is empty in the EF*/
1756 if(!reg_sim_ef_plmn_field_empty(&data[index*UBYTES_PER_PLMN_WITH_ACC_TECH]))
1757 {
1758 /*Check if the PLMN is already present in the pref_plmn list*/
1759 if(!reg_read_plmn_present(&data[index*UBYTES_PER_PLMN_WITH_ACC_TECH]))
1760 {
1761 memcpy(&mm_data->reg.pref_plmn[plmn_count*UBYTES_PER_PLMN],
1762 &data[index*UBYTES_PER_PLMN_WITH_ACC_TECH], UBYTES_PER_PLMN);
1763 plmn_count++;
1764 }
1765 }
1766 if(plmn_count >= MAX_PREF_PLMN_ID)
1767 {
1768 /*MAX_PREF_PLMN_ID PLMN in pref_plmn list will be copied*/
1769 break;
1770 }
1771 }
1772 }
1773 }
1774
1775
1776 #endif
1777 /*
1778 +--------------------------------------------------------------------+
1779 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1780 | STATE : code ROUTINE : reg_clear_plmn |
1781 +--------------------------------------------------------------------+
1782
1783 PURPOSE : Clears a given PLMN.
1784
1785 */
1786
1787 GLOBAL void reg_clear_plmn (T_plmn *plmn)
1788 {
1789 TRACE_FUNCTION ("reg_clear_plmn()");
1790
1791 memset (plmn, 0x0F, sizeof (T_plmn));
1792 plmn->v_plmn = FALSE;
1793 }
1794
1795
1796 /*
1797 +--------------------------------------------------------------------+
1798 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1799 | STATE : code ROUTINE : reg_clear_plmn_list |
1800 +--------------------------------------------------------------------+
1801
1802 PURPOSE : Clears a given PLMN list. Returns TRUE if the function
1803 actually had to change data.
1804
1805 */
1806
1807 GLOBAL BOOL reg_clear_plmn_list (UBYTE *plmn_list, USHORT list_size)
1808 {
1809 USHORT i;
1810 USHORT byte_count;
1811
1812 TRACE_FUNCTION ("reg_clear_plmn_list()");
1813
1814 byte_count = UBYTES_PER_PLMN * list_size;
1815
1816 for (i = 0; i < byte_count; i++)
1817 {
1818 if (plmn_list[i] NEQ NOT_PRESENT_8BIT)
1819 {
1820 memset (plmn_list, NOT_PRESENT_8BIT, UBYTES_PER_PLMN * list_size);
1821 TRACE_EVENT ("list actually deleted");
1822 return TRUE; /* List has been changed */
1823 }
1824 }
1825 return FALSE; /* Nothing changed */
1826 }
1827
1828 /*
1829 +--------------------------------------------------------------------+
1830 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1831 | STATE : code ROUTINE : reg_unpack_plmn |
1832 +--------------------------------------------------------------------+
1833
1834 PURPOSE : Unpacks a PLMN from compressed form to uncompressed form.
1835
1836 */
1837
1838 GLOBAL void reg_unpack_plmn (T_plmn *plmn, const UBYTE *packed, USHORT index)
1839 {
1840 /* TRACE_FUNCTION ("reg_unpack_plmn()"); */ /* Avoid too much traces */
1841
1842 index *= UBYTES_PER_PLMN;
1843 plmn->mcc[0] = packed[index] & 0x0f;
1844 plmn->mcc[1] = packed[index] >> 4;
1845 index++;
1846 plmn->mcc[2] = packed[index] & 0x0f;
1847 plmn->mnc[2] = packed[index] >> 4;
1848 index++;
1849 plmn->mnc[0] = packed[index] & 0x0f;
1850 plmn->mnc[1] = packed[index] >> 4;
1851 index++;
1852 if ((plmn->mcc[0] & 0x0F) EQ 0x0F)
1853 plmn->v_plmn = V_PLMN_NOT_PRES;
1854 else
1855 plmn->v_plmn = V_PLMN_PRES;
1856 }
1857
1858
1859 /*
1860 +--------------------------------------------------------------------+
1861 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1862 | STATE : code ROUTINE : reg_pack_plmn |
1863 +--------------------------------------------------------------------+
1864
1865 PURPOSE : Packs a PLMN from uncompressed form to compressed form.
1866
1867 */
1868
1869 GLOBAL void reg_pack_plmn (UBYTE *packed, USHORT index, const T_plmn *plmn)
1870 {
1871 /* TRACE_FUNCTION ("reg_pack_plmn()"); */ /* Avoid too much traces */
1872
1873 index *= UBYTES_PER_PLMN;
1874 packed[index] = plmn->mcc[1] << 4;
1875 packed[index] += plmn->mcc[0];
1876 index++;
1877 packed[index] = plmn->mnc[2] << 4;
1878 packed[index] += plmn->mcc[2];
1879 index++;
1880 packed[index] = plmn->mnc[1] << 4;
1881 packed[index] += plmn->mnc[0];
1882 index++;
1883 }
1884
1885 /*
1886 +--------------------------------------------------------------------+
1887 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1888 | STATE : code ROUTINE : reg_set_bcch_info |
1889 +--------------------------------------------------------------------+
1890
1891 PURPOSE : Fill in the BCCH information in SIM_MM_UPDATE_REQ using
1892 the new data in the registration data structures.
1893
1894 */
1895
1896 GLOBAL void reg_set_bcch_info (T_SIM_MM_UPDATE_REQ *sim_mm_update_req)
1897 {
1898 GET_INSTANCE_DATA;
1899 TRACE_FUNCTION ("reg_set_bcch_info ()");
1900
1901 if (!mm_normal_upd_needed())
1902 {
1903 if(memcmp(mm_data->reg.bcch, mm_data->mm.bcch, SIZE_BCCH))
1904 {
1905 /* Set bit 2 in ef_indicator to indicate bcch_info change to SIM */
1906 mm_data->ef_indicator|=(0x01 << 1);
1907 }
1908 memcpy (mm_data->reg.bcch, mm_data->mm.bcch, SIZE_BCCH);
1909 }
1910 sim_mm_update_req->bcch_inf.c_bcch = SIZE_BCCH;
1911 memcpy (sim_mm_update_req->bcch_inf.bcch, mm_data->reg.bcch, SIZE_BCCH);
1912 }
1913
1914 /*
1915 +--------------------------------------------------------------------+
1916 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1917 | STATE : code ROUTINE : reg_set_forb_plmns |
1918 +--------------------------------------------------------------------+
1919
1920 PURPOSE : Fill the forbidden PLMN field in the SIM_MM_UPDATE_REQ
1921 primitive with the actual values in the MM data structures.
1922
1923 */
1924
1925 GLOBAL void reg_set_forb_plmns (T_SIM_MM_UPDATE_REQ *sim_mm_update_req)
1926 {
1927 GET_INSTANCE_DATA;
1928 T_plmn forb_plmn;
1929 UBYTE sim_forb_plmn_list[MAX_SIM_FORB_PLMN_ID * UBYTES_PER_PLMN];
1930 USHORT i;
1931
1932 TRACE_FUNCTION ("reg_set_forb_plmns ()");
1933
1934 memcpy (sim_forb_plmn_list,
1935 mm_data->reg.forb_plmn,
1936 MAX_SIM_FORB_PLMN_ID * UBYTES_PER_PLMN);
1937
1938 for (i = MAX_SIM_FORB_PLMN_ID; i < MAX_FORB_PLMN_ID; i++)
1939 {
1940 reg_unpack_plmn (&forb_plmn, mm_data->reg.forb_plmn, i);
1941 if (!reg_plmn_empty (&forb_plmn))
1942 {
1943 reg_plmn_add_bad (sim_forb_plmn_list,
1944 MAX_SIM_FORB_PLMN_ID,
1945 &forb_plmn);
1946 }
1947 }
1948
1949 sim_mm_update_req->forb_plmn.c_forb = MAX_SIM_FORB_PLMN_ID * UBYTES_PER_PLMN;
1950 memcpy (sim_mm_update_req->forb_plmn.forb,
1951 sim_forb_plmn_list,
1952 MAX_SIM_FORB_PLMN_ID * UBYTES_PER_PLMN);
1953
1954 #ifndef NTRACE
1955 for (i = 0; i < MAX_SIM_FORB_PLMN_ID; i++)
1956 {
1957 reg_unpack_plmn (&forb_plmn, sim_mm_update_req->forb_plmn.forb, i);
1958 TRACE_EVENT_P6 ("FORB = %x%x%x %x%x%x",
1959 forb_plmn.mcc[0],
1960 forb_plmn.mcc[1],
1961 forb_plmn.mcc[2],
1962 forb_plmn.mnc[0],
1963 forb_plmn.mnc[1],
1964 forb_plmn.mnc[2]);
1965 }
1966 #endif /* #ifndef NTRACE */
1967 }
1968
1969 /*
1970 +--------------------------------------------------------------------+
1971 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1972 | STATE : code ROUTINE : reg_set_kc |
1973 +--------------------------------------------------------------------+
1974
1975 PURPOSE :
1976
1977 */
1978
1979 GLOBAL void reg_set_kc (T_SIM_MM_UPDATE_REQ *sim_mm_update_req)
1980 {
1981 GET_INSTANCE_DATA;
1982 TRACE_FUNCTION ("reg_set_kc ()");
1983
1984 sim_mm_update_req->cksn = mm_data->reg.cksn;
1985 memcpy (sim_mm_update_req->kc, mm_data->reg.kc, MAX_KC);
1986
1987 TRACE_EVENT_P1 ("CKSN = %d", mm_data->reg.cksn);
1988 }
1989
1990 /*
1991 +--------------------------------------------------------------------+
1992 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
1993 | STATE : code ROUTINE : reg_set_loc_info |
1994 +--------------------------------------------------------------------+
1995
1996 PURPOSE : Set the location information in the SIM_MM_UPDATE_REQ
1997 primitive to the actual values of the MM data structures.
1998
1999 */
2000
2001 GLOBAL void reg_set_loc_info (T_SIM_MM_UPDATE_REQ *sim_mm_update_req)
2002 {
2003 GET_INSTANCE_DATA;
2004 ULONG tmsi_binary;
2005
2006 TRACE_FUNCTION ("reg_set_loc_info ()");
2007
2008 sim_mm_update_req->loc_info.c_loc = SIZE_LOC_INFO;
2009
2010 tmsi_binary = mm_data->reg.tmsi;
2011
2012 mm_mmgmm_tmsi_ind (tmsi_binary);
2013
2014 sim_mm_update_req->loc_info.loc[0] = (UBYTE)(tmsi_binary >> 24);
2015 sim_mm_update_req->loc_info.loc[1] = (UBYTE)(tmsi_binary >> 16);
2016 sim_mm_update_req->loc_info.loc[2] = (UBYTE)(tmsi_binary >> 8);
2017 sim_mm_update_req->loc_info.loc[3] = (UBYTE)tmsi_binary;
2018 sim_mm_update_req->loc_info.loc[4] = mm_data->reg.lai.mcc[1] << 4;
2019 sim_mm_update_req->loc_info.loc[4] += mm_data->reg.lai.mcc[0];
2020 sim_mm_update_req->loc_info.loc[5] = mm_data->reg.lai.mnc[2] << 4;
2021 sim_mm_update_req->loc_info.loc[5] += mm_data->reg.lai.mcc[2];
2022 sim_mm_update_req->loc_info.loc[6] = mm_data->reg.lai.mnc[1] << 4;
2023 sim_mm_update_req->loc_info.loc[6] += mm_data->reg.lai.mnc[0];
2024 sim_mm_update_req->loc_info.loc[7] = mm_data->reg.lai.lac >> 8;
2025 sim_mm_update_req->loc_info.loc[8] = mm_data->reg.lai.lac & 0xff;
2026 sim_mm_update_req->loc_info.loc[9] = 0;
2027 sim_mm_update_req->loc_info.loc[10] = mm_data->reg.update_stat;
2028 sim_mm_update_req->cell_identity = mm_data->mm.cid;
2029 }
2030
2031
2032 /*
2033 +--------------------------------------------------------------------+
2034 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2035 | STATE : code ROUTINE : reg_send_sim_read_req |
2036 +--------------------------------------------------------------------+
2037
2038 PURPOSE : This functions sends SIM_READ_REQ for the requested field
2039 Currently only used by function reg_read_next_sim_file
2040
2041 */
2042
2043 LOCAL void reg_send_sim_read_req ( USHORT datafield,
2044 T_path_info *path_info_ptr,
2045 UBYTE act_length,
2046 UBYTE max_length )
2047 {
2048 GET_INSTANCE_DATA;
2049 PALLOC (read_req, SIM_READ_REQ);
2050
2051 TRACE_FUNCTION ("mm_send_sim_read_req()");
2052
2053 read_req->source = SRC_MM;
2054 /* req_id can be set to 0 as MM sends a SIM_READ_REQ only
2055 * when it gets the SIM_READ_CNF to the previous request */
2056 read_req->req_id = 0;
2057
2058 read_req->offset = 0;
2059
2060 if(path_info_ptr NEQ NULL)
2061 {
2062 read_req->v_path_info = TRUE;
2063 read_req->path_info = *path_info_ptr;
2064 }
2065 else
2066 {
2067 read_req->v_path_info = FALSE;
2068 }
2069
2070 mm_data->sim_read_req_data_field = read_req->datafield = datafield;
2071
2072 read_req->length = act_length;
2073 read_req->max_length = max_length;
2074 PSENDX (SIM, read_req);
2075 }
2076
2077 /*
2078 +--------------------------------------------------------------------+
2079 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2080 | STATE : code ROUTINE : reg_read_next_sim_file |
2081 +--------------------------------------------------------------------+
2082
2083 PURPOSE : This functions requests the next changed, unread SIM file
2084
2085 RETURN: TRUE if function call caused a pending SIM_READ_CNF
2086 FALSE otherwise
2087
2088 */
2089
2090 GLOBAL BOOL reg_read_next_sim_file (void)
2091 {
2092 GET_INSTANCE_DATA;
2093 /* Definition used to determine sizeof() */
2094 T_SIM_MM_INSERT_IND *insert_ind;
2095
2096 TRACE_FUNCTION ("reg_read_next_sim_file()");
2097
2098 if (mm_data->reg.upd_sim_fplmn EQ SAT_READ_FILE)
2099 {
2100 /* Change of forbidden PLMN indicated */
2101
2102 reg_send_sim_read_req (SIM_FPLMN, NULL, NOT_PRESENT_8BIT, sizeof (insert_ind->forb_plmn.forb));
2103 mm_data->reg.upd_sim_fplmn = SAT_PEND_CNF;
2104 return TRUE;
2105 }
2106
2107 if (mm_data->reg.upd_sim_hplmn EQ SAT_READ_FILE)
2108 {
2109 /* Change of HPLMN search timer indicated */
2110
2111 reg_send_sim_read_req (SIM_HPLMN, NULL, NOT_PRESENT_8BIT, sizeof (insert_ind->hplmn));
2112 mm_data->reg.upd_sim_hplmn = SAT_PEND_CNF;
2113 return TRUE;
2114 }
2115
2116 #ifdef REL99
2117 /*updating status user controlled & operator controlled PLMN selection*/
2118
2119 if (mm_data->reg.upd_sim_ucps_at EQ SAT_READ_FILE)
2120 {
2121 /*
2122 * Change of user controlled PLMN selector with access technology list indicated.
2123 * Max length in SIM READ REQ is sent to FF(255 which is a limitation in SIM READ REQ)instead
2124 * of MAX_PREF_PLMN because MM does not know how many PLMN in the EF are supported GSM access
2125 * technology.So MM will try to read as many as possible.
2126 * In future if MM want to read more than 255 byte for the same EF, MM implementation can
2127 * be extented to send more than one SIM READ REQ for same EF.
2128 */
2129 reg_send_sim_read_req (SIM_UCPS_ACTEC, NULL, (UBYTE)mm_data->reg.sim_ucps_at_len, 0xFF);
2130 mm_data->reg.upd_sim_ucps_at = SAT_PEND_CNF;
2131 return TRUE;
2132 }
2133
2134
2135 if (mm_data->reg.upd_sim_ocps_at EQ SAT_READ_FILE)
2136 {
2137 /*
2138 * Read Operator controlled PLMN selector with access technology list.
2139 * Max length in SIM READ REQ is sent to FF(255 which is a limitation in SIM READ REQ)instead
2140 * of MAX_PREF_PLMN because MM does not know how many PLMN in the EF are supported GSM access
2141 * technology.So MM will try to read as much as possible.
2142 * In future if MM want to read more than 255 byte for the same EF, MM implementation can
2143 * be extented to send more than one SIM READ REQ for same EF.
2144 */
2145 reg_send_sim_read_req (SIM_OCPS_ACTEC, NULL, (UBYTE)mm_data->reg.sim_ocps_at_len, 0xFF);
2146 mm_data->reg.upd_sim_ocps_at = SAT_PEND_CNF;
2147 return TRUE;
2148 }
2149 #endif
2150
2151 if (mm_data->reg.upd_sim_acc EQ SAT_READ_FILE)
2152 {
2153 /* Change of access class indicated */
2154
2155 reg_send_sim_read_req (SIM_ACC,NULL, NOT_PRESENT_8BIT, sizeof (insert_ind->acc_ctrl.acc));
2156 mm_data->reg.upd_sim_acc = SAT_PEND_CNF;
2157 return TRUE;
2158 }
2159
2160 if (mm_data->reg.upd_sim_act_hplmn EQ SAT_READ_FILE)
2161 {
2162 /* Change of AHPLMN indicated */
2163
2164 reg_send_sim_read_req (SIM_CING_AHPLMN,NULL,NOT_PRESENT_8BIT, sizeof (insert_ind->act_hplmn));
2165 mm_data->reg.upd_sim_act_hplmn = SAT_PEND_CNF;
2166 return TRUE;
2167 }
2168 if (mm_data->reg.upd_sim_plmnsel EQ SAT_READ_FILE)
2169 {
2170 /* Change of preferred PLMN list indicated */
2171 /*
2172 * EF PLMNsel will only be used if EFs EFPLMNwAcT & EFOPLMNwAcT are not used.
2173 * mm_data->reg.sim_uocps_at_used will only be true after successful sim read
2174 * cnf for EFs EFPLMNwAcT or EFOPLMNwAcT.
2175 */
2176 #ifdef REL99
2177 if(mm_data->reg.sim_uocps_at_used EQ FALSE)
2178 {
2179 reg_send_sim_read_req (SIM_PLMNSEL,NULL, (UBYTE)mm_data->reg.sim_plmnsel_len, MAX_PREF_PLMN);
2180 mm_data->reg.upd_sim_plmnsel = SAT_PEND_CNF;
2181 return TRUE;
2182 }
2183 else
2184 {
2185 /*
2186 * No need to read EF PLMNsel because EFs EFPLMNwAcT and(or) EFOPLMNwAcT are being used.
2187 */
2188 mm_data->reg.upd_sim_plmnsel = SAT_UNCHANGED;
2189 }
2190 #else
2191
2192 reg_send_sim_read_req (SIM_PLMNSEL, NULL,(UBYTE)mm_data->reg.sim_plmnsel_len, MAX_PREF_PLMN);
2193 mm_data->reg.upd_sim_plmnsel = SAT_PEND_CNF;
2194 return TRUE;
2195
2196 #endif
2197 }
2198 return FALSE;
2199 }
2200
2201
2202 /*
2203 +--------------------------------------------------------------------+
2204 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2205 | STATE : code ROUTINE : reg_end_of_deregistration |
2206 +--------------------------------------------------------------------+
2207
2208 PURPOSE : Indicate or confirm negative registration to MMI/GMM.
2209 The MM restart procedure may be performed.
2210
2211 */
2212
2213 GLOBAL void reg_end_of_deregistration (UBYTE nreg_cause, UBYTE service)
2214 {
2215 GET_INSTANCE_DATA;
2216 BOOL mm_restart;
2217
2218 TRACE_FUNCTION ("reg_end_of_deregistration()");
2219
2220 /* Remember the MM restart condition */
2221 mm_restart = ((mm_data->reg.sim_insert_info NEQ NULL) AND
2222 (mm_data->nreg_cause EQ CS_SIM_REM));
2223
2224 if (mm_data->reg.sim_insert_info NEQ NULL)
2225 {
2226 /* Insert the new SIM data and free primive */
2227 mm_clear_reg_data ();
2228 reg_copy_sim_data (mm_data->reg.sim_insert_info);
2229 PFREE (mm_data->reg.sim_insert_info);
2230 mm_data->reg.sim_insert_info = NULL;
2231 }
2232
2233 if (mm_restart)
2234 {
2235 /*
2236 * End of MM restart procedure, re-register
2237 */
2238 if (mm_data->reg.op.m EQ MODE_AUTO)
2239 {
2240 /*
2241 * Register in automatic mode
2242 */
2243 mm_auto_net_reg ();
2244 }
2245 else
2246 {
2247 /*
2248 * Register in manual mode
2249 */
2250 mm_data->reg.plmn_cnt = 0; /* Delete list of available PLMNs */
2251 mm_data->attempt_cnt = 0;
2252 mm_mmr_reg_req (FUNC_PLMN_SRCH);
2253 }
2254 }
2255 else
2256 {
2257 /*
2258 * This was no MM RESTART
2259 */
2260 if (mm_data->nreg_request)
2261 {
2262 /*
2263 * The deregistration was requested by the MMI
2264 */
2265
2266 if (nreg_cause EQ CS_POW_OFF)
2267 {
2268 /* Hard switch off (AT+CFUN=0), delete SIM data physically */
2269 reg_init ();
2270
2271 mm_data->limited_cause = MMCS_SIM_REMOVED; /* MMCS_SIM_INVAL_NOSIM */
2272 }
2273
2274 mm_mmgmm_nreg_cnf (nreg_cause);
2275 }
2276 else
2277 {
2278 /*
2279 * This was a real SIM remove, the SIM has been pulled
2280 */
2281 if (service EQ NO_SERVICE)
2282 {
2283 mm_mmgmm_nreg_ind (NREG_NO_SERVICE,
2284 SEARCH_NOT_RUNNING,
2285 FORB_PLMN_NOT_INCLUDED);
2286 }
2287 else
2288 {
2289 mm_mmgmm_nreg_ind (NREG_LIMITED_SERVICE,
2290 SEARCH_NOT_RUNNING,
2291 FORB_PLMN_NOT_INCLUDED);
2292 }
2293 }
2294 }
2295
2296 #ifdef GPRS
2297 if (mm_data->gprs.sim_physically_removed)
2298 {
2299 mm_data->gprs.sim_physically_removed = FALSE;
2300
2301 /* Delete registration data */
2302 reg_init ();
2303 }
2304 #endif /* GPRS */
2305 }
2306
2307
2308 /*
2309 +--------------------------------------------------------------------+
2310 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2311 | STATE : code ROUTINE : reg_invalidate_upd_state |
2312 +--------------------------------------------------------------------+
2313
2314 PURPOSE : This function invalidates the update state.
2315
2316 */
2317
2318 #ifdef REL99
2319 GLOBAL void reg_invalidate_upd_state (UBYTE new_update_state, BOOL tmsi_cksn_kc_not_deleted)
2320 #else
2321 GLOBAL void reg_invalidate_upd_state (UBYTE new_update_state)
2322 #endif
2323 {
2324 GET_INSTANCE_DATA;
2325 TRACE_FUNCTION ("reg_invalidate_update_state()");
2326
2327 /* No IMSI ATTACH neccessary anymore */
2328 if (mm_data->first_attach)
2329 {
2330 mm_data->first_attach_mem = mm_data->first_attach;
2331 mm_data->first_attach = FALSE;
2332 }
2333
2334 /* No periodic update needed anymore, needing normal update now */
2335 mm_data->t3212_timeout = FALSE;
2336
2337 /* Set new update state */
2338 mm_data->reg.update_stat = new_update_state;
2339
2340 #ifdef REL99
2341 if(tmsi_cksn_kc_not_deleted EQ TRUE)
2342 {
2343 /*Dont delete LAI CKSN CKSN KC*/
2344 }
2345 else
2346 #endif
2347 {
2348 /* Delete TMSI */
2349 mm_data->reg.tmsi = TMSI_INVALID_VALUE;
2350
2351 /* Delete LAI */
2352 mm_data->reg.lai.lac = LAC_INVALID_VALUE;
2353
2354 /* Delete CKSN */
2355 mm_data->reg.cksn = CKSN_RES;
2356
2357 /* Delete also KC */
2358 memset (mm_data->reg.kc, 0xff, MAX_KC);
2359 }
2360
2361 /* Delete BCCH information */
2362 memset (mm_data->reg.bcch, 0, SIZE_BCCH);
2363
2364 /* Update all EFs on SIM */
2365 mm_data->ef_indicator = 0xFF;
2366 /* Write changed data to SIM */
2367 reg_build_sim_update ();
2368 /* added by TISH 0418 to write simloci to FFS */
2369 mm_write_simloci_to_ffs();
2370 mm_write_imsi_to_ffs();
2371 /* added by TISH 0418 to write simloci to FFS */
2372
2373 /* Check HPLMN timer state */
2374 reg_check_hplmn_tim (mm_data->reg.thplmn);
2375 }
2376
2377
2378 /*
2379 +----------------------------------------------------------------------------+
2380 | PROJECT : GSM-PS (6147) MODULE : MM_MM |
2381 | STATE : code ROUTINE : reg_select_network |
2382 +----------------------------------------------------------------------------+
2383
2384 PURPOSE : This function starts the network registration for the given PLMN.
2385
2386 */
2387
2388 GLOBAL void reg_select_network (const T_plmn *plmn)
2389 {
2390 GET_INSTANCE_DATA;
2391 TRACE_FUNCTION ("reg_select_network()");
2392
2393 mm_data->reg.actual_plmn = *plmn; /* Struct copy */
2394
2395 if (reg_plmn_empty(plmn))
2396 {
2397 if (mm_data->reg.update_stat EQ MS_UPDATED)
2398 {
2399 mm_data->reg.actual_plmn.v_plmn = TRUE;
2400 memcpy(mm_data->reg.actual_plmn.mcc, mm_data->reg.lai.mcc, SIZE_MCC);
2401 memcpy(mm_data->reg.actual_plmn.mnc, mm_data->reg.lai.mnc, SIZE_MNC);
2402 }
2403 else
2404 {
2405 /* If PLMN sent is 0xFF (PLMN not present in FFS) and MM Update Status
2406 * is MS_NOT_UPDATED, We send a error message to ACI */
2407 mm_mmgmm_nreg_ind(NREG_LIMITED_SERVICE,
2408 SEARCH_NOT_RUNNING,
2409 FORB_PLMN_NOT_INCLUDED);
2410 return;
2411 }
2412 }
2413 mm_data->attempt_cnt = 0;
2414 mm_mmr_reg_req (FUNC_PLMN_SRCH);
2415 }
2416
2417
2418 /*
2419
2420 +----------------------------------------------------------------------------+
2421 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2422 | STATE : code ROUTINE : reg_best_plmn_in_country |
2423 +----------------------------------------------------------------------------+
2424
2425 PURPOSE : This function checks whether the given PLMN is the best PLMN
2426 in the country where the mobile is roaming.
2427
2428 */
2429
2430 GLOBAL BOOL reg_best_plmn_in_country (const T_plmn *bcch_plmn)
2431 {
2432 GET_INSTANCE_DATA;
2433 T_plmn hplmn;
2434 USHORT i;
2435
2436 TRACE_FUNCTION ("reg_best_plmn_in_country()");
2437
2438 reg_extract_hplmn (&hplmn);
2439
2440 /* fix for CT PTCRB- TC_26_7_4_5_4_6. HPLMN timer is not started only if
2441 bcch PLMN and HPLMN belong to same country and both are in equivalent PLMN list.
2442 Detailed analysis present in OMAPS00150594*/
2443 if (reg_same_country_plmn (bcch_plmn, &hplmn))
2444 {
2445
2446 if (reg_plmn_equal_eqv (bcch_plmn, &hplmn))
2447 return TRUE; /* The PLMN is the HPLMN */
2448 else
2449 return FALSE; /* National roaming */
2450 }
2451 /* International roaming: Check the preferred PLMN list */
2452 for (i = 0; i < MAX_PREF_PLMN_ID; i++)
2453 {
2454 T_plmn pref_plmn;
2455
2456 reg_unpack_plmn (&pref_plmn, mm_data->reg.pref_plmn, i);
2457
2458 if (reg_same_country_plmn (bcch_plmn, &pref_plmn))
2459 return reg_plmn_equal_eqv (bcch_plmn, &pref_plmn);
2460 }
2461
2462 return TRUE; /* For this country no entry exists */
2463 }
2464
2465
2466 /*
2467
2468 +----------------------------------------------------------------------------+
2469 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2470 | STATE : code ROUTINE : reg_check_hplmn_tim |
2471 +----------------------------------------------------------------------------+
2472
2473 PURPOSE : This function checks whether:
2474 - the HPLMN timer has to be started (if not running) with the duration given as input parameter or
2475 - stopped.
2476 Time unit is decihour.
2477 */
2478
2479 GLOBAL void reg_check_hplmn_tim (UBYTE decihours)
2480 {
2481 GET_INSTANCE_DATA;
2482 TRACE_FUNCTION ("reg_check_hplmn_tim()");
2483
2484 /*
2485 * The HPLMN timer has to be started if all the conditions below are
2486 * fulfilled and is not running already. Otherwise, it has to be
2487 * stopped.
2488 * - Registration state is updated
2489 * - MS is roaming on a VPLMN
2490 * - Registration mode is automatic
2491 * - THPLMN Elementary File is not equal to zero
2492 */
2493
2494 if (mm_full_service_pplmn_scan())
2495 {
2496 if (mm_data->reg.op.m EQ M_AUTO AND
2497 mm_data->reg.thplmn NEQ 0 AND
2498 mm_data->reg.update_stat NEQ MS_LA_NOT_ALLOWED AND
2499 !reg_best_plmn_in_country (&mm_data->reg.actual_plmn))
2500 {
2501 /*
2502 * Period of HPLMN is controlled by EF_HPLMN file of the SIM.
2503 * According to TS 11.11 chapter 10.3.5 :
2504 * 0- no search attempt
2505 * N- search attempts every N*6 min intervals (6 min to 8 hours)
2506 * For phase 1 SIM wehereby this EF is not available, a default
2507 * value of 1 hour shall be used according to TS 22.011
2508 * chapter 3.2.2.5. In G23 this is managed by SIM entity that
2509 * will force this default value within SIM_INSERT_IND.
2510 */
2511 if (!TIMERACTIVE(T_HPLMN))
2512 {
2513 if (mm_data->first_attach_mem)
2514 {
2515 TRACE_EVENT_P1 ("Start initial HPLMN timer: %d min", 2);
2516 TIMERSTART(T_HPLMN, HPLMN_INITIAL_DELAY);
2517 }
2518 else
2519 {
2520 TRACE_EVENT_P1 ("Start HPLMN timer: %d", decihours);
2521 TIMERSTART(T_HPLMN, decihours * 360000);
2522 }
2523 }/* if timeractive*/
2524 }/*end if mm_data->reg.op.m eq*/
2525 else
2526 {
2527 reg_stop_hplmn_tim ();
2528 mm_data->first_attach_mem = FALSE;
2529 }
2530
2531 }/* end if mm_full_service_pplmn,,,*/
2532 else
2533 {
2534 reg_stop_hplmn_tim();
2535 }
2536 /* Issue 31179 This timer is started for foreign mcc only for cingular */
2537 if( mm_data->reg.is_cingular_sim AND !mm_data->first_attach)
2538 {
2539 T_plmn hplmn;
2540 reg_extract_hplmn (&hplmn);
2541 if(!TIMERACTIVE(T_HPLMN))
2542 {
2543 if(memcmp(&(mm_data->reg.actual_plmn.mcc[0]), &(hplmn.mcc[0]), SIZE_MCC) NEQ 0)
2544 {
2545 TRACE_EVENT_P1 ("Start HPLMN timer: %d", decihours);
2546 TIMERSTART(T_HPLMN, decihours * 360000);
2547 }
2548 }
2549 }
2550 return;
2551 }
2552
2553
2554 /*
2555 +----------------------------------------------------------------------------+
2556 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2557 | STATE : code ROUTINE : reg_stop_hplmn_tim |
2558 +----------------------------------------------------------------------------+
2559
2560 PURPOSE : This function stops the HPLMN timer.
2561 */
2562
2563 GLOBAL void reg_stop_hplmn_tim (void)
2564 {
2565 GET_INSTANCE_DATA;
2566 TRACE_FUNCTION ("reg_stop_hplmn_tim()");
2567
2568 TRACE_EVENT("Stop HPLMN timer");
2569 TIMERSTOP(T_HPLMN);
2570 mm_data->plmn_scan_mm = FALSE;
2571 }
2572
2573
2574 /*
2575 +----------------------------------------------------------------------------+
2576 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2577 | STATE : code ROUTINE : reg_plmn_in_pref_list |
2578 +----------------------------------------------------------------------------+
2579
2580 PURPOSE : This function returns TRUE if the PLMN belongs to the
2581 preferred list.
2582 */
2583
2584 GLOBAL BOOL reg_plmn_in_pref_list (const T_plmn *plmn)
2585 {
2586 GET_INSTANCE_DATA;
2587 USHORT i;
2588 TRACE_FUNCTION ("reg_plmn_in_pref_list()");
2589
2590 for (i = 0; i < MAX_PREF_PLMN_ID; i++)
2591 {
2592 T_plmn pref_plmn;
2593
2594 reg_unpack_plmn (&pref_plmn, mm_data->reg.pref_plmn, i);
2595 if (!reg_plmn_empty (&pref_plmn))
2596 {
2597 if (reg_plmn_equal_sim (plmn, &pref_plmn))
2598 return TRUE;
2599 }
2600 }
2601
2602 return FALSE;
2603 }
2604
2605
2606 /*
2607 +----------------------------------------------------------------------------+
2608 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2609 | STATE : code ROUTINE : reg_same_country_plmn |
2610 +----------------------------------------------------------------------------+
2611
2612 PURPOSE : This function returns TRUE if both PLMN belongs to the
2613 same country, handling the special case of NA (several
2614 MCC).
2615 */
2616
2617 GLOBAL BOOL reg_same_country_plmn (const T_plmn *plmn1,
2618 const T_plmn *plmn2)
2619 {
2620 /* TRACE_FUNCTION ("reg_same_country_plmn()"); */ /* Avoid too much traces */
2621
2622 if (reg_plmn_is_NA_plmn(plmn1))
2623 return (reg_plmn_is_NA_plmn(plmn2));
2624 else
2625 return (memcmp(&(plmn1->mcc[0]), &(plmn2->mcc[0]), SIZE_MCC) EQ 0);
2626 }
2627
2628
2629 /*
2630 +----------------------------------------------------------------------------+
2631 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2632 | STATE : code ROUTINE : reg_check_plmn_search |
2633 +----------------------------------------------------------------------------+
2634
2635 PURPOSE : This function checks whether a better PLMN has been found and,
2636 if so, starts automatic registration on this PLMN.
2637 In case the search has to be aborted for some reason (eg.
2638 MM is not in IDLE mode), the HPLMN search timer is started
2639 using a small value.
2640 */
2641
2642 GLOBAL void reg_check_plmn_search (USHORT cause,
2643 const T_RR_ABORT_IND *rr_abort_ind)
2644 {
2645 GET_INSTANCE_DATA;
2646 T_plmn plmn;
2647 BOOL success;
2648
2649 TRACE_FUNCTION ("reg_check_plmn_search()");
2650
2651 if (mm_data->plmn_scan_mm)
2652 {
2653 /*
2654 * A MM search was ongoing
2655 */
2656 switch (cause)
2657 {
2658 case MMCS_PLMN_NOT_IDLE_MODE:
2659 TRACE_EVENT ("PLMN scan aborted");
2660
2661 /*
2662 * PLMN scan has been aborted because not compatible with the
2663 * current activity of the MS. Restart timer with a small duration.
2664 * Bufferize / postpone this in a later implementation (Maybe).
2665 */
2666 reg_check_hplmn_tim (HPLMN_REARM_DELAY);
2667 break;
2668
2669 case MMCS_SUCCESS:
2670 /*
2671 * First we need to create the list of available PLMNs. We
2672 * are not interested in the ones belonging to a forbidden list
2673 * but we are still interested in the current RPLMN.
2674 * Criteria to start the PLMN selection will be:
2675 * 1) First PLMN in the list (higher priority) is not the RPLMN
2676 * 2) Either it is the HPLMN,
2677 * Or it is an other PLMN, which belongs to the same country
2678 * than the current VPLMN, and it belongs to the preferred
2679 * list ie it has not been inserted here to the randomization
2680 * of the PLMNs whose fieldstrength is higher than -85 dBm.
2681 */
2682
2683 reg_create_plmn_list (rr_abort_ind, WITH_RPLMN);
2684
2685 success = FALSE;
2686
2687 while (mm_data->reg.plmn_index < mm_data->reg.plmn_cnt)
2688 {
2689 reg_unpack_plmn (&plmn, mm_data->reg.plmn, mm_data->reg.plmn_index);
2690
2691 if (reg_plmn_equal_sim (&plmn, &mm_data->reg.actual_plmn))
2692 {
2693 TRACE_EVENT ("VPLMN hit - cancel");
2694 break;
2695 }
2696 else if (reg_plmn_equal_hplmn (&plmn))
2697 {
2698 /* fix for TC 26.7.4.5.4.4. Select a PLMN of Same country
2699 and not HPLMN if in International roaming only for Test sim.*/
2700 if((mm_data->reg.op.ts EQ TS_NO_AVAIL) OR
2701 reg_same_country_plmn (&plmn, &mm_data->reg.actual_plmn))
2702 {
2703 TRACE_EVENT ("HPLMN found - success");
2704 success = TRUE;
2705 break;
2706 }
2707 else
2708 {
2709 mm_data->reg.plmn_index++;
2710 continue;
2711 }
2712
2713 }
2714 else if (!reg_plmn_in_pref_list (&plmn))
2715 {
2716 TRACE_EVENT ("PPLMN list end - cancel");
2717 break;
2718 }
2719 else if(mm_data->reg.is_cingular_sim)
2720 {
2721 TRACE_EVENT ("better PLMN from HPLMN list in Cingular - success");
2722 success = TRUE;
2723 break;
2724 }
2725 else if (reg_same_country_plmn (&plmn, &mm_data->reg.actual_plmn))
2726 {
2727 TRACE_EVENT ("better PLMN same country - success");
2728 success = TRUE;
2729 break;
2730 }
2731 else
2732 mm_data->reg.plmn_index++;
2733 }
2734
2735 if (success)
2736 {
2737 TRACE_EVENT ("PPLMN rescan pass");
2738
2739 /*
2740 * An alternate network candidate has been found, so try to camp
2741 * on it. It the registration procedure fails, then the normal automatic
2742 * network selection procedure will apply.
2743 */
2744 reg_select_network (&plmn); /*lint !e772 conceivably not initialized */
2745 }
2746 else
2747 {
2748 TRACE_EVENT ("PPLMN rescan failed");
2749
2750 /*
2751 * PLMN rescan did not provide any interesting results,
2752 * so restart timer.
2753 */
2754 reg_check_hplmn_tim (mm_data->reg.thplmn);
2755 }
2756
2757 /*
2758 * Do not consider the forbidden PLMNs for MM's internal operation
2759 */
2760 reg_create_plmn_list (rr_abort_ind, WITH_OTHER_PLMNS);
2761 break;
2762
2763 case MMCS_SIM_REMOVED:
2764 /*
2765 * Not relevant for MM initiated search.
2766 */
2767 break;
2768
2769 default:
2770 TRACE_ERROR (UNEXPECTED_DEFAULT);
2771 break;
2772 }
2773 }
2774
2775 mm_data->plmn_scan_mm = FALSE;
2776 mm_data->plmn_scan_mmi = FALSE;
2777
2778 }
2779
2780 /*
2781 +----------------------------------------------------------------------------+
2782 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2783 | STATE : code ROUTINE : reg_store_eqv_plmns |
2784 +----------------------------------------------------------------------------+
2785
2786 PURPOSE : This function checks whether a received equivalent PLMN list
2787 matches an already stored list. If no match then the new
2788 equivalent PLMN list overwrites the currently stored list.
2789 */
2790 BOOL reg_store_eqv_plmns(T_eqv_plmn_list *rx_eplmn_list, T_plmn *plmn)
2791 {
2792 GET_INSTANCE_DATA;
2793 U8 i=0, j=0;
2794 T_plmn local_plmn;
2795 UBYTE local_store[EPLMNLIST_SIZE*UBYTES_PER_PLMN];
2796
2797 TRACE_FUNCTION ("reg_store_eqv_plmns()");
2798
2799 if (rx_eplmn_list->c_eqv_plmn > EPLMNLIST_SIZE)
2800 {
2801 rx_eplmn_list->c_eqv_plmn = 0;
2802 TRACE_ERROR ("count out of range");
2803 return FALSE;
2804 }
2805
2806 for (i=0; i < EPLMNLIST_SIZE - 1; i++)
2807 {
2808 /* Use 0xf as filler for 2 digit MNCs */
2809 if (rx_eplmn_list->eqv_plmn[i].c_mnc EQ (SIZE_MNC-1))
2810 rx_eplmn_list->eqv_plmn[i].mnc[SIZE_MNC-1] = 0xf;
2811 }
2812
2813 /*Convert the new list into a MM-friendly format*/
2814 reg_pack_plmn(local_store, 0, plmn);
2815
2816 for(i=0;i<EPLMNLIST_SIZE-1;i++)
2817 {
2818 memcpy(&local_plmn.mcc, &rx_eplmn_list->eqv_plmn[i].mcc, SIZE_MCC);
2819 memcpy(&local_plmn.mnc, &rx_eplmn_list->eqv_plmn[i].mnc, SIZE_MNC);
2820
2821 reg_pack_plmn(local_store, i+1, &local_plmn);
2822 }
2823
2824 if(memcmp(local_store, mm_data->reg.eqv_plmns.eqv_plmn_list, EPLMNLIST_SIZE*UBYTES_PER_PLMN))
2825 {
2826 /* The Equivalent PLMN list has changed */
2827
2828 /*Initialise EPLMN storage*/
2829 memset (&mm_data->reg.eqv_plmns.eqv_plmn_list, 0xFF, EPLMNLIST_SIZE*UBYTES_PER_PLMN);
2830
2831 /* Store Equivalent PLMNs */
2832 for(i=0,j=0;i<EPLMNLIST_SIZE;i++)
2833 {
2834 T_plmn new_plmn;
2835
2836 reg_unpack_plmn(&new_plmn, local_store, i);
2837
2838 /* Remove any forbidden PLMNs from the new EPLMN list */
2839 if(!reg_plmn_in_list(mm_data->reg.forb_plmn, MAX_FORB_PLMN_ID, &new_plmn))
2840 reg_pack_plmn(mm_data->reg.eqv_plmns.eqv_plmn_list, j++, &new_plmn);
2841 }
2842 return(TRUE);
2843 }
2844 return(FALSE);
2845 }
2846
2847
2848 /*
2849 +----------------------------------------------------------------------------+
2850 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2851 | STATE : code ROUTINE : reg_read_acting_hplmn |
2852 +----------------------------------------------------------------------------+
2853
2854 PURPOSE : This function copies the AHPLMN value read from the SIM at poweron
2855 or after REFRESH command from network.
2856 */
2857 GLOBAL void reg_read_acting_hplmn (const U8 acting_hplmn[])
2858 {
2859 GET_INSTANCE_DATA;
2860 mm_data->reg.acting_hplmn.mcc[0] = acting_hplmn[0] &0x0f;
2861 mm_data->reg.acting_hplmn.mcc[1] = acting_hplmn[0] >> 4;
2862 mm_data->reg.acting_hplmn.mcc[2] = acting_hplmn[1] &0x0f;
2863 mm_data->reg.acting_hplmn.mnc[2] = acting_hplmn[1] >>4;
2864 mm_data->reg.acting_hplmn.mnc[0] = acting_hplmn[2] &0x0f;
2865 mm_data->reg.acting_hplmn.mnc[1] = acting_hplmn[2] >>4;
2866 }
2867
2868
2869 /*
2870 +----------------------------------------------------------------------------+
2871 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2872 | STATE : code ROUTINE : valid_acting_hplmn |
2873 +----------------------------------------------------------------------------+
2874
2875 PURPOSE : This function checks whether a received AHPLMN has the
2876 same MCC as the True-HPLMN and if yes then checks the
2877 validity of the MNC digits. Thus it checks the validity
2878 of AHPLMN received.
2879 */
2880
2881 BOOL valid_acting_hplmn(T_plmn *acting_hplmn)
2882 {
2883 GET_INSTANCE_DATA;
2884 T_plmn hplmn;
2885
2886 UINT temp1=0x0F0F0F;
2887
2888 /*This will be set to TRUE if AHPLMN is FFFFFF*/
2889 mm_data->reg.acting_hplmn_invalid = FALSE;
2890
2891 TRACE_FUNCTION ("valid_acting_hplmn()");
2892
2893 /* Extract HPLMN from IMSI and compare MCC of HPLMN and AHPLMN */
2894 reg_extract_hplmn(&hplmn);
2895
2896 /* Check If the AHPLMN contains FFFFFF */
2897
2898 if (!(memcmp(acting_hplmn->mcc,&temp1,SIZE_MCC) AND
2899 memcmp(acting_hplmn->mnc,&temp1,SIZE_MNC)))
2900 {
2901 mm_data->reg.acting_hplmn.v_plmn = V_PLMN_NOT_PRES;
2902 mm_data->reg.acting_hplmn_invalid = TRUE;
2903 return FALSE;
2904 }
2905
2906 /* If MCC of HPLMN and AHPLMN differs invalidate AHPLMN */
2907 if ( memcmp(acting_hplmn->mcc,mm_data->reg.imsi_struct.id,3) )
2908 {
2909 mm_data->reg.acting_hplmn.v_plmn = V_PLMN_NOT_PRES;
2910 return FALSE;
2911 }
2912
2913 if (acting_hplmn->mnc[0] EQ 0x0f OR
2914 acting_hplmn->mnc[1] EQ 0x0f )
2915 {
2916 mm_data->reg.acting_hplmn.v_plmn = V_PLMN_NOT_PRES;
2917 return FALSE;
2918 }
2919 else
2920 {
2921 /* 1. If True HPLMN has only 2 mnc digits ignore 3rd digit of mnc in AHPLMN
2922 even if exists
2923 2. If True HPLMN has mnc as 3 digits but AHPLMN has only 2 OR if any
2924 of the mnc digits are 0xff,invalidate the AHPLMN
2925 */
2926 if (mm_data->reg.length_mnc EQ 2 )
2927 {
2928 acting_hplmn->mnc[2] = 0x0F;
2929 }
2930 else if(acting_hplmn->mnc[2] EQ 0xFF)
2931 {
2932 mm_data->reg.acting_hplmn.v_plmn = V_PLMN_NOT_PRES;
2933 return FALSE;
2934 }
2935 }/* else acting_hplmn->mnc */
2936
2937 mm_data->reg.acting_hplmn.v_plmn = V_PLMN_PRES;
2938 return TRUE;
2939
2940 }/* end of valid_acting_hplmn */
2941
2942 /*
2943 +----------------------------------------------------------------------------+
2944 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2945 | STATE : code ROUTINE : reg_pack_plmn_fn..... |
2946 +----------------------------------------------------------------------------+
2947
2948 PURPOSE : This function packs a PLMN.
2949 */
2950
2951 LOCAL void reg_pack_plmn_fn (USHORT i,
2952 const T_RR_ABORT_IND *rr_abort_ind)
2953 {
2954 GET_INSTANCE_DATA;
2955 TRACE_FUNCTION ("reg_pack_plmn_fn()");
2956 reg_pack_plmn (mm_data->reg.plmn, mm_data->reg.plmn_cnt,
2957 &rr_abort_ind->plmn[i]);
2958 mm_data->reg.plmn_rx[mm_data->reg.plmn_cnt] = rr_abort_ind->rxlevel[i];
2959 mm_data->reg.plmn_lac[mm_data->reg.plmn_cnt] = rr_abort_ind->lac_list[i]; /* LOL 02.01.2003: added for EONS support */
2960 mm_data->reg.plmn_cnt++;
2961 }/*reg_pack_plmn_fn*/
2962
2963 /*
2964 +--------------------------------------------------------------------+
2965 | PROJECT : GSM-PS (6147) MODULE : MM_REG |
2966 | STATE : code ROUTINE : check_if_cingular_sim |
2967 +--------------------------------------------------------------------+
2968
2969 PURPOSE : This function checks whether inserted sim belong to
2970 Cingular Network.cingular_plmn_list contains the entire mcc and mnc of
2971 Cingular Network. Issue 31179
2972
2973 */
2974
2975 GLOBAL void check_if_cingular_sim(void)
2976 {
2977 GET_INSTANCE_DATA;
2978 USHORT plmn_index;
2979 T_plmn hplmn;
2980 reg_extract_hplmn (&hplmn);
2981 for(plmn_index = 0; plmn_index < MAX_CINGULAR_PLMN; plmn_index++)
2982 {
2983 if(reg_plmn_equal_sim (&hplmn, &cingular_plmn_list[plmn_index]))
2984 {
2985 mm_data->reg.is_cingular_sim = TRUE;
2986 break;
2987 }
2988 }
2989 }
2990