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

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