comparison src/g23m-aci/aci/phb_aci.c @ 1:fa8dc04885d8

src/g23m-*: import from Magnetite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:25:50 +0000
parents
children
comparison
equal deleted inserted replaced
0:4e78acac3d88 1:fa8dc04885d8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : MMI-Framework (8417)
4 | Modul : PHB
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 contains the functions to establish the phone book.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifdef TI_PS_FFS_PHB
22
23 #include "aci_all.h"
24 #include "aci_cmh.h"
25 #include "aci_mem.h"
26
27 #include "phb_aci.h"
28
29 #ifdef _SIMULATION_
30 /*
31 * Unfortunately we have a double definition of some preprocessor definitions
32 * within windows.h and within the protocol stack, so we undefine here.
33 */
34 #undef PARITY_NONE
35 #undef PARITY_ODD
36 #undef PARITY_EVEN
37 #undef DRV_OK
38 #include "ffs_pc_api.h"
39 #undef PARITY_NONE
40 #undef PARITY_ODD
41 #undef PARITY_EVEN
42 #undef DRV_OK
43 #else
44 #include "ffs/ffs.h"
45 #endif
46
47 #ifdef SIM_TOOLKIT
48 #include "psa.h"
49 #include "psa_sim.h"
50 #include "psa_cc.h"
51 #include "psa_sat.h"
52 #endif /* #ifdef SIM_TOOLKIT */
53
54 #include "cmh.h"
55 #include "cmh_phb.h"
56
57 #ifdef DTI
58 #include "dti_conn_mng.h"
59 #endif
60 #include "cmh_sim.h"
61
62
63 /*
64 * Constants and enumerations
65 */
66 /* #define NR_EF_ICI 20 LRN, LMN */
67 /* #define SIZE_EF_ICI (28+16) alpha id 16 bytes, 31.102 clause 4.2.33 */
68
69 #define NR_EF_OCI 10 /* Arbitrary, LDN */
70 #define SIZE_EF_OCI (27+16) /* alpha id 16 bytes, 31.102 clause 4.2.34 */
71
72 #define NR_EF_EXT5 10 /* Arbitrary */
73 #define SIZE_EF_EXT5 13 /* 31.102 clause 4.2.37 */
74
75 #define NR_EF_LRN 10 /* Arbitrary, LRN */
76 #define SIZE_EF_LRN SIZE_EF_OCI
77
78 #define NR_EF_LMN 10 /* Arbitrary, LMN */
79 #define SIZE_EF_LMN SIZE_EF_OCI
80
81 #define NR_EF_EXT_LRN 10 /* Arbitrary */
82 #define SIZE_EF_EXT_LRN SIZE_EF_EXT5
83
84 #define NR_EF_EXT_LMN 10 /* Arbitrary */
85 #define SIZE_EF_EXT_LMN SIZE_EF_EXT5
86
87 #define PHB_MAX_QUEUE 4 /* Queued LDN entries */
88 #define SIM_MAX_RECORD_SIZE 256 /* Maximum size of a SIM record */
89
90 #define PHB_STATE_NULL 0 /* NULL state before reading phonebook */
91 #define PHB_STATE_IDLE 1 /* IDLE state, phonebook has been read */
92 #define PHB_STATE_VERIFY 2 /* Verify SIM (Initialization, SAT) */
93 #define PHB_STATE_READ 3 /* Reading from SIM (Initialization, SAT) */
94 #define PHB_STATE_WRITE 4 /* Write/Delete single record to SIM */
95 #define PHB_STATE_DELETE_BOOK 5 /* Delete a whole SIM phonebook */
96
97 #define SET_PHB_STATE(n) pba_data.state = n;
98 #define GET_PHB_STATE() pba_data.state
99
100 typedef struct
101 {
102 USHORT index;
103 T_PHB_RECORD entry;
104 } T_PHB_QUEUE;
105
106 /*
107 * Type definitions
108 */
109 typedef struct
110 {
111 /* Fixed Dialling Numbers mode */
112 T_PHB_FDN_MODE fdn_mode;
113
114 /* Fixed Dialling Number class type */
115 T_ACI_CLASS fdn_classtype;
116
117 /* T_PHB_STATE of the phonebook */
118 T_PHB_STAT phb_stat;
119
120 /* Current state of the phonebook PHB_STATE_XXX */
121 UBYTE state;
122
123 /* SIM data */
124 UBYTE *data;
125
126 /* SIM service table */
127 UBYTE sim_service_table[MAX_SRV_TBL];
128
129 /* Database has to be recreated (IMSI changed or DB unclean) */
130 BOOL db_recreate;
131
132 /* Paused elementary file if reading extension record, otherwise 0 */
133 USHORT paused_ef;
134
135 /* Paused record number if reading extension record, otherwise 0 */
136 UBYTE paused_no;
137
138 /* Delete all: Book to delete, Read: Current book reading */
139 T_PHB_TYPE current_book;
140
141 /* Delete all: current record */
142 UBYTE del_record;
143
144 /* Book created */
145 BOOL book_created[MAX_PHONEBOOK];
146
147 /* Extension created */
148 BOOL ext_created[MAX_PHB_EXT];
149
150 /* We are reading the 1st ext record only to get the number of records */
151 BOOL ext_dummy_read;
152
153 /* Read flags for SIM phonebooks. Set to TRUE when reading has started */
154 BOOL book_read[MAX_PHONEBOOK];
155
156 /* Maximum number of phonebook records */
157 UBYTE phb_record_max[MAX_PHONEBOOK];
158 /* Maximum number of extension records */
159 UBYTE ext_record_max[MAX_PHB_EXT];
160
161 /* Record sizes of phonebook records */
162 UBYTE phb_record_len[MAX_PHONEBOOK];
163 /* Record sizes of extension records */
164 UBYTE ext_record_len[MAX_PHB_EXT];
165
166 /* Queued LDN entries during startup */
167 UBYTE c_queued;
168 T_PHB_QUEUE *queued[PHB_MAX_QUEUE];
169
170 /* Records to be synchronized to the SIM */
171 T_DB_CHANGED records_changed;
172
173 /* To keep track of read extension records */
174 BOOL *read_ext_record;
175
176 } T_PHB_ACI_DATA;
177
178 /* We pack all internal data into one data structure */
179 LOCAL T_PHB_ACI_DATA pba_data;
180
181
182 /*
183 * Prototypes for local functions
184 */
185 LOCAL UBYTE pb_get_max_num_len (T_PHB_TYPE type);
186 LOCAL BOOL pb_sim_service (UBYTE nr);
187 LOCAL BOOL pb_read_sim_record (USHORT data_id,
188 UBYTE rcd_num,
189 UBYTE len);
190 LOCAL BOOL pb_read_sim (USHORT data_id, UBYTE len, UBYTE max_length);
191 LOCAL void pb_read_next_sim_book (void);
192 LOCAL void pb_read_sim_record_cb (SHORT table_id);
193 LOCAL void pb_read_sim_cb (SHORT table_id);
194 LOCAL void pb_sat_update_reset (USHORT ef);
195 LOCAL T_PHB_RETURN pb_sync_next_sim_record (BOOL first);
196 LOCAL T_PHB_RETURN pb_write_sim_record (USHORT ef,
197 UBYTE phy_recno,
198 UBYTE entry_size,
199 const UBYTE *buffer);
200 LOCAL void pb_write_sim_record_cb (SHORT table_id);
201 T_EXT_TYPE pb_get_ext_type_from_ef (USHORT ef);
202 LOCAL void pb_status_ind (T_PHB_STAT phb_stat,
203 SHORT cmeError);
204 LOCAL T_PHB_RETURN pb_write_queue (const T_PHB_RECORD *entry);
205 LOCAL void pb_clear_queue (void);
206 LOCAL T_PHB_RETURN pb_read_queue (void);
207
208 /*
209 * Functions - Interface functions to external modules
210 */
211
212
213 /*
214 +----------------------------------------------------------------------------+
215 | PROJECT : GSM-PS (6147) MODULE : PHB |
216 | STATE : code ROUTINE : pb_init |
217 +----------------------------------------------------------------------------+
218
219 PURPOSE : Power-on initialization of the phonebook module. This function
220 is called at a point in time by pei_init() when it cannot be
221 expected that the protocol stack has been booted up completely,
222 so it is undesirable to do anything here which might rely on
223 a module still not started up like the PCM or the FFS.
224
225 */
226 GLOBAL void pb_init (void)
227 {
228 TRACE_FUNCTION ("pb_init()");
229
230 memset (&pba_data, 0, sizeof (T_PHB_ACI_DATA));
231
232 pba_data.fdn_mode = NO_OPERATION;
233 pba_data.fdn_classtype = CLASS_VceDatFaxSms;
234
235 pb_sim_init();
236
237 #ifdef SIM_TOOLKIT
238 simShrdPrm.fuRef= - 1;
239 psaSAT_FURegister (pb_update);
240 #endif /* #ifdef SIM_TOOLKIT */
241
242 SET_PHB_STATE (PHB_STATE_NULL);
243 }
244
245
246 /*
247 +----------------------------------------------------------------------------+
248 | PROJECT : GSM-PS (6147) MODULE : PHB |
249 | STATE : code ROUTINE : pb_exit_phb |
250 +----------------------------------------------------------------------------+
251
252 PURPOSE : This function synchronizes, if necessary, all unwritten data,
253 shuts down the SIM phonebook layer and deallocates all
254 resources. The SIM itself is not deactivated here.
255
256
257 */
258 LOCAL void pb_exit_phb (void)
259 {
260 TRACE_FUNCTION ("pb_exit_phb()");
261
262 /*
263 * Flush everything which has not yet been written.
264 * Note: It's a good idea if everything is written immediately
265 * so that we don't need to flush anything here. Competitor phones
266 * do the job in this way, this has the advantage that even after
267 * a phone crash immediately after dialling a number or missing
268 * a call nothing is lost.
269 */
270 (void)pb_sim_flush_data ();
271
272 /* Shutdown the lower layers */
273 pb_sim_exit ();
274
275 /*
276 * Free all allocated resources
277 */
278 if (pba_data.data NEQ NULL)
279 {
280 ACI_MFREE (pba_data.data);
281 pba_data.data = NULL;
282 }
283
284 if (pba_data.read_ext_record NEQ NULL)
285 {
286 ACI_MFREE (pba_data.read_ext_record);
287 pba_data.read_ext_record = NULL;
288 }
289
290
291 pb_clear_queue ();
292
293 /*
294 * Set phonebook to no operation
295 */
296 pba_data.fdn_mode = NO_OPERATION;
297 pba_data.phb_stat = PHB_UNKNOWN;
298 SET_PHB_STATE (PHB_STATE_NULL);
299 }
300
301
302 /*
303 +----------------------------------------------------------------------------+
304 | PROJECT : GSM-PS (6147) MODULE : PHB |
305 | STATE : code ROUTINE : pb_exit |
306 +----------------------------------------------------------------------------+
307
308 PURPOSE : Shutdown phonebook and the SIM itself also.
309
310 */
311 GLOBAL void pb_exit (void)
312 {
313 TRACE_FUNCTION ("pb_exit()");
314
315 /* Shutdown SIM phonebook */
316 pb_exit_phb ();
317
318 /* Shutdown the SIM itself */
319 simShrdPrm.synCs = SYNC_DEACTIVATE;
320 psaSIM_SyncSIM();
321 }
322
323
324 /*
325 +----------------------------------------------------------------------------+
326 | PROJECT : GSM-PS (6147) MODULE : PHB |
327 | STATE : code ROUTINE : pb_reset |
328 +----------------------------------------------------------------------------+
329
330 PURPOSE : Resets the phonebook, basically pb_exit() / pb_init().
331
332 */
333 GLOBAL void pb_reset (void)
334 {
335 TRACE_FUNCTION ("pb_reset()");
336
337 if (GET_PHB_STATE() EQ PHB_STATE_NULL)
338 return;
339
340 pb_exit_phb();
341 pb_init();
342 }
343
344 /*
345 +----------------------------------------------------------------------------+
346 | PROJECT : GSM-PS (6147) MODULE : PHB |
347 | STATE : code ROUTINE : pb_set_sim_ecc |
348 +----------------------------------------------------------------------------+
349
350 PURPOSE : This function set's the emergency call numbers.
351 This can only happen at startup time when the SIM when
352 a SIM_ACTIVATE_CNF / SIM_ACTIVATE_IND is received.
353 At this point in time the entering of PIN may be outstanding,
354 the only information we may have gotten are the emergency call
355 numbers.
356
357 */
358 GLOBAL void pb_set_sim_ecc (USHORT cause,
359 UBYTE ecc_len,
360 const UBYTE *sim_ecc)
361 {
362 TRACE_FUNCTION ("pb_set_sim_ecc()");
363
364 if (pba_data.fdn_mode NEQ NO_OPERATION)
365 {
366 /*
367 * Setting of the emergency call numbers after having gotten the
368 * IMSI of the SIM is ignored.
369 */
370 return;
371 }
372
373 if ((cause EQ SIM_CAUSE_OTHER_ERROR) OR
374 (cause EQ SIM_CAUSE_CARD_REMOVED) OR
375 (cause >= SIM_CAUSE_PARAM_WRONG AND cause <= SIM_CAUSE_DRV_TEMPFAIL))
376 {
377 /*
378 * Some error from the SIM. Indicate a fallback to the PCM/FFS.
379 */
380 (void)pb_sim_set_ecc (0, NULL);
381 }
382 else
383 {
384 (void)pb_sim_set_ecc (ecc_len, sim_ecc);
385 }
386
387
388
389 }
390
391
392 /*
393 +----------------------------------------------------------------------------+
394 | PROJECT : GSM-PS (6147) MODULE : PHB |
395 | STATE : code ROUTINE : pb_inserted_sim |
396 +----------------------------------------------------------------------------+
397
398 PURPOSE : This function is called when the PIN has been entered and we have
399 the IMSI and full access on the SIM phonebook. Reading/Verifying
400 of phonebook data is not started at this point except for the
401 ECC phonebook.
402
403 */
404 GLOBAL void pb_inserted_sim (UBYTE c_sim_serv,
405 UBYTE *sim_serv,
406 const T_imsi_field *imsi_field,
407 UBYTE adn_bdn_fdn_func,
408 UBYTE phase) /* For further study */
409 {
410 T_FFS_SIZE ffs_size; /* FFS result code */
411 T_ACI_CLASS classFDN; /* FDN class */
412 UBYTE ub_class = (UBYTE)CLASS_None; /* T_ACI_CLASS */
413
414 TRACE_FUNCTION ("pb_inserted_sim()");
415
416 /* Store SIM service table */
417 if (c_sim_serv > MAX_SRV_TBL)
418 c_sim_serv = MAX_SRV_TBL; /* Garbage protection */
419 memcpy (pba_data.sim_service_table, sim_serv, c_sim_serv);
420
421 /*
422 * Open SIM phonebook. Remember whether the database has to be recreated
423 * for some reason (SIM changed, database unclean).
424 */
425 if (pb_sim_open (imsi_field, &pba_data.db_recreate) NEQ PHB_OK)
426 {
427 /* We're here in really big trouble and can do nothing about it */
428 TRACE_ERROR ("Fatal: pb_sim_open() NEQ PHB_OK");
429 }
430
431 /*
432 * Update ECC phonebook
433 */
434 pba_data.book_read[ECC] = TRUE;
435 if (!pb_read_sim (SIM_ECC, NOT_PRESENT_8BIT, (UBYTE)SIM_MAX_RECORD_SIZE))
436 {
437 /* Unexpected problem. Live with previously read values */
438 TRACE_ERROR ("Unexpected: No free SIM slot");
439 }
440
441 switch (adn_bdn_fdn_func)
442 {
443 case SIM_ADN_ENABLED:
444 case SIM_ADN_BDN_ENABLED:
445 pba_data.fdn_mode = FDN_DISABLE;
446 break;
447
448 case SIM_FDN_ENABLED:
449 case SIM_FDN_BDN_ENABLED:
450 pba_data.fdn_mode = FDN_ENABLE;
451
452 /* read last fdn_classtype from FFS */
453 ffs_size = ffs_file_read ("/mmi/fdnClassType", &ub_class, sizeof(ub_class));
454
455 if (ffs_size EQ sizeof(ub_class)) /* successful read */
456 {
457 classFDN = (T_ACI_CLASS)ub_class;
458
459 /* only these two classes are currently supported */
460 if (classFDN EQ CLASS_VceDatFax OR
461 classFDN EQ CLASS_VceDatFaxSms)
462 {
463 pba_data.fdn_classtype = classFDN;
464 }
465 }
466 break;
467
468 default: /* SIM_NO_OPERATION or trash */
469 pba_data.fdn_mode = NO_OPERATION;
470 break;
471 }
472 }
473
474
475 /*
476 +----------------------------------------------------------------------------+
477 | PROJECT : GSM-PS (6147) MODULE : PHB |
478 | STATE : code ROUTINE : pb_start_build |
479 +----------------------------------------------------------------------------+
480
481 PURPOSE : This function is called when the flash phonebook has to be
482 read/verified from/against the phonebook stored on the SIM card.
483 This is triggered by the reception of the
484 MNSMS_REPORT_IND (SMS_STATE_READY) primitive.
485
486 */
487 GLOBAL void pb_start_build (BOOL unchanged)
488 {
489 TRACE_FUNCTION ("pb_start_build()");
490
491 if (pba_data.db_recreate)
492 {
493 /*
494 * Indicate a busy phonebook. We have to re-read all from scratch
495 */
496 pb_status_ind (PHB_BUSY, CME_ERR_NotPresent);
497 SET_PHB_STATE (PHB_STATE_READ);
498 }
499 else
500 {
501 /*
502 * SIM (IMSI) not changed and database clean,
503 * allow reading from the SIM phonebook by the MMI.
504 */
505 pb_status_ind (PHB_READY, CME_ERR_NotPresent);
506 SET_PHB_STATE (PHB_STATE_VERIFY);
507 }
508
509 pba_data.ext_dummy_read = FALSE;
510
511 #ifdef _SIMULATION_
512 TRACE_EVENT_P1 ("SRV_ADN: %s", pb_sim_service (SRV_ADN) ? "YES" : "NO");
513 TRACE_EVENT_P1 ("SRV_FDN: %s", pb_sim_service (SRV_FDN) ? "YES" : "NO");
514 TRACE_EVENT_P1 ("SRV_CCP: %s", pb_sim_service (SRV_CCP) ? "YES" : "NO");
515 TRACE_EVENT_P1 ("SRV_MSISDN: %s",pb_sim_service (SRV_MSISDN) ? "YES" : "NO");
516 TRACE_EVENT_P1 ("SRV_EXT1: %s", pb_sim_service (SRV_EXT1) ? "YES" : "NO");
517 TRACE_EVENT_P1 ("SRV_EXT2: %s", pb_sim_service (SRV_EXT2) ? "YES" : "NO");
518 TRACE_EVENT_P1 ("SRV_LDN: %s", pb_sim_service (SRV_LDN) ? "YES" : "NO");
519 TRACE_EVENT_P1 ("SRV_SDN: %s", pb_sim_service (SRV_SDN) ? "YES" : "NO");
520 TRACE_EVENT_P1 ("SRV_EXT3: %s", pb_sim_service (SRV_EXT3) ? "YES" : "NO");
521 TRACE_EVENT_P1 ("SRV_BDN: %s", pb_sim_service (SRV_BDN) ? "YES" : "NO");
522 TRACE_EVENT_P1 ("SRV_EXT4: %s", pb_sim_service (SRV_EXT4) ? "YES" : "NO");
523 #endif
524
525 pb_read_next_sim_book();
526 }
527
528
529 /*
530 +----------------------------------------------------------------------------+
531 | PROJECT : GSM-PS (6147) MODULE : PHB |
532 | STATE : code ROUTINE : pb_update |
533 +----------------------------------------------------------------------------+
534
535 PURPOSE : This function is called when the SIM wants to inform the
536 phonebook that some elementary files have been changed.
537 Returns TRUE if no files aere changed affecting the phonebook,
538 otherwise FALSE.
539
540 */
541 GLOBAL BOOL pb_update (int ref,
542 T_SIM_FILE_UPDATE_IND *fu)
543 {
544 unsigned i; /* Index variable */
545 T_PHB_TYPE phb_type; /* Phonebook type */
546 T_EXT_TYPE ext_type; /* Extension type */
547 USHORT ef; /* Elementary file number */
548
549 TRACE_FUNCTION ("pb_update()");
550
551 simShrdPrm.fuRef = -1; /* Assume phonebook is not affected */
552
553 for (i = 0; i < fu->val_nr; i++)
554 {
555 ef = fu->file_info[i].datafield;
556
557 if (ef EQ SIM_SST)
558 {
559 /*
560 * When SIM service table is changed, then all SIM phonebooks
561 * will be updated.
562 */
563
564 /* Mark all phonebooks as unread */
565 pb_sat_update_reset (SIM_ECC);
566 pb_sat_update_reset (SIM_ADN);
567 pb_sat_update_reset (SIM_FDN);
568 pb_sat_update_reset (SIM_BDN);
569 #ifdef SIM_LND_SUPPORT
570 pb_sat_update_reset (SIM_LND);
571 #endif
572 pb_sat_update_reset (SIM_MSISDN);
573 pb_sat_update_reset (SIM_SDN);
574
575 /* Mark all extensions as unread */
576 pb_sat_update_reset (EXT1);
577 pb_sat_update_reset (EXT2);
578 pb_sat_update_reset (EXT3);
579 pb_sat_update_reset (EXT4);
580
581 if (!pb_read_sim (SIM_SST, NOT_PRESENT_8BIT, (UBYTE)SIM_MAX_RECORD_SIZE))
582 {
583 /*
584 * We could not get an empty slot and are in trouble now as there is
585 * no good error handling possible here. On the other hand, it is
586 * not expected ever that an error occurs here.
587 */
588 TRACE_ERROR ("Internal problem getting a SIM slot");
589 return TRUE; /* No update in progress */
590 }
591
592 simShrdPrm.fuRef = ref; /* Something to do */
593
594 SET_PHB_STATE (PHB_STATE_READ);
595 return FALSE; /* Update in progress */
596 }
597 }
598
599 /*
600 * At least the SIM service table has not been changed, check now for
601 * single phonebooks and extension records.
602 */
603
604 for (i = 0; i < fu->val_nr; i++)
605 {
606 ef = fu->file_info[i].datafield;
607 phb_type = pb_get_phb_type_from_ef (ef);
608 ext_type = pb_get_ext_type_from_ef (ef);
609
610 if (phb_type NEQ INVALID_PHB)
611 {
612 /* Phonebook affected by change */
613 simShrdPrm.fuRef = ref;
614
615 /* Reset respective field */
616 pb_sat_update_reset (ef);
617
618 switch (phb_type)
619 {
620 case ADN:
621 pb_sat_update_reset (SIM_FDN);
622 break;
623
624 case FDN:
625 pb_sat_update_reset (SIM_ADN);
626 break;
627
628 default:
629 break;
630 }
631 }
632 else if (ext_type NEQ INVALID_EXT)
633 {
634 /* Phonebook affected by change */
635 simShrdPrm.fuRef = ref;
636
637 /* Reset respective field */
638 pb_sat_update_reset (ef);
639
640 /* Mark also the appropriate book itself as unread */
641 switch (ext_type)
642 {
643 case EXT1:
644 pb_sat_update_reset (SIM_ADN);
645 pb_sat_update_reset (SIM_MSISDN);
646 #ifdef SIM_LND_SUPPORT
647 pb_sat_update_reset (SIM_LND);
648 #endif
649 break;
650
651 case EXT2:
652 pb_sat_update_reset (SIM_FDN);
653 break;
654
655 case EXT3:
656 pb_sat_update_reset (SIM_SDN);
657 break;
658
659 case EXT4:
660 pb_sat_update_reset (SIM_EXT4);
661 break;
662
663 default:
664 TRACE_ERROR ("Unexpected default"); /* Everything caught */
665 break;
666 }
667 }
668 }
669
670 if (simShrdPrm.fuRef NEQ -1)
671 {
672 pb_start_build (FALSE);
673 return FALSE; /* FALSE means update in progress */
674 }
675
676 return TRUE; /* TRUE means nothing to do */
677 }
678
679
680 /*
681 +----------------------------------------------------------------------------+
682 | PROJECT : GSM-PS (6147) MODULE : PHB |
683 | STATE : code ROUTINE : pb_flush_data |
684 +----------------------------------------------------------------------------+
685
686 PURPOSE : This function is called when someone wants to flush some pending
687 data to persistent memory. Probably a bad concept, it's always
688 better to flush always internally if some operation is finished
689 and to synchronize also to the SIM immediately. This has the
690 advantage that even after a crash nothing is lost.
691
692 */
693 T_PHB_RETURN pb_flush_data (void)
694 {
695 TRACE_FUNCTION ("pb_flush_data()");
696
697 /* This function is empty, and this should remain this way if possible */
698 return PHB_OK;
699 }
700
701
702 /*
703 +----------------------------------------------------------------------------+
704 | PROJECT : GSM-PS (6147) MODULE : PHB |
705 | STATE : code ROUTINE : pb_add_record |
706 +----------------------------------------------------------------------------+
707
708 PURPOSE : This function adds or replaces a phonebook entry.
709
710 */
711 GLOBAL T_PHB_RETURN pb_add_record (T_PHB_TYPE type,
712 USHORT phy_recno,
713 const T_PHB_RECORD *entry)
714 {
715 T_PHB_RETURN phb_result;
716 T_DB_CHANGED dummy_changed;
717
718 TRACE_FUNCTION ("pb_add_record()");
719
720 #ifdef _SIMULATION_
721 {
722 char name [PHB_MAX_TAG_LEN + 1];
723 char number[MAX_PHB_NUM_LEN];
724
725 memset (name, 0, PHB_MAX_TAG_LEN + 1);
726 memcpy (name, entry->tag, entry->tag_len);
727 cmhPHB_getAdrStr (number,
728 MAX_PHB_NUM_LEN - 1,
729 entry->number,
730 entry->len);
731 if ((UBYTE)(name[0]) >= 0x80)
732 strcpy (name, "<Some UCS2 coding>");
733
734 TRACE_EVENT_P4 ("Adding number %s with name '%s' to book %d record %d",
735 number, name, type, phy_recno);
736 }
737 #endif
738
739 /* Fix phy_recno parameter for circular books */
740 if ((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN))
741 {
742 if (phy_recno EQ 0)
743 phy_recno = 1;
744 }
745
746 switch (GET_PHB_STATE())
747 {
748 case PHB_STATE_IDLE:
749
750 /* Add the data in the database */
751 phb_result = pb_sim_add_record (type,
752 phy_recno,
753 entry,
754 &pba_data.records_changed);
755 if (phb_result NEQ PHB_OK)
756 return phb_result; /* Record could not be added to the database */
757
758 if (pba_data.records_changed.entries NEQ 0)
759 {
760 SET_PHB_STATE (PHB_STATE_WRITE);
761 }
762
763 /* Start synchronizing record(s) to the SIM */
764 return pb_sync_next_sim_record (TRUE);
765
766 case PHB_STATE_VERIFY:
767 case PHB_STATE_READ:
768 if ((type EQ LRN) OR (type EQ LMN))
769 {
770 /*
771 * In Release 1998- there is no counterpart on the SIM here,
772 * we can write immediately as we don't have to synch to the SIM.
773 */
774 return (pb_sim_add_record (type,
775 phy_recno,
776 entry,
777 &dummy_changed));
778 }
779 else if (type EQ LDN)
780 {
781 /* We have to queue the LDN entry and will write later */
782 return pb_write_queue (entry);
783 }
784 return PHB_FAIL;
785
786 default:
787 return PHB_FAIL;
788 }
789 }
790
791
792 /*
793 +----------------------------------------------------------------------------+
794 | PROJECT : GSM-PS (6147) MODULE : PHB |
795 | STATE : code ROUTINE : pb_del_record |
796 +----------------------------------------------------------------------------+
797
798 PURPOSE : This function deletes a phonebook entry.
799
800 */
801 GLOBAL T_PHB_RETURN pb_del_record (T_PHB_TYPE type,
802 USHORT phy_recno)
803 {
804 T_PHB_RETURN phb_result;
805
806 TRACE_FUNCTION ("pb_del_record()");
807
808 if (GET_PHB_STATE() NEQ PHB_STATE_IDLE)
809 return PHB_FAIL;
810
811 /* Delete the data in the database */
812 phb_result = pb_sim_del_record (type,
813 phy_recno,
814 &pba_data.records_changed);
815 if (phb_result NEQ PHB_OK)
816 return phb_result; /* Record could not be deleted from the database */
817
818 if (pba_data.records_changed.entries NEQ 0)
819 {
820 SET_PHB_STATE (PHB_STATE_WRITE);
821 }
822
823 /* Start synchronizing record(s) to the SIM */
824 return pb_sync_next_sim_record (TRUE);
825 }
826
827
828 /*
829 +----------------------------------------------------------------------------+
830 | PROJECT : GSM-PS (6147) MODULE : PHB |
831 | STATE : code ROUTINE : pb_check_fdn |
832 +----------------------------------------------------------------------------+
833
834 PURPOSE : This function checks whether a phone number is in FDN phonebook.
835
836 */
837 #define RETURN(x) { retVal = x; goto cleanup_exit; }
838 /*lint -e{801} Use of goto*/
839 GLOBAL T_PHB_RETURN pb_check_fdn (UBYTE toa,
840 const UBYTE *number)
841 {
842 T_PHB_RETURN retVal;
843 T_PHB_RECORD *phb_record;
844 CHAR cur_number[MAX_PHB_NUM_LEN];
845 UBYTE cur_num_len;
846 USHORT phy_recno;
847 SHORT max_rcd;
848 SHORT dummy_used_rcd;
849 UBYTE dummy_tag_len;
850 SHORT dummy_max_ext, dummy_used_ext;
851
852 ACI_MALLOC (phb_record, sizeof (T_PHB_RECORD));
853
854 TRACE_FUNCTION ("pb_check_fdn()");
855
856 retVal = pb_sim_read_sizes (FDN,
857 &max_rcd,
858 &dummy_used_rcd,
859 &dummy_tag_len,
860 &dummy_max_ext,
861 &dummy_used_ext);
862 if (retVal NEQ PHB_OK)
863 {
864 TRACE_ERROR ("Unexpected return from pb_sim_read_sizes()");
865 RETURN (retVal)
866 }
867
868 /*
869 * Do a linear search through all the records applying the number comparision
870 * rules which make us pass 51.010 test case 27.18.1.1.4.2.
871 * Those rules are different from those which are to be applied if a matching
872 * record has to be found for an incoming call, therefore we cannot use
873 * pb_sim_search_number() here.
874 * As normally FDN phonebooks have not more than 10 entries (max_rcd) a
875 * simple linear search will fulfill here all timing requirements.
876 */
877
878 for (phy_recno = 1; phy_recno <= max_rcd; phy_recno++)
879 {
880 retVal = pb_sim_read_record (FDN, phy_recno, phb_record);
881 if (retVal EQ PHB_OK)
882 {
883 cmhPHB_getAdrStr (cur_number,
884 MAX_PHB_NUM_LEN - 1,
885 phb_record->number,
886 phb_record->len);
887 cur_num_len = strlen (cur_number);
888
889 /* Compare number strings considering Wild card */
890 if (pb_sim_cmpWild((char*)cur_number, (char *) number, cur_num_len) EQ 0)
891 {
892 /* Number matches. ACI-SPR-11927: check type of address */
893 if ((toa EQ 0) OR
894 (toa EQ phb_record->ton_npi) OR
895 (phb_record->ton_npi EQ 0xFF))
896 {
897 RETURN (PHB_OK)
898 }
899
900 }
901 }
902 }
903 RETURN (PHB_FAIL) /* Not found */
904
905 cleanup_exit:
906 ACI_MFREE (phb_record);
907 return retVal;
908 }
909
910
911 /*
912 +----------------------------------------------------------------------------+
913 | PROJECT : GSM-PS (6147) MODULE : PHB |
914 | STATE : code ROUTINE : pb_switch_adn_fdn |
915 +----------------------------------------------------------------------------+
916
917 PURPOSE : This function switches FDN and ADN phonebooks (sAT_PlusCLCK()).
918
919 */
920 GLOBAL T_PHB_RETURN pb_switch_adn_fdn (T_PHB_FDN_MODE mode,
921 T_ACI_CLASS classFDN)
922 {
923 TRACE_FUNCTION ("pb_switch_adn_fdn()");
924
925 if (GET_PHB_STATE() NEQ PHB_STATE_IDLE)
926 return PHB_FAIL;
927
928 /* Check parameters */
929 switch (mode)
930 {
931 case FDN_DISABLE:
932 case FDN_ENABLE:
933 break;
934
935 default:
936 return PHB_FAIL;
937 }
938
939 if (classFDN NEQ pba_data.fdn_classtype)
940 {
941 pba_data.fdn_classtype = classFDN;
942
943 #ifndef _SIMULATION_
944 if (ffs_fwrite("/mmi/fdnClassType", &classFDN, sizeof(UBYTE)) < 1)
945 {
946 TRACE_ERROR ("sAT_PlusCLCK: failed to write /mmi/fdnClassType");
947 }
948 #endif /* #ifndef _SIMULATION_ */
949 }
950
951 #if 1
952
953 pba_data.fdn_mode = mode;
954
955 /* Remove ADN from database */
956 (void)pb_sim_remove_ef (SIM_ADN);
957 pba_data.book_created[ADN] = FALSE;
958 pba_data.book_read[ADN] = FALSE;
959
960 /* Remove MSISDN database */
961 (void)pb_sim_remove_ef (SIM_MSISDN);
962 pba_data.book_created[UPN] = FALSE;
963 pba_data.book_read[UPN] = FALSE;
964
965 #ifdef SIM_LND_SUPPORT
966 /* Remove LND from database */
967 (void)pb_sim_remove_ef (SIM_LND);
968 pba_data.book_created[LDN] = FALSE;
969 pba_data.book_read[LDN] = FALSE;
970 #endif
971
972 /* Remove EXT1 from database */
973 (void)pb_sim_remove_ef (SIM_EXT1);
974 pba_data.ext_created[EXT1] = FALSE;
975
976 /* Remove FDN from database */
977 (void)pb_sim_remove_ef (SIM_FDN);
978 pba_data.book_created[FDN] = FALSE;
979 pba_data.book_read[FDN] = FALSE;
980
981 /* Remove EXT2 from database */
982 (void)pb_sim_remove_ef (SIM_EXT2);
983 pba_data.ext_created[EXT2] = FALSE;
984
985 /* Force cmhPHB_StatIndication (PHB_BUSY, CME_ERR_NotPresent) */
986 pba_data.db_recreate = TRUE;
987
988 SET_PHB_STATE (PHB_STATE_READ);
989
990 /* Start reading changed books */
991 pb_start_build (FALSE);
992 #else
993 // This optimization does not comply with current test cases,
994 // not understood perfectly whether the test cases can be
995 // changed, so kept old behaviour.
996 if (pba_data.fdn_mode NEQ mode)
997 {
998 pba_data.fdn_mode = mode;
999
1000 if (mode EQ FDN_ENABLE)
1001 {
1002 /* Remove ADN from database */
1003 (void)pb_sim_remove_ef (SIM_ADN);
1004 pba_data.book_created[ADN] = FALSE;
1005 pba_data.book_read[ADN] = FALSE;
1006 }
1007 else
1008 {
1009 /* Remove FDN from database */
1010 (void)pb_sim_remove_ef (SIM_FDN);
1011 pba_data.book_created[FDN] = FALSE;
1012 pba_data.book_read[FDN] = FALSE;
1013
1014 /* Remove EXT2 from database */
1015 (void)pb_sim_remove_ef (SIM_EXT2);
1016 pba_data.ext_created[EXT2] = FALSE;
1017 }
1018
1019 /* Force cmhPHB_StatIndication (PHB_BUSY, CME_ERR_NotPresent) */
1020 pba_data.db_recreate = TRUE;
1021
1022 SET_PHB_STATE (PHB_STATE_READ);
1023
1024 /* Start reading changed books */
1025 pb_start_build (FALSE);
1026 }
1027 #endif
1028 return PHB_OK;
1029 }
1030
1031
1032 /*
1033 +----------------------------------------------------------------------------+
1034 | PROJECT : GSM-PS (6147) MODULE : PHB |
1035 | STATE : code ROUTINE : pb_del_book |
1036 +----------------------------------------------------------------------------+
1037
1038 PURPOSE : This function deletes a whole SIM phonebook
1039
1040 */
1041 GLOBAL T_PHB_RETURN pb_del_book (T_PHB_TYPE book)
1042 {
1043 T_PHB_RETURN phb_result;
1044 UBYTE max_record;
1045
1046 TRACE_FUNCTION ("pb_del_book()");
1047
1048 if (GET_PHB_STATE() NEQ PHB_STATE_IDLE)
1049 return PHB_FAIL;
1050
1051 /* Remember book to delete, initialize record to delete */
1052 pba_data.current_book = book;
1053 pba_data.del_record = 1;
1054 max_record = pba_data.phb_record_max[pba_data.current_book];
1055
1056 do
1057 {
1058 /* Delete the record in the database */
1059 phb_result = pb_sim_del_record (pba_data.current_book,
1060 pba_data.del_record,
1061 &pba_data.records_changed);
1062
1063 if ((phb_result NEQ PHB_OK) AND (phb_result NEQ PHB_EMPTY_RECORD))
1064 return phb_result;
1065
1066 pba_data.del_record++;
1067 }
1068 while ((pba_data.del_record <= max_record) AND
1069 (pba_data.records_changed.entries EQ 0));
1070
1071 if (pba_data.records_changed.entries NEQ 0)
1072 {
1073 /* Synchronize to SIM */
1074 SET_PHB_STATE (PHB_STATE_DELETE_BOOK);
1075
1076 /* Start synchronizing record(s) to the SIM */
1077 return pb_sync_next_sim_record (TRUE);
1078 }
1079
1080 return PHB_OK;
1081 }
1082
1083
1084 /*
1085 +----------------------------------------------------------------------------+
1086 | PROJECT : GSM-PS (6147) MODULE : PHB |
1087 | STATE : code ROUTINE : pb_get_fdn_classtype |
1088 +----------------------------------------------------------------------------+
1089
1090 PURPOSE : This function gets the FDN class type
1091
1092 */
1093 GLOBAL T_ACI_CLASS pb_get_fdn_classtype (void)
1094 {
1095 TRACE_FUNCTION ("pb_get_fdn_classtype()");
1096
1097 return pba_data.fdn_classtype;
1098
1099 }
1100
1101
1102 /*
1103 +----------------------------------------------------------------------------+
1104 | PROJECT : GSM-PS (6147) MODULE : PHB |
1105 | STATE : code ROUTINE : pb_get_fdn_mode |
1106 +----------------------------------------------------------------------------+
1107
1108 PURPOSE : This function gets the FDN mode
1109
1110 */
1111 GLOBAL T_PHB_FDN_MODE pb_get_fdn_mode (void)
1112 {
1113 TRACE_FUNCTION ("pb_get_fdn_mode()");
1114
1115 return pba_data.fdn_mode;
1116
1117 }
1118
1119
1120 /*
1121 * Wrapper functions. Wrapper functions don't define own functionality
1122 * except of routing to a different block which is the SIM part of
1123 * the phonebook here. For a description of these functions have
1124 * a look into the SIM part of the phonebook.
1125 */
1126
1127 GLOBAL T_PHB_RETURN pb_read_record (T_PHB_TYPE type,
1128 SHORT phy_recno,
1129 T_PHB_RECORD *entry)
1130 {
1131 T_PHB_RETURN phb_result;
1132
1133 TRACE_FUNCTION ("pb_read_record()");
1134
1135 if (phy_recno EQ 0)
1136 return PHB_FAIL;
1137
1138 switch (GET_PHB_STATE())
1139 {
1140 case PHB_STATE_VERIFY:
1141 /*
1142 * For LDN records, first have a look into the queue
1143 */
1144 if ((type EQ LDN) AND (phy_recno - 1 < pba_data.c_queued))
1145 {
1146 /* Entry freshly dialled and still in the queue */
1147 *entry = pba_data.queued[phy_recno - 1]->entry;
1148 return PHB_OK;
1149 }
1150 phb_result = pb_sim_read_record (type,
1151 (USHORT)(phy_recno - pba_data.c_queued),
1152 entry);
1153 TRACE_EVENT_P3 ("type = %d, phy_recno = %d, phb_result = %d",
1154 type, phy_recno, phb_result);
1155 return phb_result;
1156
1157 case PHB_STATE_READ:
1158 /*
1159 * For LDN records, first have a look into the queue
1160 */
1161 if ((type EQ LDN) AND (phy_recno - 1 < pba_data.c_queued))
1162 {
1163 /* Entry freshly dialled and still in the queue */
1164 *entry = pba_data.queued[phy_recno - 1]->entry;
1165 return PHB_OK;
1166 }
1167 return PHB_FAIL; /* We already know the SIM was changed */
1168
1169 case PHB_STATE_IDLE:
1170 phb_result = pb_sim_read_record (type, phy_recno, entry);
1171 TRACE_EVENT_P3 ("type = %d, phy_recno = %d, phb_result = %d",
1172 type, phy_recno, phb_result);
1173 return phb_result;
1174
1175 default:
1176 return PHB_FAIL;
1177 }
1178 }
1179
1180
1181 GLOBAL T_PHB_RETURN pb_read_alpha_record (T_PHB_TYPE type,
1182 SHORT order_num,
1183 T_PHB_RECORD *entry)
1184 {
1185 TRACE_FUNCTION ("pb_read_alpha_record()");
1186
1187 switch (GET_PHB_STATE())
1188 {
1189 case PHB_STATE_IDLE:
1190 case PHB_STATE_VERIFY:
1191 /* Implements Measure #30 */
1192 return pb_sim_read_alpha_num_record (type, order_num, entry, NAME_IDX);
1193 default:
1194 return PHB_FAIL;
1195 }
1196 }
1197
1198
1199 GLOBAL T_PHB_RETURN pb_read_number_record (T_PHB_TYPE type,
1200 SHORT order_num,
1201 T_PHB_RECORD *entry)
1202 {
1203 TRACE_FUNCTION ("pb_read_number_record()");
1204
1205 switch (GET_PHB_STATE())
1206 {
1207 case PHB_STATE_IDLE:
1208 case PHB_STATE_VERIFY:
1209 /* Implements Measure #30 */
1210 return pb_sim_read_alpha_num_record (type, order_num, entry, NUMBER_IDX);
1211 default:
1212 return PHB_FAIL;
1213 }
1214 }
1215
1216
1217 GLOBAL T_PHB_RETURN pb_search_name (T_PHB_TYPE type,
1218 T_PHB_MATCH match,
1219 const T_ACI_PB_TEXT *search_tag,
1220 SHORT *order_num)
1221 {
1222 T_PHB_RETURN phb_result;
1223
1224 TRACE_FUNCTION ("pb_search_name()");
1225
1226 switch (GET_PHB_STATE())
1227 {
1228 case PHB_STATE_IDLE:
1229 case PHB_STATE_VERIFY:
1230 TRACE_EVENT_P1 ("order_num = %d", *order_num);
1231 phb_result = pb_sim_search_name (type, match, search_tag, order_num);
1232 if (phb_result EQ PHB_OK) /* #HM# Remove before production */
1233 {
1234 TRACE_EVENT ("Entry found");
1235 }
1236 else
1237 {
1238 TRACE_EVENT ("Entry not found");
1239 }
1240 return phb_result;
1241
1242 default:
1243 return PHB_FAIL;
1244 }
1245 }
1246
1247
1248 GLOBAL T_PHB_RETURN pb_search_number (T_PHB_TYPE type,
1249 const UBYTE *number,
1250 SHORT *order_num)
1251 {
1252 TRACE_FUNCTION ("pb_search_number()");
1253
1254 if(type EQ ECC)
1255 {
1256 return pb_sim_search_number (type, number, order_num);
1257 }
1258 switch (GET_PHB_STATE())
1259 {
1260 case PHB_STATE_IDLE:
1261 case PHB_STATE_VERIFY:
1262 return pb_sim_search_number (type, number, order_num);
1263 default:
1264 return PHB_FAIL;
1265 }
1266 }
1267
1268
1269 /*
1270 +----------------------------------------------------------------------------+
1271 | PROJECT : GSM-PS (6147) MODULE : PHB |
1272 | STATE : code ROUTINE : pb_get_max_num_len |
1273 +----------------------------------------------------------------------------+
1274
1275 PURPOSE : This function gets the maximum length of a number within a
1276 given phonebook. The length depends on the given phonebook and
1277 the availability of extension records (SIM service table).
1278
1279 Question: The case that the extension records are present but
1280 exhausted on the SIM is not considered here. Should this be done?
1281
1282 Question: From an architectural point of view, belongs this into
1283 the ACI part of the phonebook or more into the SIM part of the
1284 phonebook? SIM part until now has no information about SIM service
1285 table.
1286
1287 */
1288 LOCAL UBYTE pb_get_max_num_len (T_PHB_TYPE type)
1289 {
1290 TRACE_FUNCTION ("pb_get_max_num_len()");
1291
1292 switch (type)
1293 {
1294 case ECC:
1295 return 3;
1296
1297 case ADN:
1298 case UPN:
1299 case ADN_ME:
1300 if (pb_sim_service (SRV_EXT1))
1301 return 2 * PHB_PACKED_NUM_LEN;
1302 break;
1303
1304 case FDN:
1305 if (pb_sim_service (SRV_EXT2))
1306 return 2 * PHB_PACKED_NUM_LEN;
1307 break;
1308
1309 case SDN:
1310 if (pb_sim_service (SRV_EXT3))
1311 return 2 * PHB_PACKED_NUM_LEN;
1312 break;
1313
1314 case BDN:
1315 if (pb_sim_service (SRV_EXT4))
1316 return 2 * PHB_PACKED_NUM_LEN;
1317 break;
1318
1319 case LDN:
1320 case LRN:
1321 case LMN:
1322 case ME:
1323 return 2 * PHB_PACKED_NUM_LEN;
1324
1325 default:
1326 TRACE_ERROR ("Invalid phonebook type");
1327 return 0;
1328 }
1329 return 20; /* Default according to 11.11 if no EXT records and not ECC */
1330 }
1331
1332
1333 GLOBAL T_PHB_RETURN pb_read_sizes (T_PHB_TYPE type, /* IN */
1334 SHORT *max_rcd, /* OUT */
1335 SHORT *used_rcd, /* OUT */
1336 UBYTE *num_len, /* OUT */
1337 UBYTE *tag_len, /* OUT */
1338 SHORT *max_ext, /* OUT */
1339 SHORT *used_ext) /* OUT */
1340 {
1341 T_PHB_RETURN phb_result;
1342
1343 TRACE_FUNCTION ("pb_read_sizes()");
1344
1345 if(type EQ ECC)
1346 {
1347 *num_len = pb_get_max_num_len (type);
1348 phb_result = pb_sim_read_sizes (type, max_rcd, used_rcd, tag_len,
1349 max_ext, used_ext);
1350 if (phb_result NEQ PHB_OK)
1351 {
1352 *max_rcd = 0;
1353 *used_rcd = 0;
1354 *num_len = 0;
1355 *tag_len = 0;
1356 *max_ext = 0;
1357 *used_ext = 0;
1358 }
1359 return PHB_OK;
1360 }
1361 switch (GET_PHB_STATE())
1362 {
1363 case PHB_STATE_IDLE:
1364 case PHB_STATE_VERIFY:
1365
1366 /*
1367 * For a valid phonebook type, set all parameters to zero instead of
1368 * reporting an error.
1369 */
1370 switch (type)
1371 {
1372 case ADN:
1373 case FDN:
1374 case BDN:
1375 case LDN:
1376 case LRN:
1377 case SDN:
1378 case LMN:
1379 case UPN:
1380 /*case ME:
1381 case ADN_ME:*/
1382 *num_len = pb_get_max_num_len (type);
1383 phb_result = pb_sim_read_sizes (type, max_rcd, used_rcd, tag_len,
1384 max_ext, used_ext);
1385 if (phb_result NEQ PHB_OK)
1386 {
1387 *max_rcd = 0;
1388 *used_rcd = 0;
1389 *num_len = 0;
1390 *tag_len = 0;
1391 *max_ext = 0;
1392 *used_ext = 0;
1393 }
1394 #ifdef _SIMULATION_
1395 TRACE_EVENT_P7 ("pb_read_sizes(): type=%d, "
1396 "max_rcd=%d, used_rcd=%d, "
1397 "num_len=%d, tag_len=%d, "
1398 "max_ext=%d, used_ext=%d",
1399 type,
1400 *max_rcd, *used_rcd,
1401 *num_len, *tag_len,
1402 *max_ext, *used_ext);
1403 #endif /* #ifdef _SIMULATION_ */
1404 return PHB_OK;
1405
1406 default:
1407 break;
1408 }
1409 return PHB_FAIL; /* Invalid phonebook */
1410
1411 default:
1412 return PHB_FAIL; /* Invalid state */
1413 }
1414 }
1415
1416
1417 GLOBAL int pb_get_entry_len (const UBYTE *pb_tag,
1418 UBYTE max_pb_len)
1419 {
1420 TRACE_FUNCTION ("pb_get_entry_len()");
1421
1422 return pb_sim_get_entry_len (pb_tag, max_pb_len);
1423 }
1424
1425
1426 GLOBAL int pb_find_free_record (T_PHB_TYPE type)
1427 {
1428 /*
1429 * This function finds the number of the first free record in
1430 * a given phonebook. This is new functionality as from S621.
1431 */
1432 TRACE_FUNCTION ("pb_find_free_record()");
1433
1434 switch (GET_PHB_STATE())
1435 {
1436 case PHB_STATE_IDLE:
1437 case PHB_STATE_VERIFY:
1438 return pb_sim_find_free_record (type);
1439 default:
1440 return PHB_FAIL;
1441 }
1442 }
1443
1444
1445 GLOBAL int pb_find_ext_free_record ()
1446 {
1447 /*
1448 * This function finds the number of the first free record in
1449 * a given phonebook. This is new functionality as from S621.
1450 */
1451 TRACE_FUNCTION ("pb_find_free_record()");
1452
1453 switch (GET_PHB_STATE())
1454 {
1455 case PHB_STATE_IDLE:
1456 case PHB_STATE_VERIFY:
1457 return pb_sim_find_free_ext_record ();
1458 default:
1459 return PHB_FAIL;
1460 }
1461 }
1462
1463 GLOBAL void pb_update_ext_bitmap (UBYTE recu_num,BOOL flag)
1464 {
1465 pb_sim_update_ext_bitmap(recu_num, flag);
1466 }
1467
1468
1469
1470
1471
1472 /*
1473 * Internal functions, not part of the interface
1474 */
1475
1476
1477
1478 /*
1479 +----------------------------------------------------------------------------+
1480 | PROJECT : GSM-PS (6147) MODULE : PHB |
1481 | STATE : code ROUTINE : pb_sim_service |
1482 +----------------------------------------------------------------------------+
1483
1484 PURPOSE : This function checks whether a given service is
1485 "allocated and activated" on the SIM, if so TRUE is returned,
1486 otherwise the function returns FALSE.
1487
1488 No, using psaSIM_ChkSIMSrvSup() is not a good alternative here
1489 as we may have to handle the situation where the SIM service
1490 table itself has been changed, in this case we are not signalled
1491 by the ACI when we have again a valid SIM service table, therefore
1492 this function exist here within the phonebook.
1493
1494 */
1495 LOCAL BOOL pb_sim_service (UBYTE nr)
1496 {
1497 UBYTE byte_offset;
1498 UBYTE bit_offset;
1499 UBYTE service;
1500
1501 TRACE_FUNCTION ("pb_sim_service()");
1502
1503 if (nr > MAX_SRV_TBL * 4)
1504 return FALSE; /* Table overflow */
1505
1506 byte_offset = (nr - 1) / 4;
1507 bit_offset = ((nr - 1) & 0x03) * 2;
1508 service = (pba_data.sim_service_table[byte_offset] >> bit_offset) & 0x03;
1509 return (service EQ ALLOCATED_AND_ACTIVATED);
1510 }
1511
1512
1513 /*
1514 +----------------------------------------------------------------------------+
1515 | PROJECT : GSM-PS (6147) MODULE : PHB |
1516 | STATE : code ROUTINE : pb_read_sim_record |
1517 +----------------------------------------------------------------------------+
1518
1519 PURPOSE : This function sends a SIM_READ_RECORD_REQ to the SIM card.
1520 On success this function returns TRUE, otherwise FALSE.
1521
1522 */
1523 LOCAL BOOL pb_read_sim_record (USHORT data_id, UBYTE rcd_num, UBYTE len)
1524 {
1525 SHORT table_id;
1526
1527 TRACE_FUNCTION ("pb_read_sim_record()");
1528
1529 table_id = psaSIM_atbNewEntry();
1530
1531 if (table_id NEQ NO_ENTRY)
1532 {
1533 /* Allocate room for the SIM data */
1534 if (pba_data.data EQ NULL)
1535 {
1536 ACI_MALLOC (pba_data.data, SIM_MAX_RECORD_SIZE);
1537 }
1538 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1539 simShrdPrm.atb[table_id].v_path_info = FALSE;
1540 simShrdPrm.atb[table_id].accType = ACT_RD_REC;
1541 simShrdPrm.atb[table_id].reqDataFld = data_id;
1542 simShrdPrm.atb[table_id].recNr = rcd_num;
1543 simShrdPrm.atb[table_id].dataLen = len;
1544 simShrdPrm.atb[table_id].exchData = pba_data.data;
1545 simShrdPrm.atb[table_id].rplyCB = pb_read_sim_record_cb;
1546
1547 simShrdPrm.aId = table_id;
1548
1549 if (psaSIM_AccessSIMData() < 0)
1550 {
1551 TRACE_EVENT("FATAL ERROR");
1552 return FALSE;
1553 }
1554 return TRUE;
1555 }
1556
1557 return FALSE;
1558 }
1559
1560
1561 /*
1562 +----------------------------------------------------------------------------+
1563 | PROJECT : GSM-PS (6147) MODULE : PHB |
1564 | STATE : code ROUTINE : pb_read_sim |
1565 +----------------------------------------------------------------------------+
1566
1567 PURPOSE : This function sends a SIM_READ_REQ to the SIM card.
1568 On success this function returns TRUE, otherwise FALSE.
1569
1570 */
1571 LOCAL BOOL pb_read_sim (USHORT data_id, UBYTE len, UBYTE max_length)
1572 {
1573 SHORT table_id;
1574
1575 TRACE_FUNCTION ("pb_read_sim()");
1576
1577 table_id = psaSIM_atbNewEntry();
1578
1579 if (table_id NEQ NO_ENTRY)
1580 {
1581 /* Allocate room for the SIM data */
1582 if (pba_data.data EQ NULL)
1583 {
1584 ACI_MALLOC (pba_data.data, SIM_MAX_RECORD_SIZE);
1585 }
1586
1587 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1588 simShrdPrm.atb[table_id].accType = ACT_RD_DAT;
1589 simShrdPrm.atb[table_id].v_path_info = FALSE;
1590 simShrdPrm.atb[table_id].reqDataFld = data_id;
1591 simShrdPrm.atb[table_id].dataOff = 0;
1592 simShrdPrm.atb[table_id].dataLen = len;
1593 simShrdPrm.atb[table_id].recMax = max_length;
1594 simShrdPrm.atb[table_id].exchData = NULL;
1595 simShrdPrm.atb[table_id].rplyCB = pb_read_sim_cb;
1596
1597 simShrdPrm.aId = table_id;
1598
1599 if (psaSIM_AccessSIMData() < 0)
1600 {
1601 TRACE_EVENT("FATAL ERROR");
1602 return FALSE;
1603 }
1604 return TRUE;
1605 }
1606 return FALSE;
1607 }
1608
1609
1610 /*
1611 +----------------------------------------------------------------------------+
1612 | PROJECT : GSM-PS (6147) MODULE : PHB |
1613 | STATE : code ROUTINE : pb_read_next_sim_book |
1614 +----------------------------------------------------------------------------+
1615
1616 PURPOSE : This function starts reading the phonebooks based on the
1617 information whether the phonebook is activated and allocated
1618 and still has to be read at all.
1619
1620 */
1621 LOCAL void pb_read_next_sim_book (void)
1622 {
1623 TRACE_FUNCTION("pb_read_next_sim_book()");
1624
1625 /*
1626 * The next three phonebooks ADN, MSISDN and LND share EXT1 records
1627 */
1628 if ((pba_data.fdn_mode NEQ FDN_ENABLE) AND
1629 pb_sim_service (SRV_ADN) AND !pba_data.book_read[ADN])
1630 {
1631 /* Read ADN from SIM card */
1632 pba_data.current_book = ADN;
1633 pba_data.book_read[ADN] = TRUE;
1634 pb_read_sim_record (SIM_ADN, 1, NOT_PRESENT_8BIT);
1635 return;
1636 }
1637
1638 if (pb_sim_service (SRV_MSISDN) AND !pba_data.book_read[UPN])
1639 {
1640 /* Read MSISDN from SIM card */
1641 pba_data.current_book = UPN;
1642 pba_data.book_read[UPN] = TRUE;
1643 pb_read_sim_record (SIM_MSISDN, 1, NOT_PRESENT_8BIT);
1644 return;
1645 }
1646
1647 #ifdef SIM_LND_SUPPORT
1648 if (pb_sim_service (SRV_LDN) AND !pba_data.book_read[LDN])
1649 {
1650 /* Read LND from SIM card */
1651 pba_data.current_book = LDN;
1652 pba_data.book_read[LDN] = TRUE;
1653 pb_read_sim_record (SIM_LND, 1, NOT_PRESENT_8BIT);
1654 return;
1655 }
1656 #endif
1657
1658 #ifdef SIM_LND_SUPPORT
1659 if (!pb_sim_service (SRV_LDN) AND !pba_data.book_read[LDN])
1660 #else
1661 if (!pba_data.book_read[LDN])
1662 #endif
1663 {
1664 /*
1665 * SIM card without LDN service. Create SIM_ICI and SIM_OCI here.
1666 * Don't create obsolete SIM_LND
1667 */
1668 pba_data.book_read[LDN] = TRUE;
1669
1670 /* Create now also some helper elementary files as of R99+ */
1671 /* (void)pb_sim_create_ef (SIM_ICI, SIZE_EF_ICI, NR_EF_ICI); */
1672 (void)pb_sim_create_ef (FFS_LRN, SIZE_EF_LRN, NR_EF_LRN);
1673 (void)pb_sim_create_ef (FFS_EXT_LRN, SIZE_EF_EXT_LRN, NR_EF_EXT_LRN);
1674 (void)pb_sim_create_ef (FFS_LMN, SIZE_EF_LMN, NR_EF_LMN);
1675 (void)pb_sim_create_ef (FFS_EXT_LMN, SIZE_EF_EXT_LMN, NR_EF_EXT_LMN);
1676
1677 (void)pb_sim_create_ef (SIM_OCI, SIZE_EF_OCI, NR_EF_OCI);
1678 (void)pb_sim_create_ef (SIM_EXT5, SIZE_EF_EXT5, NR_EF_EXT5);
1679
1680 pba_data.phb_record_max[LDN] = NR_EF_OCI;
1681 pba_data.phb_record_len[LDN] = SIZE_EF_OCI;
1682 pba_data.book_created[LDN] = TRUE;
1683
1684 /* pba_data.phb_record_max[LRN] = NR_EF_ICI; Shared! */
1685 /* pba_data.phb_record_len[LRN] = SIZE_EF_ICI; */
1686 pba_data.phb_record_max[LRN] = NR_EF_LRN;
1687 pba_data.phb_record_len[LRN] = SIZE_EF_LRN;
1688 pba_data.book_created[LRN] = TRUE;
1689
1690 /* pba_data.phb_record_max[LMN] = NR_EF_ICI; Shared! */
1691 /* pba_data.phb_record_len[LMN] = SIZE_EF_ICI; */
1692 pba_data.phb_record_max[LMN] = NR_EF_LMN;
1693 pba_data.phb_record_len[LMN] = SIZE_EF_LMN;
1694 pba_data.book_created[LMN] = TRUE;
1695
1696 pba_data.ext_record_max[EXT5] = NR_EF_EXT5;
1697 pba_data.ext_record_max[EXT_LRN] = NR_EF_EXT_LRN;
1698 pba_data.ext_record_max[EXT_LMN] = NR_EF_EXT_LMN;
1699
1700 pba_data.ext_record_max[EXT5] = SIZE_EF_EXT5;
1701 pba_data.ext_record_max[EXT_LRN] = SIZE_EF_EXT_LRN;
1702 pba_data.ext_record_max[EXT_LMN] = SIZE_EF_EXT_LMN;
1703 }
1704
1705 #ifdef SIM_LND_SUPPORT
1706 if (pba_data.book_read[ADN] OR
1707 pba_data.book_read[UPN] OR
1708 pba_data.book_read[LDN])
1709 #else
1710 if (pba_data.book_read[ADN] OR
1711 pba_data.book_read[UPN])
1712 #endif
1713 {
1714 /* At least one of the books referencing EXT1 has been read */
1715 if (!pba_data.ext_created[EXT1] AND
1716 pb_sim_service (SRV_EXT1))
1717 {
1718 /* Reading to get the number of records only */
1719 pba_data.ext_dummy_read = TRUE;
1720 pb_read_sim_record (SIM_EXT1, 1, NOT_PRESENT_8BIT);
1721 return;
1722 }
1723 }
1724
1725 /*
1726 * FDN phonebook only to be read if ADN is blocked
1727 */
1728 if ((pba_data.fdn_mode EQ FDN_ENABLE) AND
1729 pb_sim_service (SRV_FDN) AND !pba_data.book_read[FDN])
1730 {
1731 /* Read FDN from SIM card */
1732 pba_data.current_book = FDN;
1733 pba_data.book_read[FDN] = TRUE;
1734 pb_read_sim_record (SIM_FDN, 1, NOT_PRESENT_8BIT);
1735 return;
1736 }
1737
1738 if (pba_data.book_read[FDN] AND
1739 !pba_data.ext_created[EXT2] AND
1740 pb_sim_service (SRV_EXT2))
1741 {
1742 /* Reading to get the number of records only */
1743 pba_data.ext_dummy_read = TRUE;
1744 pb_read_sim_record (SIM_EXT2, 1, NOT_PRESENT_8BIT);
1745 return;
1746 }
1747
1748 if (pb_sim_service (SRV_BDN) AND !pba_data.book_read[BDN])
1749 {
1750 /* Read BDN from SIM card */
1751 pba_data.current_book = BDN;
1752 pba_data.book_read[BDN] = TRUE;
1753 pb_read_sim_record (SIM_BDN, 1, NOT_PRESENT_8BIT);
1754 return;
1755 }
1756
1757 if (pba_data.book_read[BDN] AND
1758 !pba_data.ext_created[EXT4] AND
1759 pb_sim_service (SRV_EXT4))
1760 {
1761 /* Reading to get the number of records only */
1762 pba_data.ext_dummy_read = TRUE;
1763 pb_read_sim_record (SIM_EXT4, 1, NOT_PRESENT_8BIT);
1764 return;
1765 }
1766
1767 if (pb_sim_service (SRV_SDN) AND !pba_data.book_read[SDN])
1768 {
1769 /* Read SDN from SIM card */
1770 pba_data.current_book = SDN;
1771 pba_data.book_read[SDN] = TRUE;
1772 pb_read_sim_record (SIM_SDN, 1, NOT_PRESENT_8BIT);
1773 return;
1774 }
1775
1776 if (pba_data.book_read[SDN] AND
1777 !pba_data.ext_created[EXT3] AND
1778 pb_sim_service (SRV_EXT3))
1779 {
1780 /* Reading to get the number of records only */
1781 pba_data.ext_dummy_read = TRUE;
1782 pb_read_sim_record (SIM_EXT3, 1, NOT_PRESENT_8BIT);
1783 return;
1784 }
1785
1786 /* Update the CPHS extension1 records*/
1787 pb_update_cphs_mb_ext_record();
1788
1789
1790
1791 /*
1792 * For the phonebook entries which reside on SIM but don't have
1793 * timestamps some checks could be done here.
1794 * For example, we could read based on EF_LDN, subsequently we
1795 * could read the informations solely stored in the flash and
1796 * then we could decide whether we through away the last dialled
1797 * numbers or don't.
1798 * Probably this is overkill, old Nokia 5110 and more recent Nokia 6330i
1799 * simply does not support EF_LND at all but stores the last dialled
1800 * numbers in the flash.
1801 */
1802
1803 #ifdef SIM_TOOLKIT
1804 if (simShrdPrm.fuRef >= 0)
1805 {
1806 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_SUCC_ADD);
1807 }
1808 #endif
1809
1810 /* Free SIM exchange data */
1811 if (pba_data.data NEQ NULL)
1812 {
1813 ACI_MFREE (pba_data.data);
1814 pba_data.data = NULL;
1815 }
1816
1817 SET_PHB_STATE (PHB_STATE_IDLE);
1818
1819 if (pb_read_queue() EQ PHB_EXCT)
1820 return; /* Queued LDN entry is written */
1821
1822 /* Finished reading phonebooks. Flush data. */
1823 (void)pb_sim_flush_data ();
1824
1825 /* Inform ACI that we're ready */
1826 pb_status_ind (PHB_READY, CME_ERR_NotPresent);
1827 }
1828
1829
1830 /*
1831 +----------------------------------------------------------------------------+
1832 | PROJECT : GSM-PS (6147) MODULE : PHB |
1833 | STATE : code ROUTINE : pb_read_sim_record_cb |
1834 +----------------------------------------------------------------------------+
1835
1836 PURPOSE : This function is the callback when a SIM record has been read
1837 (SIM_READ_RECORD_CNF).
1838
1839 */
1840 #define PHB_INCREMENTAL_SORT // Only locally and temporary, HM 18-Oct-2006
1841 LOCAL void pb_read_sim_record_cb (SHORT table_id)
1842 {
1843 T_PHB_RETURN phb_result; /* Phonebook result code */
1844 T_PHB_TYPE phb_type; /* Phonebook type */
1845 T_EXT_TYPE ext_type; /* Extension record type */
1846 T_PHB_TYPE next_phb_type; /* Phonebook type of record to read */
1847 T_EXT_TYPE next_ext_type; /* Extension record type of record to read */
1848 USHORT reqDataFld; /* requested datafield identifier */
1849 UBYTE recNr; /* record number */
1850 UBYTE dataLen; /* Length of data */
1851 UBYTE recMax; /* Maximum number of records */
1852 USHORT errCode; /* Error code from the SIM */
1853 USHORT ext_record_ef; /* Extension record elementary file id */
1854 UBYTE ext_record_no; /* Extension record number */
1855 BOOL changed; /* Record changed by pb_sim_write_ef() */
1856 BOOL write_record; /* Write the record */
1857
1858 TRACE_FUNCTION ("pb_read_sim_record_cb()");
1859
1860 /*
1861 * Currently we have a limitation of 254 records in the code.
1862 * This is because there is a note in 11.11 version 8.3.0 clause 6.4.2
1863 * that there is a limit of 254 records for linear fixed.
1864 * Same for USIM looking into 31.102 Annex G.
1865 * However this constraint is not valid for cyclic, and also this
1866 * note has not been present in 11.11 version 7.4.0 clause 6.2.4,
1867 * there is a limit of 255 records mentioned.
1868 * Not supporting the 255th record is a minor issue for now.
1869 * To avoid crashing, we have to limit here for now to 254.
1870 * This is not a theoretical issue only as there exists SIMs
1871 * which have 255 ADN entries.
1872 */
1873 if (simShrdPrm.atb[table_id].recMax EQ 255)
1874 simShrdPrm.atb[table_id].recMax = 254;
1875
1876 /* Get the important information from the read record from T_SIM_ACC_PRM */
1877 reqDataFld = simShrdPrm.atb[table_id].reqDataFld;
1878 recNr = simShrdPrm.atb[table_id].recNr;
1879 dataLen = simShrdPrm.atb[table_id].dataLen;
1880 recMax = simShrdPrm.atb[table_id].recMax;
1881 errCode = simShrdPrm.atb[table_id].errCode;
1882
1883 phb_type = pb_get_phb_type_from_ef (reqDataFld);
1884 ext_type = pb_get_ext_type_from_ef (reqDataFld);
1885
1886 if (phb_type EQ INVALID_PHB AND
1887 ext_type EQ INVALID_EXT)
1888 {
1889 TRACE_ERROR ("Invalid reqDataFld!");
1890 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1891 return;
1892 }
1893
1894 /* We assume we write the record until we have certain errors */
1895 write_record = TRUE;
1896
1897 if (errCode NEQ SIM_NO_ERROR)
1898 {
1899 TRACE_EVENT_P1 ("SIM indicated problem code %04x", errCode);
1900 /*
1901 * At least use cleanly deleted data instead of trash.
1902 * Do memset only if pba_data.data is not equal to NULL.
1903 */
1904 if (pba_data.data NEQ NULL)
1905 {
1906 memset (pba_data.data, 0xff, SIM_MAX_RECORD_SIZE);
1907 }
1908 else
1909 {
1910 TRACE_EVENT("PHB data has been cleared");
1911 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1912 return;
1913 }
1914 }
1915
1916 if (ext_type NEQ INVALID_EXT)
1917 {
1918 /*
1919 * Got an extension record.
1920 */
1921 if (!pba_data.ext_created[ext_type])
1922 {
1923 if (errCode NEQ SIM_NO_ERROR)
1924 {
1925 /* We won't create a field on invalid data and won't write */
1926 write_record = FALSE;
1927
1928 /*
1929 * When SIM returns an error case when tried to read Extension
1930 * file, then set the ext_created field to TRUE so that further
1931 * reading of Phonebook continues
1932 */
1933 pba_data.ext_created[ext_type] = TRUE;
1934 }
1935 else
1936 {
1937 pba_data.ext_record_max[ext_type] = recMax;
1938 pba_data.ext_record_len[ext_type] = dataLen;
1939
1940 /* Shadow field for extension record not yet created */
1941 (void)pb_sim_create_ef (reqDataFld, dataLen, recMax);
1942 pba_data.ext_created[ext_type] = TRUE;
1943 }
1944
1945 if (pba_data.ext_dummy_read)
1946 {
1947 /*
1948 * We are reading the first extension record which is assumed
1949 * to be not used just to get the number of respective extension
1950 * records.
1951 */
1952 write_record = FALSE;
1953 pba_data.ext_dummy_read = FALSE;
1954 }
1955 }
1956 }
1957 else
1958 {
1959 /*
1960 * Got a normal phonebook record
1961 */
1962 if (!pba_data.book_created[phb_type])
1963 {
1964 if (errCode NEQ SIM_NO_ERROR)
1965 {
1966 /* We won't create a field on invalid data */
1967 write_record = FALSE;
1968 }
1969 else
1970 {
1971 pba_data.phb_record_max[phb_type] = recMax;
1972 pba_data.phb_record_len[phb_type] = dataLen;
1973
1974 /* Shadow field for normal phonebook record not yet created */
1975 (void)pb_sim_create_ef (reqDataFld, dataLen, recMax);
1976 pba_data.book_created[phb_type] = TRUE;
1977
1978 #ifdef SIM_LND_SUPPORT
1979 if (phb_type EQ LDN)
1980 {
1981 /* Create now also some helper elementary files as of R99+ */
1982 (void)pb_sim_create_ef (SIM_OCI, (USHORT)(dataLen + 14), recMax);
1983 pba_data.phb_record_max[LDN] = recMax;
1984 pba_data.phb_record_len[LDN] = dataLen;
1985 pba_data.book_created[LDN] = TRUE;
1986
1987 (void)pb_sim_create_ef (SIM_ICI, (USHORT)(dataLen + 14), recMax);
1988 pba_data.phb_record_max[LRN] = recMax;
1989 pba_data.phb_record_len[LRN] = dataLen;
1990 pba_data.book_created[LRN] = TRUE;
1991
1992 pba_data.phb_record_max[LMN] = recMax;
1993 pba_data.phb_record_len[LMN] = dataLen;
1994 pba_data.book_created[LMN] = TRUE;
1995 }
1996 #endif
1997 }
1998 }
1999 }
2000
2001 /*
2002 * Write raw record. The SIM layer is aware about the data structures
2003 * and gives us the information whether we have to read an/another
2004 * extension record now or whether we can continue reading normal
2005 * phonebook entries.
2006 */
2007 if (write_record)
2008 {
2009 phb_result = pb_sim_write_ef(reqDataFld,
2010 recNr,
2011 dataLen,
2012 pba_data.data,
2013 &changed,
2014 &ext_record_ef,
2015 &ext_record_no);
2016 }
2017 else
2018 {
2019 /*
2020 * New field, record was trash, don't write it, continue reading
2021 * phonebook entries.
2022 */
2023 TRACE_EVENT ("Record not written (trash/dummy ext)");
2024
2025 phb_result = PHB_OK;
2026 changed = FALSE;
2027 ext_record_ef = 0;
2028 ext_record_no = 0;
2029 }
2030
2031 /* Mark SIM table as free now */
2032 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2033
2034 if ((GET_PHB_STATE() EQ PHB_STATE_VERIFY) AND
2035 (phb_result EQ PHB_OK) AND changed)
2036 {
2037 /* We have a change detected. Prevent further reading until all read */
2038 SET_PHB_STATE (PHB_STATE_READ);
2039 }
2040
2041 /*
2042 * Here an optimization is possible. This is, if an extension record
2043 * and already has been read we could skip reading the extension record
2044 * here. The optimization is not worth the effort, so we simply don't do
2045 * it.
2046 */
2047
2048 /*
2049 * Do some protection against garbage
2050 */
2051 if (ext_record_ef NEQ 0)
2052 {
2053 /* Current record references an extension record */
2054 next_ext_type = pb_get_ext_type_from_ef (ext_record_ef);
2055
2056 if ((next_ext_type EQ INVALID_EXT) OR
2057 (ext_record_no < 1) OR
2058 (ext_record_no > 254))
2059 {
2060 TRACE_ERROR ("pb_sim_write_ef() for ext delivered garbage EXT record");
2061 ext_record_ef = 0; /* Try to proceed without this garbage */
2062 }
2063 else if (ext_type NEQ INVALID_EXT)
2064 {
2065 /* We have read an extension record */
2066 if (pba_data.read_ext_record EQ NULL)
2067 {
2068 /* 1st extension record in the chain */
2069 ACI_MALLOC (pba_data.read_ext_record, pba_data.ext_record_max[ext_type]);
2070 memset (pba_data.read_ext_record, FALSE, pba_data.ext_record_max[ext_type]);
2071 }
2072
2073 /* Mark current extension record as read */
2074 pba_data.read_ext_record[recNr - 1] = TRUE;
2075
2076 if (pba_data.read_ext_record[ext_record_no - 1] EQ TRUE)
2077 {
2078 /* We've already read the next extension record */
2079 TRACE_ERROR ("EXT record already seen");
2080 ext_record_ef = 0; /* Mark as garbage */
2081 }
2082 }
2083 }
2084
2085 if (ext_record_ef NEQ 0)
2086 {
2087 /* Current record references an extension record */
2088 next_ext_type = pb_get_ext_type_from_ef (ext_record_ef);
2089
2090 /*
2091 * We have to read an extension record.
2092 */
2093 if (phb_type NEQ INVALID_PHB) // Patch HM 21-Sep-2006
2094 {
2095 /*
2096 * It's the first extension record. Remember the paused phonebook.
2097 */
2098 TRACE_EVENT_P4 ("PHB EF %04x record %d references EXT EF %04x record %d",
2099 reqDataFld,
2100 recNr,
2101 ext_record_ef,
2102 ext_record_no);
2103 pba_data.paused_ef = reqDataFld;
2104 pba_data.paused_no = recNr;
2105 }
2106
2107 /* Read the extension record. */
2108 if (pba_data.ext_created[next_ext_type])
2109 {
2110 (void)pb_read_sim_record (ext_record_ef,
2111 ext_record_no,
2112 pba_data.ext_record_len[next_ext_type]);
2113 }
2114 else
2115 {
2116 (void)pb_read_sim_record (ext_record_ef,
2117 ext_record_no,
2118 NOT_PRESENT_8BIT);
2119 }
2120 }
2121 else if (ext_type NEQ INVALID_EXT)
2122 {
2123 /*
2124 * The record read was the last extension record in the chain.
2125 * Come back reading normal phonebook entries.
2126 */
2127
2128 /* Free memory allocated for
2129 * tracking EXT records in chain
2130 * since EXT reading is over */
2131 if(pba_data.read_ext_record NEQ NULL)
2132 {
2133 ACI_MFREE(pba_data.read_ext_record);
2134 pba_data.read_ext_record = NULL;
2135 }
2136
2137 if (!pba_data.ext_dummy_read)
2138 {
2139 next_phb_type = pb_get_phb_type_from_ef (pba_data.paused_ef);
2140 if (pba_data.paused_no < pba_data.phb_record_max[next_phb_type])
2141 {
2142 /* Continue reading the current phonebook */
2143 (void)pb_read_sim_record (pba_data.paused_ef,
2144 (UBYTE)(pba_data.paused_no + 1),
2145 pba_data.phb_record_len[next_phb_type]);
2146
2147 #ifdef PHB_INCREMENTAL_SORT
2148 /* Sort while reading the next record from the SIM */
2149 (void)pb_sim_build_index (next_phb_type);
2150 #endif
2151
2152 }
2153 else
2154 {
2155 (void)pb_sim_build_index (next_phb_type); /* Sort last entry of this book */
2156
2157 /* Next book */
2158 pb_read_next_sim_book ();
2159 }
2160 }
2161 else
2162 {
2163 /* Next book after having read dummy extension record */
2164 pba_data.ext_dummy_read = FALSE;
2165 pb_read_next_sim_book ();
2166 }
2167 pba_data.paused_ef = 0;
2168 pba_data.paused_no = 0;
2169
2170 }
2171 else if (simShrdPrm.atb[table_id].recNr < simShrdPrm.atb[table_id].recMax)
2172 {
2173 /*
2174 * Normal phonebook record read, no extension referenced and not
2175 * finished. Continue reading the current phonebook
2176 */
2177
2178
2179 (void)pb_read_sim_record (simShrdPrm.atb[table_id].reqDataFld,
2180 (UBYTE)(simShrdPrm.atb[table_id].recNr + 1),
2181 simShrdPrm.atb[table_id].dataLen);
2182 #ifdef PHB_INCREMENTAL_SORT
2183 /* Sort while reading the next record from the SIM */
2184 (void)pb_sim_build_index (phb_type);
2185 #endif
2186
2187 }
2188 else
2189 {
2190 /*
2191 * Normal phonebook record read, no extension referenced and finished
2192 * reading this book. Continue reading the next book.
2193 */
2194 (void)pb_sim_build_index (phb_type); /* Sort last entry of this book */
2195
2196 /* Next book */
2197 pb_read_next_sim_book ();
2198 }
2199 }
2200 #undef PHB_INCREMENTAL_SORT // Only locally and temporary, HM 18-Oct-2006
2201
2202
2203 /*
2204 +----------------------------------------------------------------------------+
2205 | PROJECT : GSM-PS (6147) MODULE : PHB |
2206 | STATE : code ROUTINE : pb_sat_update_reset |
2207 +----------------------------------------------------------------------------+
2208
2209 PURPOSE : This function marks the given elementary file as unread.
2210
2211 */
2212 LOCAL void pb_sat_update_reset (USHORT ef)
2213 {
2214 T_PHB_TYPE phb_type;
2215
2216 TRACE_FUNCTION ("pb_sat_update_reset()");
2217
2218 phb_type = pb_get_phb_type_from_ef (ef);
2219
2220 if (phb_type NEQ INVALID_PHB)
2221 {
2222 /* Mark book as unread */
2223 pba_data.book_read[phb_type] = FALSE;
2224 }
2225 }
2226
2227
2228 /*
2229 +----------------------------------------------------------------------------+
2230 | PROJECT : GSM-PS (6147) MODULE : PHB |
2231 | STATE : code ROUTINE : pb_read_sim_cb |
2232 +----------------------------------------------------------------------------+
2233
2234 PURPOSE : This function is the callback when a SIM elementary file has
2235 been read (SIM_READ_CNF).
2236 There are two fields which can have been read here, those are
2237 the emergency call numbers and the SIM service table.
2238
2239 */
2240
2241
2242 LOCAL void pb_read_sim_cb (SHORT table_id)
2243 {
2244 TRACE_FUNCTION ("pb_read_sim_cb()");
2245
2246 switch (simShrdPrm.atb[table_id].reqDataFld)
2247 {
2248 case SIM_ECC:
2249 if (simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)
2250 {
2251 (void)pb_sim_set_ecc (simShrdPrm.atb[table_id].dataLen,
2252 simShrdPrm.atb[table_id].exchData);
2253
2254 #ifdef SIM_TOOLKIT
2255 if (simShrdPrm.fuRef >= 0)
2256 {
2257 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_SUCCESS);
2258 }
2259 #endif /* #ifdef SIM_TOOLKIT */
2260
2261 }
2262 else
2263 {
2264 /*
2265 * Some error from the SIM. Indicate a fallback to the PCM/FFS.
2266 */
2267 (void)pb_sim_set_ecc (0, NULL);
2268
2269 #ifdef SIM_TOOLKIT
2270 if (simShrdPrm.fuRef >= 0)
2271 {
2272 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_ERROR);
2273 }
2274 #endif
2275
2276 }
2277
2278 if (pba_data.data NEQ NULL)
2279 {
2280 ACI_MFREE (pba_data.data);
2281 pba_data.data = NULL;
2282 }
2283 break;
2284
2285 case SIM_SST:
2286 if (simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)
2287 {
2288 /* copy SIM service table */
2289 memset(pba_data.sim_service_table, 0, MAX_SRV_TBL);
2290 memcpy(pba_data.sim_service_table,
2291 simShrdPrm.atb[table_id].exchData,
2292 MINIMUM(MAX_SRV_TBL, simShrdPrm.atb[table_id].dataLen));
2293
2294 /* start reading SIM phonebook */
2295 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2296 pb_start_build (FALSE);
2297 }
2298 else
2299 {
2300 TRACE_ERROR ("Cannot read SIM service table, using old table");
2301
2302 #ifdef SIM_TOOLKIT
2303 if (simShrdPrm.fuRef >= 0)
2304 {
2305 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_ERROR);
2306 }
2307 #endif
2308
2309 /* start reading SIM phonebook (fallback action, best effort) */
2310 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2311 pb_start_build (FALSE);
2312 }
2313 break;
2314
2315 default:
2316 TRACE_ERROR ("Unexpected SIM_READ_CNF");
2317 break;
2318 }
2319 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2320 }
2321
2322
2323 /*
2324 +----------------------------------------------------------------------------+
2325 | PROJECT : GSM-PS (6147) MODULE : PHB |
2326 | STATE : code ROUTINE : pb_is_sim_field |
2327 +----------------------------------------------------------------------------+
2328
2329 PURPOSE : This function determines wheter an elementary file has to
2330 be synchronized to the SIM or only exists locally in the FFS.
2331
2332 */
2333 LOCAL BOOL pb_is_sim_field (USHORT ef)
2334 {
2335 TRACE_FUNCTION ("pb_is_sim_field()");
2336
2337 switch (ef)
2338 {
2339 /* case SIM_ICI: */
2340 case FFS_LRN:
2341 case FFS_LMN:
2342 case FFS_EXT_LRN:
2343 case FFS_EXT_LMN:
2344 case SIM_OCI:
2345 case SIM_EXT5:
2346 return FALSE; /* Only in FFS */
2347
2348 default:
2349 return TRUE; /* Counterpart in SIM exists */
2350 }
2351 }
2352
2353
2354 /*
2355 +----------------------------------------------------------------------------+
2356 | PROJECT : GSM-PS (6147) MODULE : PHB |
2357 | STATE : code ROUTINE : pb_sync_next_sim_record |
2358 +----------------------------------------------------------------------------+
2359
2360 PURPOSE : This function synchronizes a changed record to the SIM.
2361
2362 The first parameter is given to determine whether it's the first
2363 record to be synchronized, in this case ACI has to be informed.
2364
2365 If there was no record to synchronize, PHB_OK is returned.
2366 If there is a record to synchronize, PHB_EXCT is returned.
2367 If there was an internal failure we get PHB_FAIL
2368 (which is unexpected).
2369
2370 */
2371
2372 LOCAL T_PHB_RETURN pb_sync_next_sim_record (BOOL first)
2373 {
2374 T_PHB_RETURN phb_result;
2375 USHORT field_id;
2376 USHORT record;
2377 USHORT entry_size;
2378
2379 TRACE_FUNCTION ("pb_sync_next_sim_record()");
2380
2381 do
2382 {
2383 if (pba_data.records_changed.entries EQ 0)
2384 {
2385 if (pb_read_queue() EQ PHB_EXCT)
2386 return PHB_EXCT; /* Queued LDN entry is written */
2387
2388 /* Inform SIM layer we're done synchronizing */
2389 (void)pb_sim_flush_data ();
2390
2391 /* Don't change the state if phb_state is PHB_STATE_DELETE_BOOK
2392 * since state will be changed in pb_write_sim_record_cb after
2393 * all the records are deleted */
2394 if(GET_PHB_STATE() NEQ PHB_STATE_DELETE_BOOK)
2395 {
2396 SET_PHB_STATE (PHB_STATE_IDLE);
2397
2398 /* Inform ACI that we're ready */
2399 pb_status_ind (PHB_READY, CME_ERR_NotPresent);
2400 }
2401
2402 return PHB_OK; /* No record to synchronize to the SIM */
2403 }
2404
2405 /* Get the next record from the list */
2406 pba_data.records_changed.entries--;
2407 field_id = pba_data.records_changed.field_id[0];
2408 record = pba_data.records_changed.record[0];
2409
2410 /* Remove the record from the list */
2411 memmove (&pba_data.records_changed.field_id[0],
2412 &pba_data.records_changed.field_id[1],
2413 sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
2414 memmove (&pba_data.records_changed.record[0],
2415 &pba_data.records_changed.record[1],
2416 sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
2417 }
2418 while (!pb_is_sim_field(field_id));
2419
2420 TRACE_EVENT_P3 ("Synch ef %04X record %d, still %d entries to do",
2421 field_id, record, pba_data.records_changed.entries);
2422
2423 /* Allocate room for the SIM data #HM# Check for free */
2424 if (pba_data.data EQ NULL)
2425 {
2426 ACI_MALLOC (pba_data.data, SIM_MAX_RECORD_SIZE);
2427 }
2428
2429 /* Fetch record in raw form from the database */
2430 phb_result = pb_sim_read_ef (field_id,
2431 record,
2432 &entry_size,
2433 pba_data.data);
2434
2435 if (phb_result EQ PHB_OK)
2436 {
2437 /* And write it to the SIM */
2438 phb_result = pb_write_sim_record (field_id,
2439 (UBYTE)record,
2440 (UBYTE)entry_size,
2441 pba_data.data);
2442
2443 if (phb_result NEQ PHB_EXCT)
2444 {
2445 /* Inform ACI that we've had a problem */
2446 pb_status_ind ( PHB_WRITE_FAIL, CME_ERR_NotPresent );
2447 return phb_result; /* Some unexpected internal failure */
2448 }
2449
2450 if (first)
2451 {
2452 /* Inform ACI that we're busy synchronizing SIM entries */
2453 pb_status_ind ( PHB_BUSY, CME_ERR_NotPresent );
2454 }
2455
2456 return PHB_EXCT;
2457 }
2458 return phb_result;
2459 }
2460
2461
2462 /*
2463 +----------------------------------------------------------------------------+
2464 | PROJECT : GSM-PS (6147) MODULE : PHB |
2465 | STATE : code ROUTINE : pb_write_sim_record |
2466 +----------------------------------------------------------------------------+
2467
2468 PURPOSE : This function writes a SIM record to the SIM.
2469
2470 */
2471
2472 LOCAL T_PHB_RETURN pb_write_sim_record (USHORT ef,
2473 UBYTE phy_recno,
2474 UBYTE entry_size,
2475 const UBYTE *buffer)
2476 {
2477 SHORT table_id;
2478
2479
2480 TRACE_FUNCTION("pb_write_sim_record()");
2481
2482 table_id = psaSIM_atbNewEntry();
2483 if (table_id EQ NO_ENTRY)
2484 {
2485 TRACE_ERROR ("pb_write_sim_record(): no more table entries");
2486 return (PHB_FAIL);
2487 }
2488
2489 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
2490 simShrdPrm.atb[table_id].accType = ACT_WR_REC;
2491 simShrdPrm.atb[table_id].v_path_info = FALSE;
2492 simShrdPrm.atb[table_id].reqDataFld = ef;
2493 simShrdPrm.atb[table_id].recNr = phy_recno;
2494 simShrdPrm.atb[table_id].dataLen = entry_size;
2495 simShrdPrm.atb[table_id].exchData = (UBYTE *)buffer;
2496 simShrdPrm.atb[table_id].rplyCB = pb_write_sim_record_cb;
2497
2498 simShrdPrm.aId = table_id;
2499
2500 if (psaSIM_AccessSIMData() < 0)
2501 {
2502 TRACE_EVENT("pb_write_sim_record(): psaSIM_AccessSIMData() failed");
2503 return (PHB_FAIL);
2504 }
2505
2506 return (PHB_EXCT);
2507 }
2508
2509
2510 /*
2511 +----------------------------------------------------------------------------+
2512 | PROJECT : GSM-PS (6147) MODULE : PHB |
2513 | STATE : code ROUTINE : pb_write_sim_record_cb |
2514 +----------------------------------------------------------------------------+
2515
2516 PURPOSE : This function is the callback when a SIM record has been
2517 written to the SIM.
2518
2519 */
2520
2521 LOCAL void pb_write_sim_record_cb (SHORT table_id)
2522 {
2523 UBYTE max_record;
2524 T_PHB_RETURN phb_result;
2525
2526 TRACE_FUNCTION("pb_write_sim_record_cb()");
2527
2528 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2529
2530 if (simShrdPrm.atb[table_id].errCode NEQ SIM_NO_ERROR)
2531 {
2532 /*
2533 * Data in the database and on the SIM probably now differ,
2534 * we can do not much about this.
2535 */
2536 TRACE_ERROR("pb_write_cb(): error for writing");
2537 pb_status_ind (PHB_WRITE_FAIL,
2538 (SHORT)cmhSIM_GetCmeFromSim (simShrdPrm.atb[table_id].errCode));
2539 return;
2540 }
2541
2542 switch (GET_PHB_STATE())
2543 {
2544 case PHB_STATE_WRITE:
2545 /* Synchronize next SIM record */
2546 switch (pb_sync_next_sim_record (FALSE))
2547 {
2548 case PHB_OK:
2549 /* PHB_READY has been already indicated in pb_sync_next_sim_record */
2550 break;
2551
2552 case PHB_EXCT:
2553 break; /* Next record => SIM */
2554
2555 case PHB_FAIL:
2556 default:
2557 TRACE_ERROR ("Unexpected phb_result");
2558 SET_PHB_STATE (PHB_STATE_IDLE);
2559 pb_status_ind (PHB_WRITE_FAIL, CME_ERR_NotPresent);
2560 break;
2561 }
2562 break;
2563
2564 case PHB_STATE_DELETE_BOOK:
2565 /* Synchronize next SIM record */
2566 switch (pb_sync_next_sim_record (FALSE))
2567 {
2568 case PHB_OK:
2569 /*
2570 * Record synched. Delete next record of phonebook, if available
2571 */
2572 max_record = pba_data.phb_record_max[pba_data.current_book];
2573 while ((pba_data.del_record <= max_record) AND
2574 (pba_data.records_changed.entries EQ 0))
2575 {
2576 /* Delete the record in the database */
2577 phb_result = pb_sim_del_record (pba_data.current_book,
2578 pba_data.del_record,
2579 &pba_data.records_changed);
2580
2581 if ((phb_result NEQ PHB_OK) AND (phb_result NEQ PHB_EMPTY_RECORD))
2582 {
2583 TRACE_ERROR ("Unexpected problem from pb_sim_del_record()");
2584
2585 /* Inform SIM layer we're done synchronizing.
2586 * Should we indicate also there was a problem? */
2587 (void)pb_sim_flush_data ();
2588
2589 pb_status_ind (PHB_WRITE_FAIL, CME_ERR_NotPresent);
2590
2591 SET_PHB_STATE (PHB_STATE_IDLE);
2592 return;
2593 }
2594 pba_data.del_record++;
2595 }
2596
2597 if (pba_data.records_changed.entries NEQ 0)
2598 {
2599 /* Synchronizing record(s) to the SIM */
2600 if (pb_sync_next_sim_record (FALSE) NEQ PHB_EXCT)
2601 {
2602 TRACE_ERROR ("Unexpected problem from pb_sync_next_sim_record()");
2603
2604 /* Inform SIM layer we're done synchronizing.
2605 * Should we indicate also there was a problem? */
2606 (void)pb_sim_flush_data ();
2607
2608 pb_status_ind (PHB_WRITE_FAIL, CME_ERR_NotPresent);
2609
2610 SET_PHB_STATE (PHB_STATE_IDLE);
2611 return;
2612 }
2613 }
2614
2615 /*
2616 * We're through
2617 */
2618 if(pba_data.del_record > max_record)
2619 {
2620 (void)pb_sim_flush_data ();
2621
2622 SET_PHB_STATE (PHB_STATE_IDLE);
2623
2624 /* Inform the ACI that we're done */
2625 pb_status_ind (PHB_READY, CME_ERR_NotPresent);
2626 }
2627 break;
2628
2629 case PHB_EXCT:
2630 break; /* Next record => SIM */
2631
2632 case PHB_FAIL:
2633 default:
2634 TRACE_ERROR ("Unexpected problem synching SIM");
2635
2636 (void)pb_sim_flush_data ();
2637
2638 pb_status_ind (PHB_WRITE_FAIL, CME_ERR_NotPresent);
2639 /* Inform SIM layer we're done synchronizing.
2640 * Should we indicate also there was a problem? */
2641
2642 SET_PHB_STATE (PHB_STATE_IDLE);
2643 break;
2644 }
2645 break;
2646
2647 default:
2648 TRACE_ERROR ("Unexpected default");
2649 break;
2650 }
2651 }
2652
2653
2654 /*
2655 +----------------------------------------------------------------------------+
2656 | PROJECT : GSM-PS (6147) MODULE : PHB |
2657 | STATE : code ROUTINE : pb_get_phb_type_from_ef |
2658 +----------------------------------------------------------------------------+
2659
2660 PURPOSE : This function converts a SIM elementary file number to the
2661 appropriate constant of type T_PHB_TYPE, if applicable.
2662 Non applicable => INVALID_PHB
2663
2664 */
2665 T_PHB_TYPE pb_get_phb_type_from_ef (USHORT ef)
2666 {
2667 TRACE_FUNCTION ("pb_get_phb_type_from_ef()");
2668
2669 switch (ef)
2670 {
2671 case SIM_ECC:
2672 return ECC;
2673
2674 case SIM_ADN:
2675 return ADN;
2676
2677 case SIM_FDN:
2678 return FDN;
2679
2680 case SIM_BDN:
2681 return BDN;
2682
2683 case SIM_LND:
2684 return LDN;
2685
2686 case SIM_MSISDN:
2687 return UPN;
2688
2689 case SIM_SDN:
2690 return SDN;
2691
2692 default:
2693 return INVALID_PHB;
2694 }
2695 }
2696
2697
2698 /*
2699 +----------------------------------------------------------------------------+
2700 | PROJECT : GSM-PS (6147) MODULE : PHB |
2701 | STATE : code ROUTINE : pb_get_ext_type_from_ef |
2702 +----------------------------------------------------------------------------+
2703
2704 PURPOSE : This function converts a SIM elementary file number to the
2705 appropriate constant of T_PHB_EXT_TYPE, if applicable.
2706 Non applicable => INVALID_EXT
2707
2708 */
2709 T_EXT_TYPE pb_get_ext_type_from_ef (USHORT ef)
2710 {
2711 TRACE_FUNCTION ("pb_get_ext_type_from_ef()");
2712
2713 switch (ef)
2714 {
2715 case SIM_EXT1:
2716 return EXT1;
2717
2718 case SIM_EXT2:
2719 return EXT2;
2720
2721 case SIM_EXT3:
2722 return EXT3;
2723
2724 case SIM_EXT4:
2725 return EXT4;
2726
2727 case SIM_EXT5:
2728 return EXT5;
2729
2730 default:
2731 return INVALID_EXT;
2732 }
2733 }
2734
2735
2736 /* ------------------------------------------------------------------------ */
2737
2738 /*
2739 +----------------------------------------------------------------------------+
2740 | PROJECT : GSM-PS (6147) MODULE : PHB |
2741 | STATE : code ROUTINE : pb_search_number_ex |
2742 +----------------------------------------------------------------------------+
2743
2744 PURPOSE : At some places a more sohisticated number searching function
2745 is desirable which can be based on existing phonebook
2746 functionality.
2747
2748 */
2749 GLOBAL T_PHB_RETURN pb_search_number_ex (T_PHB_TYPE type,
2750 const UBYTE *number,
2751 SHORT *order_num,
2752 SHORT *found,
2753 T_PHB_RECORD *entry)
2754 {
2755 T_PHB_RETURN phb_result;
2756 SHORT index;
2757
2758 TRACE_FUNCTION ("pb_search_number_ex()");
2759
2760 /* Search for first entry */
2761 phb_result = pb_search_number (type,
2762 number,
2763 order_num);
2764 if (phb_result NEQ PHB_OK)
2765 return phb_result;
2766
2767 /*
2768 * Determine number of found entries. We are doing a linear algorithm,
2769 * a binary algorithm is possible here to speed up things.
2770 */
2771 if (found NEQ NULL)
2772 {
2773 *found = 1;
2774 index = *order_num;
2775
2776 while (pb_search_number (type, number, &index) EQ PHB_OK)
2777 {
2778 ++(*found);
2779 /* index should not be incremented as lower layer (DB) will take
2780 care of it */
2781 }
2782 }
2783
2784 /* Read the first found entry, if desired */
2785 if (entry NEQ NULL)
2786 return (pb_read_number_record (type, *order_num, entry));
2787 return PHB_OK;
2788 }
2789
2790
2791 /*
2792 +----------------------------------------------------------------------------+
2793 | PROJECT : GSM-PS (6147) MODULE : PHB |
2794 | STATE : code ROUTINE : pb_search_name_ex |
2795 +----------------------------------------------------------------------------+
2796
2797 PURPOSE : At some places a more sohisticated name searching function
2798 is desirable which can be based on existing phonebook
2799 functionality.
2800
2801 */
2802 GLOBAL T_PHB_RETURN pb_search_name_ex (T_PHB_TYPE type,
2803 T_PHB_MATCH match,
2804 const T_ACI_PB_TEXT *search_tag,
2805 SHORT *order_num,
2806 SHORT *found,
2807 T_PHB_RECORD *entry)
2808 {
2809 T_PHB_RETURN phb_result;
2810 SHORT index;
2811
2812 TRACE_FUNCTION ("pb_search_name_ex()");
2813
2814 /* Search for first entry */
2815 phb_result = pb_search_name (type,
2816 match,
2817 search_tag,
2818 order_num);
2819 if (phb_result NEQ PHB_OK)
2820 return phb_result;
2821
2822 /*
2823 * Determine number of found entries. We are doing a linear algorithm,
2824 * a binary algorithm is possible here to speed up things.
2825 */
2826 if (found NEQ NULL)
2827 {
2828 *found = 1;
2829 index = *order_num;
2830
2831 while (pb_search_name (type, match, search_tag, &index) EQ PHB_OK)
2832 {
2833 ++(*found);
2834 /* index should not be incremented as lower layer (DB) will take
2835 care of it */
2836 }
2837
2838 }
2839
2840 /* Read the first found entry, if desired */
2841 if (entry NEQ NULL)
2842 return (pb_read_alpha_record (type, *order_num, entry));
2843 return PHB_OK;
2844 }
2845
2846
2847 /*
2848 +----------------------------------------------------------------------------+
2849 | PROJECT : GSM-PS (6147) MODULE : PHB |
2850 | STATE : code ROUTINE : pb_status_ind |
2851 +----------------------------------------------------------------------------+
2852
2853 PURPOSE : This function indicates the new phonebook status to the ACI
2854 preventing we're indication twice PHB_READY or PHB_BUSY.
2855
2856 */
2857 LOCAL void pb_status_ind (T_PHB_STAT phb_stat, SHORT cmeError)
2858 {
2859 TRACE_FUNCTION ("pb_status_ind()");
2860
2861 /* Avoid to indicate twice busy or ready */
2862 if ((pba_data.phb_stat NEQ phb_stat) OR
2863 ((phb_stat NEQ PHB_READY) AND
2864 (phb_stat NEQ PHB_BUSY)))
2865 {
2866 pba_data.phb_stat = phb_stat;
2867 cmhPHB_StatIndication (phb_stat, cmeError,TRUE);
2868 }
2869 }
2870
2871
2872 /*
2873 +----------------------------------------------------------------------------+
2874 | PROJECT : GSM-PS (6147) MODULE : PHB |
2875 | STATE : code ROUTINE : pb_write_queue |
2876 +----------------------------------------------------------------------------+
2877
2878 PURPOSE : This function writes a LDN entry to the queue if the SIM is busy.
2879
2880 */
2881 LOCAL T_PHB_RETURN pb_write_queue (const T_PHB_RECORD *entry)
2882 {
2883 TRACE_FUNCTION ("pb_write_queue()");
2884
2885 if (pba_data.c_queued < PHB_MAX_QUEUE)
2886 {
2887 memmove (&pba_data.queued[1],
2888 &pba_data.queued[0],
2889 pba_data.c_queued * sizeof (T_PHB_QUEUE *));
2890 ACI_MALLOC (pba_data.queued[pba_data.c_queued],
2891 sizeof (T_PHB_QUEUE));
2892 pba_data.queued[0]->entry = *entry;
2893 pba_data.c_queued++;
2894 return PHB_EXCT;
2895 }
2896
2897 return PHB_FAIL; /* Queue full */
2898 }
2899
2900
2901 /*
2902 +----------------------------------------------------------------------------+
2903 | PROJECT : GSM-PS (6147) MODULE : PHB |
2904 | STATE : code ROUTINE : pb_clear_queue |
2905 +----------------------------------------------------------------------------+
2906
2907 PURPOSE : This function clears the LDN queue.
2908
2909 */
2910 LOCAL void pb_clear_queue (void)
2911 {
2912 TRACE_FUNCTION ("pb_clear_queue()");
2913
2914 while (pba_data.c_queued NEQ 0)
2915 {
2916 pba_data.c_queued--;
2917 ACI_MFREE (pba_data.queued[pba_data.c_queued]);
2918 pba_data.queued[pba_data.c_queued] = NULL;
2919 }
2920 }
2921
2922
2923 /*
2924 +----------------------------------------------------------------------------+
2925 | PROJECT : GSM-PS (6147) MODULE : PHB |
2926 | STATE : code ROUTINE : pb_read_queue |
2927 +----------------------------------------------------------------------------+
2928
2929 PURPOSE : This function reads the queue and adds the queued phonebook
2930 entries.
2931
2932 */
2933 LOCAL T_PHB_RETURN pb_read_queue (void)
2934 {
2935 T_PHB_RETURN phb_result;
2936
2937 TRACE_FUNCTION ("pb_write_queue()");
2938
2939 while (pba_data.c_queued NEQ 0)
2940 {
2941 /*
2942 * LDN entries have been queued. Write them now.
2943 */
2944 pba_data.c_queued--;
2945 phb_result = pb_add_record (LDN,
2946 pba_data.queued[pba_data.c_queued]->index,
2947 &pba_data.queued[pba_data.c_queued]->entry);
2948 ACI_MFREE (pba_data.queued[pba_data.c_queued]);
2949 pba_data.queued[pba_data.c_queued] = NULL;
2950 switch (phb_result)
2951 {
2952 case PHB_EXCT:
2953 return phb_result;
2954 case PHB_OK:
2955 break;
2956 default:
2957 pb_clear_queue();
2958 return phb_result;
2959 }
2960 }
2961 return PHB_OK;
2962 }
2963
2964 /*
2965 +------------------------------------------------------------------+
2966 | PROJECT : MMI-Framework (8417) MODULE: PHB |
2967 | STATE : code ROUTINE : pb_status_req |
2968 +------------------------------------------------------------------+
2969
2970 PURPOSE : To update status of Phonebook to MMI
2971
2972 */
2973 void pb_status_req(UBYTE *pb_stat)
2974 {
2975
2976 *pb_stat = pba_data.phb_stat;
2977 }
2978
2979 #endif /* #ifdef TI_PS_FFS_PHB */