line source
/*
+-----------------------------------------------------------------------------
| Project : MMI-Framework (8417)
| Modul : PHB
+-----------------------------------------------------------------------------
| Copyright 2002 Texas Instruments Berlin, AG
| All rights reserved.
|
| This file is confidential and a trade secret of Texas
| Instruments Berlin, AG
| The receipt of or possession of this file does not convey
| any rights to reproduce or disclose its contents or to
| manufacture, use, or sell anything it may describe, in
| whole, or in part, without the specific written consent of
| Texas Instruments Berlin, AG.
+-----------------------------------------------------------------------------
| Purpose : This modul contains the functions to establish the phone book.
+-----------------------------------------------------------------------------
*/
#ifdef TI_PS_FFS_PHB
#include "aci_all.h"
#include "aci_cmh.h"
#include "aci_mem.h"
#include "phb_sim.h"
#include "phb_aci.h"
#include "ffs/ffs.h"
#ifdef SIM_TOOLKIT
#include "psa.h"
#include "psa_sim.h"
#include "psa_cc.h"
#include "psa_sat.h"
#endif /* #ifdef SIM_TOOLKIT */
#include "cmh.h"
#include "cmh_phb.h"
#include "pcm.h"
/*
* Constants and enumerations
*/
#define MAX_ECC_RCD 5
#define FFS_IMSI_SIZE 8
#define MAX_EXTNS_PER_RECORD 9
#define MAX_ELEM_FILES 15
#define SIM_MAX_RECORD_SIZE 256 /* Maximum size of a SIM record */
#define RDM_DATA_FILE_ID (0xff04) /* File ID to store data related to LDN, LMN and LRN Phonebooks */
#define SIZE_DATA_DATE_TIME 12
#define MAX_EXT_RECORDS 10
typedef enum
{
DECREMENT = -1,
INCREMENT
} T_PHB_EXT_REF_TYPE;
/*
* Type definitions
*/
typedef struct
{
/* Handle for the Database */
int db_handle;
/* Maximum number of records */
UBYTE max_record[MAX_PHONEBOOK];
/* Number of used records */
UBYTE used_record[MAX_PHONEBOOK];
/* Records sizes */
USHORT record_size[MAX_PHONEBOOK];
} T_PHB_SIM_DATA;
#define RDM_PHB_DATA_SIZE 6
/* ECC records */
T_PHB_ECC_RECORD phb_ecc_element[MAX_ECC_RCD];
LOCAL T_PHB_SIM_DATA pbs_data;
/* Global arrays to hold Reference count for Extension records. */
UBYTE ext1_ref_count[MAX_EXT_RECORDS], ext2_ref_count[MAX_EXT_RECORDS];
UBYTE ext3_ref_count[MAX_EXT_RECORDS], ext4_ref_count[MAX_EXT_RECORDS];
UBYTE ext5_ref_count[MAX_EXT_RECORDS];
UBYTE ext_lmn_ref_count[MAX_EXT_RECORDS], ext_lrn_ref_count[MAX_EXT_RECORDS];
/* Prototypes for search and compare functions */
int pb_sim_search_alpha_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num);
int pb_sim_search_num_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num);
int pb_sim_alpha_cmp (int db_handle, USHORT field_id, USHORT recno_1, USHORT recno_2, ULONG flags);
int pb_sim_number_cmp (int db_handle, USHORT field_id,USHORT recno_1,USHORT recno_2, ULONG flags);
/*
* Prototypes for local functions
*/
LOCAL void pb_sim_read_eeprom_ecc (void);
LOCAL int pb_sim_nibblecopy (UBYTE dest[], int destlen, UBYTE src[], int count);
LOCAL void pb_sim_revString(char *);
LOCAL void pb_sim_read_ext(UBYTE *buffer, T_PHB_RECORD *entry);
LOCAL void pb_sim_prepare_ext_data(UBYTE *ext_data, int ext_count, UBYTE *number, UBYTE no_len, UBYTE *subaddr);
LOCAL USHORT pb_sim_get_field_id (T_PHB_TYPE type);
LOCAL USHORT pb_sim_get_ext_file (T_PHB_TYPE type);
LOCAL USHORT pb_sim_get_ext_file_id (USHORT field_id);
LOCAL USHORT pb_sim_get_size_except_tag (USHORT field_id);
LOCAL int pb_sim_cmpString ( UBYTE* cur_tag, UBYTE* check_tag, UBYTE cmpLen );
LOCAL void pb_sim_cvt_alpha_for_cmp ( UBYTE* entry_tag, UBYTE* cur_tag, UBYTE len );
LOCAL int pb_sim_cmp2Bytes(UBYTE *s1, UBYTE *s2, UBYTE len, UBYTE flag);
LOCAL T_PHB_RETURN pb_sim_update_extn_records(USHORT ext_field_id, USHORT rec_num, T_PHB_EXT_REF_TYPE ref_type);
LOCAL T_PHB_RETURN pb_sim_read_ext_record_for_delete(T_PHB_TYPE type, USHORT field_id, USHORT db_recno);
/*
+----------------------------------------------------------------------+
| PROJECT: MMI-Framework MODULE : PHB |
| STATE : code ROUTINE: pb_sim_init |
+----------------------------------------------------------------------+
PURPOSE : Initializes internal data structures for SIM Phonebook.
*/
void pb_sim_init (void)
{
USHORT i;
TRACE_FUNCTION ("pb_sim_init()");
db_init();
/* Initialise the data structures. */
/* Initialise ECC Phonebook to contain no records. */
for(i = 0; i < MAX_ECC_RCD; i++)
phb_ecc_element[i].phy_idx = 0;
return;
}
/*
+----------------------------------------------------------------------+
| PROJECT: MMI-Framework MODULE : PHB |
| STATE : code ROUTINE: pb_sim_exit |
+----------------------------------------------------------------------+
PURPOSE : This function is called by pb_exit() to inform the SIM part
of the phonebook to shut down.
*/
void pb_sim_exit (void)
{
TRACE_FUNCTION ("pb_sim_exit()");
db_exit();
return;
}
/*
+----------------------------------------------------------------------+
| PROJECT: MMI-Framework MODULE : PHB |
| STATE : code ROUTINE: pb_sim_set_ecc |
+----------------------------------------------------------------------+
PURPOSE : The emergency call numbers are read from SIM card and
written to FFS.
*/
T_PHB_RETURN pb_sim_set_ecc (UBYTE ecc_len, const UBYTE *sim_ecc)
{
USHORT ecc_rec_num;
UBYTE *data_ptr;
TRACE_FUNCTION ("pb_sim_set_ecc()");
/* Initialise used records for ECC. */
pbs_data.used_record[ECC] = 0;
/* if SIM ECC data is not empty, copy SIM ECC data to phonebook */
if ( ecc_len NEQ 0)
{
data_ptr = ( UBYTE *) sim_ecc;
pbs_data.max_record[ECC] = (SHORT)((ecc_len/ECC_NUM_LEN) > MAX_ECC_RCD)? MAX_ECC_RCD: ecc_len/ECC_NUM_LEN;
pbs_data.record_size[ECC] = ECC_NUM_LEN;
/* Store ECC into RAM, since ECC records will be less in number. */
for (ecc_rec_num = 0; ecc_rec_num < MAX_ECC_RCD; ecc_rec_num++)
{
if(*data_ptr NEQ 0xff)
{
memset(&phb_ecc_element[ecc_rec_num],0,sizeof(T_PHB_ECC_RECORD));
phb_ecc_element[ecc_rec_num].phy_idx = ecc_rec_num + 1;
memcpy(phb_ecc_element[ecc_rec_num].number, data_ptr, ECC_NUM_LEN);
data_ptr += ECC_NUM_LEN;
(pbs_data.used_record[ECC])++;
}
}
}
else
{
pb_sim_read_eeprom_ecc();
}
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_create_ef |
+--------------------------------------------------------------------+
PURPOSE : Creates a SIM elementary file.
*/
T_PHB_RETURN pb_sim_create_ef (USHORT ef, USHORT record_size, USHORT records)
{
T_DB_INFO_FIELD field_info;
T_DB_TYPE db_type;
int db_result;
TRACE_FUNCTION ("pb_sim_create_ef()");
TRACE_EVENT_P1("Elementary file ID = %x",ef);
db_result = db_info_field(pbs_data.db_handle, ef, &field_info);
/* Check whether file already exists. */
if(db_result EQ DB_OK)
{
/* Check for Record size and No. of records in the present field. */
if((field_info.record_size EQ record_size) AND (field_info.num_records EQ records))
return PHB_OK; /* Preserve the existing field. */
else
{
if(pb_sim_remove_ef(ef) EQ PHB_FAIL) /* Remove the existing file and recreate the field. */
return PHB_FAIL;
}
}
/* Set DB_TYPE depending on the Elementary file. */
switch(ef)
{
case SIM_ADN:
case SIM_FDN:
case SIM_BDN:
case SIM_SDN:
case SIM_EXT1:
case SIM_EXT2:
case SIM_EXT3:
case SIM_EXT4:
case SIM_LND:
case SIM_OCI:
//case SIM_ICI:
case FFS_LRN:
case FFS_LMN:
case FFS_EXT_LRN:
case FFS_EXT_LMN:
case SIM_EXT5:
db_type = DB_FREELIST;
break;
case SIM_MSISDN:
case SIM_IMSI:
db_type = DB_UNMANAGED;
break;
default:
TRACE_ERROR("Invalid ef passed to pb_sim_create_ef()");
return PHB_FAIL;
}
db_result = db_create_field(pbs_data.db_handle, db_type, ef, record_size, records);
if(db_result EQ DB_OK)
return PHB_OK;
/* Return PHB_FAIL since DB has failed to create File. */
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_write_ef |
+--------------------------------------------------------------------+
PURPOSE : Writes entry_size bytes content of buffer at index to the elementary file ef.
*/
T_PHB_RETURN pb_sim_write_ef (USHORT ef, USHORT phy_recno,
USHORT entry_size, const UBYTE *buffer,
BOOL *changed, USHORT *ext_record_ef, UBYTE *ext_record_no)
{
int i;
T_DB_CHANGED records_affected;
TRACE_FUNCTION ("pb_sim_write_ef()");
/* Initialise changed to FALSE. */
*changed = FALSE;
/* Check for extension records. */
switch (ef)
{
case SIM_ADN:
case SIM_MSISDN:
case SIM_LND:
*ext_record_ef = SIM_EXT1;
*ext_record_no = buffer[entry_size - 1];
break;
case SIM_FDN:
*ext_record_ef = SIM_EXT2;
*ext_record_no = buffer[entry_size - 1];
break;
case SIM_SDN:
*ext_record_ef = SIM_EXT3;
*ext_record_no = buffer[entry_size - 1];
break;
case SIM_BDN:
*ext_record_ef = SIM_EXT4;
*ext_record_no = buffer[entry_size - 1];
break;
case FFS_LRN:
case FFS_LMN:
case SIM_OCI: /* Release 1999 and above 31.102 clause 4.2.34 */
*ext_record_ef = SIM_EXT5;
*ext_record_no = buffer[entry_size - 15]; // Jirli, please check, 14 instead of 15?
break;
case SIM_EXT1: /* Extension records can reference other extension records */
case SIM_EXT2:
case SIM_EXT3:
case SIM_EXT4:
case SIM_EXT5:
case FFS_EXT_LRN:
case FFS_EXT_LMN:
*ext_record_ef = ef;
*ext_record_no = buffer[entry_size - 1];
break;
default:
*ext_record_ef = 0;
*ext_record_no = 0;
}
/* Record is not referring any extensions. So set ef and record_no to ZERO. */
if (*ext_record_no EQ 0xff)
{
*ext_record_ef = 0;
*ext_record_no = 0;
}
if (buffer[0] NEQ 0xFF)
{
/* Write record into FFS */
if(db_write_record(pbs_data.db_handle, ef, phy_recno, 0, entry_size, buffer) > DB_OK)
{
if(db_read_change_log(pbs_data.db_handle, &records_affected) EQ DB_OK)
{
for(i = 0; i < records_affected.entries; i++)
{
/* Checking whether Elementary file in the database is changed. */
if((records_affected.field_id[i] EQ ef) AND (records_affected.record[i] EQ phy_recno))
{
*changed = TRUE;
return PHB_OK;
}
}
/* Write operation has not changed File in the database. So returning PHB_OK */
return PHB_OK;
}
else /* Unable to read change log from DB. So returning PHB_FAIL. */
return PHB_FAIL;
}
else /* Write failure in DB. So returning PHB_FAIL */
return PHB_FAIL;
}
else
{
/* Empty record */
if (db_delete_record (pbs_data.db_handle, ef, phy_recno) NEQ DB_OK)
return PHB_FAIL;
if(db_read_change_log (pbs_data.db_handle, &records_affected) NEQ DB_OK)
return PHB_FAIL;
*changed = (records_affected.entries NEQ 0);
return PHB_OK;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_open |
+--------------------------------------------------------------------+
PURPOSE : Opens the SIM phonebook for the given SIM determined by the IMSI.
*/
T_PHB_RETURN pb_sim_open (const T_imsi_field *imsi_field, BOOL *changed)
{
T_DB_INFO database_info;
UBYTE ffsIMSI[MAX_IMSI_LEN+1];
UBYTE simIMSI[MAX_IMSI_LEN+1];
UBYTE imsi[FFS_IMSI_SIZE];
int db_result;
UBYTE buffer[RDM_PHB_DATA_SIZE];
TRACE_FUNCTION("pb_sim_open()");
/* Initially set SIM changed as TRUE. */
*changed = TRUE;
/* Open the database. */
db_result = db_open(FFS_PHB_DIR);
TRACE_EVENT_P1("DB handle is %d",db_result);
if(db_result >= DB_OK)
{
pbs_data.db_handle = db_result;
/* Get database info. */
db_result = db_info(pbs_data.db_handle, &database_info);
/* Read IMSI from the FFS if Database is clean. */
if((db_result EQ DB_OK) AND (database_info.clean EQ TRUE))
{
db_result = db_read_record(pbs_data.db_handle, SIM_IMSI, 1, 0, FFS_IMSI_SIZE, imsi);
/* Compare IMSI read from FFS with IMSI got from SIM. */
if(db_result > DB_OK)
{
psaSIM_decodeIMSI ((UBYTE*) imsi_field->field,(UBYTE)imsi_field->c_field, (char *)simIMSI);
psaSIM_decodeIMSI (imsi, FFS_IMSI_SIZE, (char *)ffsIMSI);
if (!strcmp((char *)simIMSI, (char *)ffsIMSI))
{
*changed = FALSE;
return PHB_OK;
}
}
else
{
/* Unable to read IMSI, regenerate database */
*changed = TRUE;
}
}
/* Remove database whenever database is Inconsistent and SIM is changed. */
if(db_close(pbs_data.db_handle) NEQ DB_OK)
return PHB_FAIL;
if(db_remove(FFS_PHB_DIR) NEQ DB_OK)
return PHB_FAIL;
}/* if(db_result >= DB_OK) */
/* Create database: For the first time, whenever SIM is changed
and whenever database is Inconsistent. */
db_result = db_create(FFS_PHB_DIR, MAX_ELEM_FILES, TRUE);
TRACE_EVENT_P1("DB handle is %d",db_result);
/* Creating DB is successful and valid db_handle is returned */
if(db_result >= DB_OK)
{
if(db_create_field(pbs_data.db_handle, DB_UNMANAGED, SIM_IMSI, imsi_field->c_field, 1) NEQ DB_OK)
return PHB_FAIL;
if(db_write_record(pbs_data.db_handle, SIM_IMSI, 1, 0, imsi_field->c_field, imsi_field->field) < DB_OK)
return PHB_FAIL;
/* Create Elementary file to store RDM Phonebook data */
if(db_create_field(pbs_data.db_handle, DB_UNMANAGED, RDM_DATA_FILE_ID,RDM_PHB_DATA_SIZE,1) NEQ DB_OK)
return PHB_FAIL;
memset(buffer,0x00, RDM_PHB_DATA_SIZE);
if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, buffer) < DB_OK)
return PHB_FAIL;
return PHB_OK;
}
/* Unable to create Database. So returning PHB_FAIL. */
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_ef |
+--------------------------------------------------------------------+
PURPOSE : Reads *buffer from elementary file ef at index.
*/
T_PHB_RETURN pb_sim_read_ef (USHORT ef, USHORT recno, USHORT *entry_size, UBYTE *buffer)
{
int db_result;
T_DB_INFO_FIELD field_info;
TRACE_FUNCTION("pb_sim_read_ef()");
if(db_info_field(pbs_data.db_handle, ef, &field_info) EQ DB_OK)
{
*entry_size = field_info.record_size;
db_result = db_read_record (pbs_data.db_handle,
ef,
recno,
0,
field_info.record_size,
buffer);
if (db_result > DB_OK)
return PHB_OK; /* Successfully read */
if (db_result EQ DB_EMPTY_RECORD)
{
/* Return a deleted record content */
memset (buffer, 0xff, *entry_size);
return PHB_OK;
}
return PHB_FAIL; /* Some problem reading record */
}
/* Returning PHB_FAIL, since DB has failed to give Info about the field. */
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_remove_ef |
+--------------------------------------------------------------------+
PURPOSE : Removes elementary file.
*/
T_PHB_RETURN pb_sim_remove_ef (USHORT ef)
{
TRACE_FUNCTION("pb_sim_remove_ef()");
if(db_remove_field(pbs_data.db_handle, ef) EQ DB_OK)
return PHB_OK;
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_build_index |
+--------------------------------------------------------------------+
PURPOSE : Builds index for the given phonebook.
*/
T_PHB_RETURN pb_sim_build_index (T_PHB_TYPE type)
{
USHORT field_id;
TRACE_FUNCTION("pb_sim_build_index()");
field_id = pb_sim_get_field_id(type);
if(db_update_index(pbs_data.db_handle, field_id, NAME_IDX, &pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
if(db_update_index(pbs_data.db_handle, field_id, NUMBER_IDX, &pb_sim_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_flush_data |
+--------------------------------------------------------------------+
PURPOSE : This function informs the SIM phonebook that SIM reading has become finished and we reached a consistent state.
*/
T_PHB_RETURN pb_sim_flush_data (void)
{
TRACE_FUNCTION("pb_sim_flush_data()");
if(db_flush(pbs_data.db_handle) EQ DB_OK)
return PHB_OK;
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_add_record |
+--------------------------------------------------------------------+
PURPOSE : Add a given record at index to the given phonebook.
*/
T_PHB_RETURN pb_sim_add_record (T_PHB_TYPE type, USHORT phy_recno, const T_PHB_RECORD *entry, T_DB_CHANGED *rec_affected)
{
USHORT field_id, ext_file_id;
UBYTE tag_len, max_tag_len;
UBYTE data[SIM_MAX_RECORD_SIZE];
UBYTE buffer[RDM_PHB_DATA_SIZE];
T_DB_INFO_FIELD info_field;
UBYTE ext_rec_cnt = 0;
UBYTE ext_rec_num1, ext_rec_num2;
int db_result,i;
TRACE_FUNCTION("pb_sim_add_record()");
/* Handling of ECC Phonebook */
if(type EQ ECC)
{
if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD))
{
phb_ecc_element[phy_recno - 1].phy_idx = phy_recno;
memcpy(phb_ecc_element[phy_recno - 1].number,entry->number, ECC_NUM_LEN);
return PHB_OK;
}
else
return PHB_FAIL;
}
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
TRACE_EVENT_P1("pb_sim_get_field_id->Field_id: %x", field_id);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
TRACE_EVENT_P1("Ext_Field_id: %x", ext_file_id);
db_result = db_info_field(pbs_data.db_handle, field_id, &info_field);
/* Get record size to calculate alpha_len for the entry */
if(db_result NEQ DB_OK)
{
TRACE_EVENT_P1("db_result = %d",db_result);
return PHB_FAIL;
}
/* Handling of LDN, LMN and LRN Phonebook records. */
if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN))
{
if(phy_recno NEQ 1)
return PHB_FAIL;
/* Read data related to LDN,LMN and LRN Phonebooks from FFS */
db_result = db_read_record(pbs_data.db_handle,
RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, buffer);
/* Check for DB Failure. */
if(db_result < DB_OK)
return PHB_FAIL;
/* Information for handling Cyclic RDM Records
----------------------------------------
buffer[0] ---> Most Recent in LDN
buffer[1] ---> Oldest in LDN
buffer[2] ---> Most Recent in LMN
buffer[3] ---> Oldest in LMN
buffer[4] ---> Most Recent in LRN
buffer[5] ---> Oldest in LRN
---------------------------------------- */
if(type EQ LDN) /* Circular entry handling for LDN */
{
buffer[0] ++;
if(buffer[0] > info_field.num_records)
buffer[0] = 1;
if(buffer[0] EQ buffer[1])
{
buffer[1]++;
if(buffer[1] > info_field.num_records)
buffer[1] = 1;
}
phy_recno = buffer[0];
if(buffer[1] EQ 0)
buffer[1] = 1;
}
if(type EQ LMN) /* Circular entry handling for LMN */
{
buffer[2]++;
if(buffer[2] > info_field.num_records)
buffer[2] = 1;
if(buffer[2] EQ buffer[3])
{
buffer[3]++;
if(buffer[3] > info_field.num_records)
buffer[3] = 1;
}
phy_recno = buffer[2];
if(buffer[3] EQ 0)
buffer[3] = 1;
}
if(type EQ LRN) /* Circular entry handling for LRN */
{
buffer[4]++;
if(buffer[4] > info_field.num_records)
buffer[4] = 1;
if(buffer[4] EQ buffer[5])
{
buffer[5]++;
if(buffer[5] > info_field.num_records)
buffer[5] = 1;
}
phy_recno = buffer[4];
if(buffer[5] EQ 0)
buffer[5] = 1;
}
TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]);
TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]);
/* Write data related to LDN,LMN and LRN Phonebooks to FFS */
db_result = db_write_record(pbs_data.db_handle,
RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, buffer);
/* Check for DB Failure. */
if(db_result < DB_OK)
return PHB_FAIL;
}/* if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN)) */
/* Convert T_PHB_TYPE into data structures as described in ETSI 11.11 */
/* Bytes Description M/O Length |
----------------------------------------------------------------------
1 to X Alpha Identifier O X bytes
X+1 Length of BCD number/SSC contents M 1 byte
X+2 TON and NPI M 1 byte
X+3 to X+12 Dialling Number/SSC String M 10 bytes
X+13 Capability/Configuration Identifier M 1 byte
X+14 Extension Record Identifier M 1 byte
-------------------------------------------------------
Extra fields for LDN, LMN, and LMN Phonebook records (As per 31.102)
-------------------------------------------------------
X+15 to X+21 Outgoing call date and time M 7 bytes
X+22 to X+24 Outgoing call duration M 3 bytes
X+26 Line of the call M 1 byte (New field added to
store line of call)
----------------------------------------------------------------------*/
tag_len = pb_sim_get_entry_len(entry->tag, PHB_MAX_TAG_LEN);
max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id);
if(tag_len > max_tag_len)
return PHB_TAG_EXCEEDED;
memset(data, 0xFF, sizeof(data));
memcpy(data, entry->tag, tag_len);
if(entry->number[10] NEQ 0xFF)
{
data[max_tag_len] = 11; /* max. length */
}
else
{
data[max_tag_len] = entry->len + 1;
}
data[max_tag_len+1] = entry->ton_npi;
memcpy((char *)&data[max_tag_len+2],
(char *)entry->number, 10);
data[max_tag_len+12] = entry->cc_id;
/* Copy data specific to records of Phonebook Types (LRN, LDN and LMN). */
if((type EQ LDN) OR (type EQ LRN) OR (type EQ LMN))
{
if(entry->v_time)
{
data[max_tag_len+14] = entry->time.year;
data[max_tag_len+15] = entry->time.month;
data[max_tag_len+16] = entry->time.day;
data[max_tag_len+17] = entry->time.hour;
data[max_tag_len+18] = entry->time.minute;
data[max_tag_len+19] = entry->time.second;
data[max_tag_len+20] = entry->time.time_zone;
data[max_tag_len+21] = (UBYTE)((entry->time.duration >> 16) & 0xff);
data[max_tag_len+22] = (UBYTE)((entry->time.duration >> 8) & 0xff);
data[max_tag_len+23] = (UBYTE)((entry->time.duration) & 0xff);
}
if(entry->v_line)
{
data[max_tag_len+24] = entry->line;
}
}
TRACE_EVENT_P1("Number = %s",entry->number);
/* Check if extension records are needed */
/* Check how many extension records are needed for number */
if(entry->number[10] NEQ 0xFF)
{
ext_rec_cnt = entry ->len - 10;
if(ext_rec_cnt % 10)
ext_rec_cnt = (ext_rec_cnt / 10) + 1;
else
ext_rec_cnt = (ext_rec_cnt / 10);
}
/* Check how many extension records are needed for subaddress */
if(entry->subaddr[0] NEQ 0xFF)
{
ext_rec_cnt++;
}
if(entry->subaddr[11] NEQ 0xFF)
{
ext_rec_cnt++;
}
TRACE_EVENT_P1("phy_recno = %d",phy_recno);
TRACE_EVENT_P2("no_rec = %d, used_rec = %d",info_field.num_records,info_field.used_records);
/* If record number is not mentioned, search for the free record and add the entry. */
if(phy_recno EQ 0)
{
db_result = db_find_free_record( pbs_data.db_handle, field_id);
/* Database is unable to find the free record. So returning PHB_FULL. */
if(db_result EQ DB_RECORD_NOT_FOUND)
return PHB_FULL;
if(db_result < DB_OK)
return PHB_FAIL;
/* Database has returned the free record number. */
phy_recno = db_result;
}
/* Write record if entry does not require extension records */
if(ext_rec_cnt EQ 0)
{
/* Write record into FFS */
if(db_write_record(pbs_data.db_handle, field_id, phy_recno, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;
/* For LDN record also write to SIM_LDN (without date and time Details */
if(type EQ LDN)
{
memset(&data[max_tag_len + pb_sim_get_size_except_tag(field_id)], 0xFF,
SIZE_DATA_DATE_TIME);
/* if(db_info_field(pbs_data.db_handle, SIM_LND, &info_field) NEQ DB_OK)
return PHB_FAIL;
if(db_write_record(pbs_data.db_handle, SIM_LND, phy_recno, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;*/
}
}
else /* We need to find free extension record. */
{
TRACE_EVENT_P1("Extension records = %d",ext_rec_cnt);
/* Search for free extension records */
/* Check whether extension file has required no. of free records. */
db_result = db_info_field(pbs_data.db_handle, ext_file_id, &info_field);
if((info_field.num_records - info_field.used_records) < ext_rec_cnt)
return PHB_FAIL;
/* Required no. of free extension records are found */
ext_rec_num1= db_find_free_record( pbs_data.db_handle,ext_file_id);
/* DB has returned non-zero positive number.
(Valid record number which is free). */
if(ext_rec_num1 > DB_OK)
{ /* Set Extension record Identifier */
data[max_tag_len+13] = ext_rec_num1;
db_result = db_info_field(pbs_data.db_handle, field_id, &info_field);
/* Write record into FFS */
if(db_write_record(pbs_data.db_handle,
field_id, phy_recno, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;
}
else
return PHB_FAIL;
db_result = db_info_field(pbs_data.db_handle, ext_file_id, &info_field);
/* Prepare extension data and write into Extension file after finding the free records. */
for(i = 0; i < ext_rec_cnt; i++)
{
pb_sim_prepare_ext_data(data, i, (UBYTE*)entry->number, entry->len, (UBYTE*)entry->subaddr);
/* Find next free record to chain the extension records. */
ext_rec_num2 = db_find_free_record( pbs_data.db_handle,ext_file_id);
/* Chain extension records and set last link to "FF" */
if(i NEQ (ext_rec_cnt - 1))
data[12] = ext_rec_num2;
/* Write extension record into FFS */
if(db_write_record(pbs_data.db_handle, ext_file_id, ext_rec_num1, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;
if(pb_sim_update_extn_records(ext_file_id, ext_rec_num1, INCREMENT) EQ PHB_FAIL)
return PHB_FAIL;
/* Preserve the previous free record number. */
ext_rec_num1 = ext_rec_num2;
}
}
/* Get information about changed records from the database. */
if(db_read_change_log(pbs_data.db_handle, rec_affected) NEQ DB_OK)
return PHB_FAIL;
if((type NEQ LDN) AND (type NEQ LMN) AND (type NEQ LRN))
{
/* Update the sorted indexes. */
if(db_update_index(pbs_data.db_handle, field_id, NAME_IDX, &pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
if(db_update_index(pbs_data.db_handle, field_id, NUMBER_IDX, &pb_sim_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
}
else
{
/* Remove RDM data record from the list */
if(rec_affected->entries NEQ 0)
{
rec_affected->entries -= 2;
/* Remove the record from the list */
memmove (&rec_affected->field_id[0],
&rec_affected->field_id[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
memmove (&rec_affected->record[0],
&rec_affected->record[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
/* Remove the record from the list */
memmove (&rec_affected->field_id[0],
&rec_affected->field_id[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
memmove (&rec_affected->record[0],
&rec_affected->record[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
/* Remove extension record from the list. */
if(ext_rec_cnt NEQ 0)
{
rec_affected->entries --;
/* Remove the record from the list */
memmove (&rec_affected->field_id[0],
&rec_affected->field_id[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
memmove (&rec_affected->record[0],
&rec_affected->record[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
}
}
}
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_del_record |
+--------------------------------------------------------------------+
PURPOSE : Delete a given record at phy_recno from the given phonebook.
*/
T_PHB_RETURN pb_sim_del_record (T_PHB_TYPE type, USHORT phy_recno, T_DB_CHANGED *rec_affected)
{
USHORT field_id, ext_file_id, db_recno;
UBYTE buffer[RDM_PHB_DATA_SIZE], rec_cnt;
T_DB_INFO_FIELD info_field;
UBYTE data[SIM_MAX_RECORD_SIZE];
TRACE_FUNCTION("pb_sim_del_record()");
/* Handling of ECC Phonebook */
if(type EQ ECC)
{
if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD))
{
phb_ecc_element[phy_recno - 1].phy_idx = 0;
memset(phb_ecc_element[phy_recno - 1].number, 0, ECC_NUM_LEN);
return PHB_OK;
}
else
return PHB_FAIL;
}
TRACE_EVENT_P1("phy_recno = %d", phy_recno);
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
/* Get no. of records in the field */
if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK)
return PHB_FAIL;
/* Information for handling Cyclic RDM Records
----------------------------------------
buffer[0] ---> Most Recent in LDN
buffer[1] ---> Oldest in LDN
buffer[2] ---> Most Recent in LMN
buffer[3] ---> Oldest in LMN
buffer[4] ---> Most Recent in LRN
buffer[5] ---> Oldest in LRN
---------------------------------------- */
/* Handling of LDN, LMN and LRN Phonebook records. */
if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN))
{
/* Read data related to LDN,LMN and LRN Phonebooks from FFS */
if(db_read_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK)
return PHB_FAIL;
if(type EQ LDN) /* Circular entry handling for LDN */
{
db_recno = buffer[0];
if(phy_recno NEQ 1)
{
for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
}
}
}
if(buffer[0] EQ buffer[1])
buffer[0] = buffer[1] = 0;
if(buffer[0] EQ db_recno)
{
buffer[0]--;
if(buffer[0] EQ 0)
buffer[0] = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, buffer[0], 0, info_field.record_size, data) < DB_OK)
{
buffer[0]--;
if(buffer[0] EQ 0)
buffer[0] = (UBYTE)info_field.num_records;
}
}
if(buffer[1] EQ db_recno)
{
buffer[1]++;
if(buffer[1] EQ info_field.num_records)
buffer[1] = 1;
while(db_read_record(pbs_data.db_handle, field_id, buffer[1], 0, info_field.record_size, data) < DB_OK)
{
buffer[1]++;
if(buffer[1] EQ info_field.num_records)
buffer[1] = 1;
}
}
}
if(type EQ LMN) /* Circular entry handling for LMN */
{
db_recno = buffer[2];
if(phy_recno NEQ 1)
{
for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
}
}
}
if(buffer[2] EQ buffer[3])
buffer[2] = buffer[3] = 0;
if(buffer[2] EQ db_recno)
{
buffer[2]--;
if(buffer[2] EQ 0)
buffer[2] = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, buffer[2], 0, info_field.record_size, data) < DB_OK)
{
buffer[2]--;
if(buffer[2] EQ 0)
buffer[2] = (UBYTE)info_field.num_records;
}
}
if(buffer[3] EQ db_recno)
{
buffer[3]++;
if(buffer[3] EQ info_field.num_records)
buffer[3] = 1;
while(db_read_record(pbs_data.db_handle, field_id, buffer[3], 0, info_field.record_size, data) < DB_OK)
{
buffer[3]++;
if(buffer[3] EQ info_field.num_records)
buffer[3] = 1;
}
}
}
if(type EQ LRN) /* Circular entry handling for LRN */
{
db_recno = buffer[4];
if(phy_recno NEQ 1)
{
for(rec_cnt = 0; rec_cnt < (phy_recno - 1) ; rec_cnt++)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK)
{
db_recno--;
if(db_recno EQ 0)
db_recno = (UBYTE)info_field.num_records;
}
}
}
if(buffer[4] EQ buffer[5])
buffer[4] = buffer[5] = 0;
if(buffer[4] EQ db_recno)
{
buffer[4]--;
if(buffer[4] EQ 0)
buffer[4] = (UBYTE)info_field.num_records;
while(db_read_record(pbs_data.db_handle, field_id, buffer[4], 0, info_field.record_size, data) < DB_OK)
{
buffer[4]--;
if(buffer[4] EQ 0)
buffer[4] = (UBYTE)info_field.num_records;
}
}
if(buffer[5] EQ db_recno)
{
buffer[5]++;
if(buffer[5] EQ info_field.num_records)
buffer[5] = 1;
while(db_read_record(pbs_data.db_handle, field_id, buffer[5], 0, info_field.record_size, data) < DB_OK)
{
buffer[5]++;
if(buffer[5] EQ info_field.num_records)
buffer[5] = 1;
}
}
}
TRACE_EVENT_P1("db_recno = %d ", db_recno);
TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]);
TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]);
/* Write data related to LDN,LMN and LRN Phonebooks to FFS */
if(db_write_record(pbs_data.db_handle, RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK)
return PHB_FAIL;
}
else
{
db_recno = phy_recno;
}
/* Delete extension records if not referenced. */
if(pb_sim_read_ext_record_for_delete(type, field_id, db_recno) EQ PHB_FAIL)
return PHB_FAIL;
/* Delete record from FFS. */
if(db_delete_record(pbs_data.db_handle, field_id,db_recno) NEQ DB_OK)
return PHB_FAIL;
/* Get information about changed records from the database. */
if(db_read_change_log(pbs_data.db_handle, rec_affected) NEQ DB_OK)
return PHB_FAIL;
if((type NEQ LDN) AND (type NEQ LMN) AND (type NEQ LRN))
{
/* Update the sorted indexes. */
if(db_update_index(pbs_data.db_handle, field_id, NAME_IDX, &pb_sim_alpha_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
if(db_update_index(pbs_data.db_handle, field_id, NUMBER_IDX, &pb_sim_number_cmp, PHB_MATCH_PARTIAL) NEQ DB_OK)
return PHB_FAIL;
}
else
{
if(rec_affected->entries NEQ 0)
{
/* Remove RDM data record from the list */
rec_affected->entries -= 2;
/* Remove the record from the list */
memmove (&rec_affected->field_id[0],
&rec_affected->field_id[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
memmove (&rec_affected->record[0],
&rec_affected->record[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
/* Remove the record from the list */
memmove (&rec_affected->field_id[0],
&rec_affected->field_id[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
memmove (&rec_affected->record[0],
&rec_affected->record[1],
sizeof (USHORT) * (DB_MAX_AFFECTED - 1));
}
TRACE_EVENT_P1("rec-affected = %d", rec_affected->entries);
}
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_record |
+--------------------------------------------------------------------+
PURPOSE : Read a given physical record from the flash based phonebook.
*/
T_PHB_RETURN pb_sim_read_record (T_PHB_TYPE type, USHORT phy_recno, T_PHB_RECORD *entry)
{
USHORT field_id, ext_file_id;
USHORT db_recno;
T_DB_INFO_FIELD info_field;
UBYTE buffer[RDM_PHB_DATA_SIZE];
UBYTE data[SIM_MAX_RECORD_SIZE], *ptr;
UBYTE max_tag_len;
UBYTE ext_rcd_num;
TRACE_FUNCTION("pb_sim_read_record()");
/* Handling of ECC Phonebook */
if(type EQ ECC)
{
if((phy_recno > 0 ) AND (phy_recno <= MAX_ECC_RCD))
{
entry->phy_recno = phy_recno;
memcpy(entry->number, phb_ecc_element[phy_recno - 1].number, ECC_NUM_LEN);
return PHB_OK;
}
else
return PHB_FAIL;
}
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
/* Read record from the database. */
if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK)
return PHB_FAIL;
/* Information for handling Cyclic RDM Records
----------------------------------------
buffer[0] ---> Most Recent in LDN
buffer[1] ---> Oldest in LDN
buffer[2] ---> Most Recent in LMN
buffer[3] ---> Oldest in LMN
buffer[4] ---> Most Recent in LRN
buffer[5] ---> Oldest in LRN
---------------------------------------- */
/* Handling of LDN, LMN and LRN Phonebook records. */
if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN))
{
/* Read data related to LDN,LMN and LRN Phonebooks from FFS */
if(db_read_record(pbs_data.db_handle,
RDM_DATA_FILE_ID, 1, 0, RDM_PHB_DATA_SIZE, (UBYTE *) buffer) < DB_OK)
return PHB_FAIL;
/* Since LDN, LMN and LRN records are circular entries,
most recent will be the 1st record and
entries increase towards the oldest one for Reading. */
if(type EQ LDN)
{
if(buffer[0] EQ 0)
buffer[0] = 1;
db_recno = buffer[0] - phy_recno + 1;
db_recno = db_recno % (info_field.num_records);
if(db_recno EQ 0)
db_recno = (info_field.num_records);
}
if(type EQ LMN)
{
if(buffer[2] EQ 0)
buffer[2] = 1;
db_recno = buffer[2] - phy_recno + 1;
db_recno = db_recno % (info_field.num_records);
if(db_recno EQ 0)
db_recno = (info_field.num_records);
}
if(type EQ LRN)
{
if(buffer[4] EQ 0)
buffer[4] = 1;
db_recno = buffer[4] - phy_recno + 1;
db_recno = db_recno % (info_field.num_records);
if(db_recno EQ 0)
db_recno = (info_field.num_records);
}
}
else
db_recno = phy_recno;
TRACE_EVENT_P2("db_recno = %d phy_recno = %d",db_recno, phy_recno);
TRACE_EVENT_P3("%d %d %d", buffer[0], buffer[1],buffer[2]);
TRACE_EVENT_P3("%d %d %d", buffer[3], buffer[4],buffer[5]);
if(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;
/* Convert SIM data to the type T_PHB_RECORD. */
ptr = data;
max_tag_len = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id), PHB_MAX_TAG_LEN);
entry->phy_recno = phy_recno;
entry->tag_len = (UBYTE)pb_sim_get_entry_len(ptr, max_tag_len);
memset(entry->tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */
memcpy ( (char*)entry->tag, (char*)ptr, entry->tag_len );
ptr += (info_field.record_size) - pb_sim_get_size_except_tag(field_id);
max_tag_len = (info_field.record_size) - pb_sim_get_size_except_tag(field_id);
entry->len = *ptr - 1;
++ptr;
entry->ton_npi = *ptr;
++ptr;
memset(entry->number, 0xFF, PHB_PACKED_NUM_LEN);
memcpy( (char*)entry->number, (char*)ptr, entry->len );
ptr += 10;
entry->cc_id = *ptr;
++ptr;
/* Copy data specific to records of LDN, LMN, and LRN phonebook types. */
if((type EQ LDN) OR (type EQ LMN) OR (type EQ LRN))
{
entry->v_time = 1;
entry->time.year=data[max_tag_len+14] ;
entry->time.month=data[max_tag_len+15];
entry->time.day=data[max_tag_len+16];
entry->time.hour=data[max_tag_len+17] ;
entry->time.minute= data[max_tag_len+18];
entry->time.second=data[max_tag_len+19] ;
entry->time.time_zone=data[max_tag_len+20];
entry->time.duration = (data[max_tag_len+21] << 16) +
(data[max_tag_len+22] << 8) +
(data[max_tag_len+23] );
entry->v_line = 1;
entry->line=data[max_tag_len+24];
}
if (*ptr NEQ 0xFF) /* check for extention records */
{
ext_rcd_num =(UBYTE)*ptr;
if(db_info_field(pbs_data.db_handle, ext_file_id, &info_field) NEQ DB_OK)
return PHB_FAIL;
/* Reset pointer to start location. */
ptr = data;
memset(ptr, 0xFF, info_field.record_size);
if(db_read_record(pbs_data.db_handle, ext_file_id, ext_rcd_num, 0, info_field.record_size, ptr) < DB_OK)
return PHB_FAIL;
pb_sim_read_ext(ptr, entry);
while(*(ptr + 12) NEQ 0xFF) /* check if a further EXT entry exists */
{
memset(ptr, 0xFF, info_field.record_size);
db_read_record(pbs_data.db_handle, ext_file_id, (USHORT)*(ptr+12), 0, info_field.record_size,ptr);
pb_sim_read_ext(ptr, entry);
}
}
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_alpha_record |
+--------------------------------------------------------------------+
PURPOSE : Read a given physical record from the flash based phonebook in alphabetical order.
*/
T_PHB_RETURN pb_sim_read_alpha_record (T_PHB_TYPE type, USHORT order_num, T_PHB_RECORD *entry)
{
int db_result;
USHORT field_id, ext_file_id;
TRACE_FUNCTION("pb_sim_read_alpha_record()");
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
/* Read record from the FFS. */
db_result = db_get_phy_from_idx(pbs_data.db_handle, field_id, NAME_IDX, order_num);
if(db_result > DB_OK)
{
return pb_sim_read_record(type, (USHORT)db_result, entry) ;
}
/* Check whether index is vaild. */
if(db_result EQ DB_INVALID_INDEX)
return PHB_INVALID_IDX;
/* Unable to get record from the database. Hence returning PHB_FAIL. */
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_number_record |
+--------------------------------------------------------------------+
PURPOSE : Read a given physical record from the flash based phonebook in number sorted order.
*/
T_PHB_RETURN pb_sim_read_number_record (T_PHB_TYPE type, USHORT order_num, T_PHB_RECORD *entry)
{
int db_result;
USHORT field_id, ext_file_id;
TRACE_FUNCTION("pb_sim_read_number_record()");
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
/* Read record from the FFS. */
db_result = db_get_phy_from_idx(pbs_data.db_handle, field_id, NUMBER_IDX, order_num);
if(db_result > DB_OK)
{
return pb_sim_read_record(type, (USHORT)db_result, entry) ;
}
else if(db_result EQ DB_INVALID_INDEX)
return PHB_INVALID_IDX;
else
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_search_name |
+--------------------------------------------------------------------+
PURPOSE : Finds the first entry matching the search tag.
*/
T_PHB_RETURN pb_sim_search_name (T_PHB_TYPE type, T_PHB_MATCH match, const T_ACI_PB_TEXT *search_tag, SHORT *order_num)
{
T_ACI_PB_TEXT key;
int res;
USHORT field_id, ext_file_id;
TRACE_FUNCTION("pb_sim_search_name()");
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
key.len = search_tag->len;
key.cs = search_tag->cs;
pb_sim_cvt_alpha_for_cmp ((UBYTE*) search_tag->data, (UBYTE*) key.data, search_tag->len);
res = db_search(pbs_data.db_handle, field_id, NAME_IDX, (UBYTE*) order_num, pb_sim_search_alpha_func, match, (const UBYTE*)&key);
if(res > DB_OK)
{
return PHB_OK;
}
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_search_number |
+--------------------------------------------------------------------+
PURPOSE : Finds the first entry matching the number.
*/
T_PHB_RETURN pb_sim_search_number (T_PHB_TYPE type, const UBYTE *number, SHORT *order_num)
{
int res, i;
CHAR cur_number[MAX_PHB_NUM_LEN];
CHAR rev_number[MAX_PHB_NUM_LEN];
int cmpLen, cmp_res;
USHORT field_id, ext_file_id;
TRACE_FUNCTION("pb_sim_search_number()");
/* Handling for ECC Phonebook. */
if(type EQ ECC)
{
for(i = 0; i < pbs_data.max_record[ECC]; i++)
{
cmhPHB_getAdrStr(cur_number, MAX_PHB_NUM_LEN - 1,phb_ecc_element[i].number,pbs_data.record_size[ECC]);
pb_sim_revString(cur_number);
strcpy( rev_number,(const char*)number);
pb_sim_revString(rev_number);
cmpLen = MINIMUM(strlen((const char*) cur_number), strlen((const char*)number));
cmp_res = pb_sim_cmpString((UBYTE*)cur_number, (UBYTE*)rev_number, cmpLen);
if(cmp_res NEQ 0)
return PHB_FAIL;
else
{
return PHB_OK;
}
}
}
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
TRACE_EVENT_P2("type = %d field_id = %x", type, field_id);
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
res = db_search(pbs_data.db_handle, field_id, NUMBER_IDX, (UBYTE*)order_num, &pb_sim_search_num_func, PHB_MATCH_PARTIAL, number);
if(res > DB_OK)
{
return PHB_OK;
}
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_sizes |
+--------------------------------------------------------------------+
PURPOSE : Reads the sizes of a given phonebook.
*/
T_PHB_RETURN pb_sim_read_sizes (T_PHB_TYPE type, SHORT *max_rcd, SHORT *used_rcd, UBYTE *tag_len)
{
T_DB_INFO_FIELD info_field;
USHORT field_id;
int db_result;
TRACE_FUNCTION("pb_sim_read_sizes()");
/* Handling for ECC Phonebook */
if(type EQ ECC)
{
*max_rcd = pbs_data.max_record[ECC];
*used_rcd = pbs_data.used_record[ECC];
*tag_len = 0; /* To Do:Alpha tag will not be there for ECC. So assigning zero here */
return PHB_OK;
}
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
db_result = db_info_field(pbs_data.db_handle, field_id, &info_field);
TRACE_EVENT_P1("db_result = %d", db_result);
if(db_result EQ DB_OK)
{
*max_rcd = info_field.num_records;
*used_rcd = info_field.used_records;
*tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id);
return PHB_OK;
}
return PHB_FAIL;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_get_entry_len |
+--------------------------------------------------------------------+
PURPOSE : Used to get the length in bytes of a given entry which is coded as given in 11.11 Annex B.
*/
int pb_sim_get_entry_len (const UBYTE *pb_tag, UBYTE max_pb_len)
{
int pb_len = 0;
UBYTE inc_count = 1;
BOOL ucs2 = FALSE;
UBYTE chars = 0;
TRACE_FUNCTION("pb_sim_get_entry_len()");
if (*pb_tag EQ 0x80)
{
ucs2 = TRUE;
inc_count = 2; /* check two bytes */
pb_len = 1; /* skip the 0x80 */
}
else if (*pb_tag EQ 0x81 OR *pb_tag EQ 0x82)
{
if (*pb_tag EQ 0x81)
pb_len = 3; /* 0x80 + len + pointer */
else
pb_len = 4; /* 0x80 + len + 2xpointer */
chars = pb_tag[1];
pb_tag += pb_len; /* go to data */
while (chars)
{
if (*pb_tag++ & 0x80)
pb_len+=2;
else
pb_len+=1;
pb_tag++;
chars--;
}
return MINIMUM(pb_len,max_pb_len);
}
while (pb_len < max_pb_len)
{
if (ucs2 EQ TRUE)
{
if (!(pb_len+1 < max_pb_len)) /* Check also if we traverse the upper bound */
break; /* so only a "half" UCS2 element is remaining */
}
if (pb_tag[pb_len] EQ 0xFF)
{
/* one 0xFF indicates the end of a non UCS2 string */
if (ucs2 EQ FALSE)
{
break;
}
/* two 0xFF indicates the end of a UCS2 string */
if (pb_tag[pb_len + 1] EQ 0xFF)
{
break;
}
}
pb_len += inc_count;
}
return (pb_len);
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_alpha_cmp |
+--------------------------------------------------------------------+
PURPOSE : Compares alpha identifier of two records.
*/
int pb_sim_alpha_cmp (int db_handle, USHORT field_id, USHORT recno_1, USHORT recno_2, ULONG flags)
{
T_PHB_RECORD entry_1,entry_2;
UBYTE cmpLen = 0;
UBYTE *buffer;
UBYTE max_tag_len;
UBYTE cur_tag[PHB_MAX_TAG_LEN], check_tag[PHB_MAX_TAG_LEN];
int cmp_res;
T_DB_INFO_FIELD info_field;
TRACE_FUNCTION("pb_sim_alpha_cmp()");
db_info_field(db_handle, field_id, &info_field);
MALLOC(buffer, info_field.record_size);
/* Read the first record. */
db_read_record(db_handle, field_id, recno_1, 0, info_field.record_size, buffer);
/* Unpack record 1 to do a string comparison on the alpha identifier field */
max_tag_len = MINIMUM ( (info_field.record_size) - pb_sim_get_size_except_tag(field_id),
PHB_MAX_TAG_LEN);
entry_1.tag_len = (UBYTE)pb_sim_get_entry_len(buffer, max_tag_len);
memset(entry_1.tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */
memcpy ( (char*)entry_1.tag, (char*)buffer, entry_1.tag_len );
pb_sim_cvt_alpha_for_cmp ( entry_1.tag, cur_tag, entry_1.tag_len );
memset(buffer, 0, info_field.record_size);
/* Read the second record. */
db_read_record(db_handle, field_id, recno_2, 0, info_field.record_size, buffer);
/* Unpack record 2 to do a string comparison on the alpha identifier field */
max_tag_len = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id),
PHB_MAX_TAG_LEN);
entry_2.tag_len = (UBYTE)pb_sim_get_entry_len(buffer, max_tag_len);
memset(entry_2.tag, 0xFF, PHB_MAX_TAG_LEN); /* init the tag value */
memcpy ( (char*)entry_2.tag, (char*)buffer, entry_2.tag_len );
pb_sim_cvt_alpha_for_cmp ( entry_2.tag, check_tag, entry_2.tag_len );
cmpLen = MINIMUM ( entry_1.tag_len,
entry_2.tag_len );
TRACE_EVENT_P1("%d", cmpLen);
cmp_res = pb_sim_cmpString ( cur_tag, check_tag, cmpLen );
if (cmp_res EQ 0)
{
/* Correct result when length was different, ACIPHB201 */
if (entry_1.tag_len < entry_2.tag_len)
cmp_res = -1;
else if (entry_1.tag_len > entry_2.tag_len)
cmp_res = 1;
}
MFREE(buffer);
return cmp_res;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_number_cmp |
+--------------------------------------------------------------------+
PURPOSE : Compares two numbers of two records.
*/
int pb_sim_number_cmp (int db_handle,
USHORT field_id,
USHORT recno_1,
USHORT recno_2,
ULONG flags)
{
T_PHB_RECORD entry_1,entry_2;
T_DB_INFO_FIELD info_field;
UBYTE cmpLen = 0;
UBYTE *buffer, *tmp_buffer;
UBYTE ext_rcd_num;
UBYTE max_tag_len;
CHAR cur_number[MAX_PHB_NUM_LEN];
CHAR ref_number[MAX_PHB_NUM_LEN];
int cmp_res;
USHORT file_id;
TRACE_FUNCTION("pb_sim_number_cmp()");
MALLOC(buffer, sizeof(T_PHB_RECORD));
/* Store pointer to free the memory allocation. */
tmp_buffer = buffer;
memset(buffer,0xFF,sizeof(T_PHB_RECORD));
db_info_field(db_handle, field_id, &info_field);
/* Read record recno_1 from the database using db_read_record() */
db_read_record(db_handle, field_id, recno_1, 0, info_field.record_size, buffer);
/* Read only number from the buffer. */
buffer += (info_field.record_size) - pb_sim_get_size_except_tag(field_id);
entry_1.len = *(buffer++) - 1;
entry_1.ton_npi = *buffer++;
memset(entry_1.number, 0xFF, PHB_PACKED_NUM_LEN);
memcpy( (char*)entry_1.number, (char*)buffer, entry_1.len );
buffer += 10;
entry_1.cc_id = *buffer++;
if (*buffer != 0xFF) /* check for extention records */
{
file_id = pb_sim_get_ext_file_id(field_id);
if (file_id != 0xFFFF)
{
ext_rcd_num = (UBYTE)*buffer;
db_info_field(db_handle, file_id, &info_field);
/* Set the buffer to starting location. */
buffer = tmp_buffer;
memset(buffer, 0xFF, info_field.record_size);
db_read_record(db_handle, file_id, ext_rcd_num, 0, info_field.record_size,buffer);
pb_sim_read_ext(buffer, &entry_1);
while(*(buffer + 12) NEQ 0xFF)
{
memset(buffer, 0xFF, info_field.record_size);
db_read_record(db_handle, file_id, *(buffer + 12), 0, info_field.record_size,buffer);
pb_sim_read_ext(buffer, &entry_1);
}
}
}
/* Set the buffer to starting location. */
buffer = tmp_buffer;
memset(buffer, 0xFF, sizeof(T_PHB_RECORD));
/* Read record recno_2 from the database using db_read_record() */
db_read_record(db_handle, field_id, recno_2, 0, info_field.record_size, buffer);
max_tag_len = info_field.record_size - pb_sim_get_size_except_tag(field_id);
/* Read only number from the buffer. */
buffer += max_tag_len;
entry_2.len = *(buffer++) - 1;
entry_2.ton_npi = *buffer++;
memset(entry_2.number, 0xFF, PHB_PACKED_NUM_LEN);
memcpy( (char*)entry_2.number, (char*)buffer, entry_2.len );
buffer += 10;
entry_2.cc_id = *buffer++;
if (*buffer != 0xFF) /* check for extention records */
{
if (file_id != 0xFFFF)
{
ext_rcd_num = (UBYTE)*buffer;
/* Set the buffer to starting location. */
buffer = tmp_buffer;
memset(buffer, 0xFF,info_field.record_size);
db_read_record(db_handle, file_id, ext_rcd_num, 0, info_field.record_size,buffer);
pb_sim_read_ext(buffer, &entry_2);
while(*(buffer + 12) NEQ 0xFF)
{
memset(buffer, 0xFF,info_field.record_size);
db_read_record(db_handle, file_id, *(buffer + 12), 0, info_field.record_size,buffer);
pb_sim_read_ext(buffer, &entry_2);
}
}
}
cmhPHB_getAdrStr(cur_number,
MAX_PHB_NUM_LEN - 1,
entry_1.number,
entry_1.len);
cmhPHB_getAdrStr(ref_number,
MAX_PHB_NUM_LEN - 1,
entry_2.number,
entry_2.len);
/* Reverse the first number to compare number from right. */
pb_sim_revString(cur_number);
/* Reverse the second number to compare number from right. */
pb_sim_revString(ref_number);
cmp_res = strcmp((char *)cur_number, (char *)ref_number);
MFREE(tmp_buffer);
return cmp_res;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_read_ext |
+--------------------------------------------------------------------+
PURPOSE : Reads extension records from the database and copies them to number.
*/
/* Extesion records will be stored as per 11.11.
Bytes Description M/O Length
--------------------------------------
1 Record type M 1 byte
2 to 12 Extension data M 11 bytes
13 Identifier M 1 byte
--------------------------------------*/
void pb_sim_read_ext(UBYTE *buffer, T_PHB_RECORD *entry)
{
UBYTE data_len;
UBYTE data_type;
UBYTE *data;
TRACE_FUNCTION("pb_sim_read_ext()");
/* If this extension record is not empty, it is written in phonebook. */
data = buffer;
data_type = *data;
data_len = *(data+1);
switch (data_type)
{
case 1: /* Called Party Subaddress */
{
int sa_len = 0;
while (sa_len<PHB_PACKED_NUM_LEN) /* get length of possible already stored subaddr if more than one EXT is used */
{
if (entry->subaddr[sa_len] EQ 0xFF)
break;
else if ((entry->subaddr[sa_len] & 0xF0) EQ 0xF0)
{
sa_len++;
break;
}
else
sa_len++;
}
pb_sim_nibblecopy (entry->subaddr,
sa_len,
data + 2,
data_len);
}
break;
case 2: /* Additional data */
entry->len =
pb_sim_nibblecopy (entry->number,
entry->len,
data + 2,
data_len);
break;
default: /* unknown type */
break;
}
return;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_revString |
+--------------------------------------------------------------------+
PURPOSE : Reverses a string within the same variable.
*/
void pb_sim_revString(char *str)
{
UBYTE i, j,str_len;
char ch;
TRACE_FUNCTION("pb_sim_revString()");
str_len = strlen(str);
for(i = 0, j = str_len - 1;i < (str_len / 2); i++, j--)
{
ch = *(str + i);
*(str + i) = *(str + j);
*(str + j) = ch;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_search_alpha_func |
+--------------------------------------------------------------------+
PURPOSE : Searches for a given alpha key in the database.
*/
int pb_sim_search_alpha_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num)
{
T_ACI_PB_TEXT *search_key;
T_PHB_RECORD entry;
UBYTE cmpLen = 0;
T_PHB_TYPE phb_type;
UBYTE cur_tag[PHB_MAX_TAG_LEN];
int cmp_res;
TRACE_FUNCTION("pb_sim_search_alpha_func()");
/* Cast search key to appropriate data structure */
search_key = (T_ACI_PB_TEXT *)key;
/* Get PHB type from field ID using PHB_ACI function. */
phb_type = pb_get_phb_type_from_ef(field_id);
/* Read record from the database. */
pb_sim_read_record(phb_type, rec_num, &entry);
pb_sim_cvt_alpha_for_cmp ( entry.tag, cur_tag, entry.tag_len );
cmpLen = search_key->len;
if(flags EQ PHB_MATCH_PARTIAL)
cmpLen = MINIMUM ( entry.tag_len, cmpLen);
TRACE_EVENT_P1( "cmpLen=%d", cmpLen );
cmp_res = pb_sim_cmpString ( cur_tag, search_key->data, cmpLen );
return cmp_res;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_search_num_func |
+--------------------------------------------------------------------+
PURPOSE : Searches for a given number key in the database.
*/
int pb_sim_search_num_func(ULONG flags, const UBYTE *key, int db_handle, USHORT field_id, USHORT rec_num)
{
T_PHB_RECORD entry;
UBYTE cmpLen = 0;
T_PHB_TYPE phb_type;
CHAR cur_number[MAX_PHB_NUM_LEN];
CHAR rev_key[MAX_PHB_NUM_LEN];
int cmp_res;
TRACE_FUNCTION("pb_sim_search_num_func()");
/* Get PHB type from field ID using PHB_ACI function. */
phb_type = pb_get_phb_type_from_ef(field_id);
/* Read record from the database. */
if(pb_sim_read_record(phb_type, rec_num, &entry) NEQ PHB_OK)
return -1;
cmhPHB_getAdrStr(cur_number,
MAX_PHB_NUM_LEN - 1,
entry.number,
entry.len);
/* Reverse the first number to compare number from right. */
pb_sim_revString(cur_number);
/* Reverse the second number to compare number from right. */
strcpy (rev_key, (const char*) key);
pb_sim_revString(rev_key);
cmpLen = strlen(rev_key);
if(flags EQ PHB_MATCH_PARTIAL)
cmpLen = MINIMUM(strlen(cur_number), cmpLen);
TRACE_EVENT_P1("Number to be compared: %s", cur_number);
TRACE_EVENT_P1("Number to be searched: %s", rev_key);
cmp_res = pb_sim_cmpString((UBYTE*)cur_number, (UBYTE*)rev_key, 7);
TRACE_EVENT_P1("Result of the comparison: %d", cmp_res);
return cmp_res;
}
/*
+--------------------------------------------------------------------+
| PROJECT: MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE: pb_sim_nibblecopy |
+--------------------------------------------------------------------+
PURPOSE : Used to convert BCD nibbles to string.
*/
LOCAL int pb_sim_nibblecopy (UBYTE dest[], int destlen, UBYTE src[], int count)
{
int i;
int nibble;
int destnibble=destlen*2;
TRACE_FUNCTION("pb_sim_nibblecopy()");
if (destnibble)
{
if ((dest[destlen-1] & 0xF0) == 0xF0) /* check if there is space in last nibble */
destnibble--;
}
for ( i=0; i<count*2; i++ )
{
/* check if we access out of bounds */
if (destnibble/2 >= PHB_PACKED_NUM_LEN)
return PHB_PACKED_NUM_LEN;
/* get nibble */
if (i%2 == 0)
nibble = src[i/2] & 0x0F;
else
nibble = (src[i/2] & 0xF0) >> 4;
if (nibble == 0xF) /* end of number detected */
break;
/* put nibble */
if (destnibble%2 == 0)
{
dest[destnibble/2] &= 0xF0;
dest[destnibble/2] |= nibble;
}
else
{
dest[destnibble/2] &= 0x0F;
dest[destnibble/2] |= nibble << 4;
}
destnibble++;
}
return destnibble/2 + destnibble%2; /* round up */
}
/*
+------------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE: PHB |
| STATE : code ROUTINE : pb_sim_read_eeprom_ecc |
+------------------------------------------------------------------------+
PURPOSE : Read EC number from EEPROM.
*/
LOCAL void pb_sim_read_eeprom_ecc (void)
{
EF_ECC efecc;
UBYTE *data_ptr;
UBYTE version;
int rec_ctr;
TRACE_FUNCTION("pb_sim_read_eeprom_ecc()");
/* Initialise ECC Phonebook Info. */
pbs_data.max_record[ECC] = MAX_ECC_RCD;
pbs_data.used_record[ECC] = 0;
if (pcm_ReadFile((UBYTE *)EF_ECC_ID,
SIZE_EF_ECC,
(UBYTE *)&efecc,
&version) EQ DRV_OK)
{
{ /* workaround when invalid data stored on PCM */
CHAR ecc_number[MAX_PHB_NUM_LEN];
int num_len;
data_ptr = efecc.ecc1;
for (rec_ctr=0; rec_ctr < pbs_data.max_record[ECC]; rec_ctr++)
{
if (*data_ptr NEQ 0xFF)
{
cmhPHB_getAdrStr (ecc_number,
MAX_PHB_NUM_LEN - 1,
data_ptr,
ECC_NUM_LEN);
for (num_len = 0; num_len < ECC_NUM_LEN; num_len++)
{
if (!isdigit (ecc_number[num_len]))
{
TRACE_EVENT_P2 ("[ERR] pb_read_eeprom_ecc(): invalid character found %c (%d)",
ecc_number[num_len], rec_ctr);
return;
}
}
}
data_ptr += ECC_NUM_LEN;
}
} /* workaround end */
data_ptr = &efecc.ecc1[0];
memset( phb_ecc_element,0, (pbs_data.max_record[ECC] * sizeof(T_PHB_ECC_RECORD)) );
for (rec_ctr=0; rec_ctr < pbs_data.max_record[ECC]; rec_ctr++)
{
if(*data_ptr NEQ 0xff)
{
phb_ecc_element[rec_ctr].phy_idx = rec_ctr + 1;
memcpy(phb_ecc_element[rec_ctr].number, data_ptr, ECC_NUM_LEN);
data_ptr += ECC_NUM_LEN;
(pbs_data.used_record[ECC])++;
}
}
}
}
/*
+----------------------------------------------------------------------+
| PROJECT : MODULE : PHB |
| STATE : code ROUTINE : pb_sim_prepare_ext_data |
+----------------------------------------------------------------------+
PURPOSE : Prepare the data for the extention record.
If NULL pointer is given for number and subaddress
then the extention record will marked as unused
*/
/* Extesion records will be stored as per 11.11.
Bytes Description M/O Length
--------------------------------------
1 Record type M 1 byte
2 to 12 Extension data M 11 bytes
13 Identifier M 1 byte
--------------------------------------*/
LOCAL void pb_sim_prepare_ext_data(UBYTE *ext_data, int ext_count, UBYTE *number, UBYTE no_len, UBYTE *subaddr)
{
UBYTE *data_num = NULL;
UBYTE *data_subadd = NULL;
TRACE_FUNCTION("pb_sim_prepare_ext_data()");
if(number[10] NEQ 0xFF)
data_num = number + ((ext_count + 1) * 10);
data_subadd = subaddr + (ext_count * 11);
memset(ext_data, 0xFF, sizeof(ext_data));
if ((data_num NEQ NULL) AND (*data_num NEQ 0xFF))
{
/* Set record type to 2 which corresponds to Additional data. Record type as per 11.11 */
ext_data[0] = 2;
ext_data[1] = no_len - ((ext_count + 1) * 10);
memcpy (ext_data + 2, data_num, 10);
}
else if ((data_subadd NEQ NULL) AND (*data_subadd NEQ 0xFF))
{
TRACE_EVENT ("SUBADDRESS EXTENTION");
/* Set record type to 1 which corresponds to Called Party Subaddress. Record type as per 11.11 */
ext_data[0] = 1;
memcpy (ext_data + 1, data_subadd, 11);
}
}
/*
+----------------------------------------------------------------------+
| PROJECT : MODULE : PHB |
| STATE : code ROUTINE : pb_sim_get_field_id |
+----------------------------------------------------------------------+
PURPOSE : Returns field ID for the corresponding Phonebook type.
*/
LOCAL USHORT pb_sim_get_field_id (T_PHB_TYPE type)
{
USHORT field_id;
TRACE_FUNCTION("pb_sim_get_field_id()");
/* Get Elementary file ID for the Phonebook type. */
switch(type)
{
case ADN:
field_id = SIM_ADN;
break;
case LDN:
field_id = SIM_OCI;
break;
case LRN:
field_id = FFS_LRN;
break;
case LMN:
field_id = FFS_LMN;
break;
case UPN:
field_id = SIM_MSISDN;
break;
case FDN:
field_id = SIM_FDN;
break;
case SDN:
field_id = SIM_SDN;
break;
case BDN:
field_id = SIM_BDN;
break;
default:
TRACE_ERROR ("No such field");
field_id = 0;
break;
}
return field_id;
}
/*
+----------------------------------------------------------------------+
| PROJECT : MODULE : PHB |
| STATE : code ROUTINE : pb_sim_get_ext_file |
+----------------------------------------------------------------------+
PURPOSE : Returns field ID for the corresponding Phonebook type.
*/
LOCAL USHORT pb_sim_get_ext_file (T_PHB_TYPE type)
{
USHORT ext_file_id;
TRACE_FUNCTION("pb_sim_get_ext_file()");
/* Get Extension Elementary file ID for the Phonebook type. */
switch(type)
{
case ADN:
case UPN:
ext_file_id = SIM_EXT1;
break;
case FDN:
ext_file_id = SIM_EXT2;
break;
case SDN:
ext_file_id = SIM_EXT3;
break;
case BDN:
ext_file_id = SIM_EXT4;
break;
case LDN:
ext_file_id = SIM_EXT5;
break;
case LRN:
ext_file_id = FFS_EXT_LRN;
break;
case LMN:
ext_file_id = FFS_EXT_LMN;
break;
default:
ext_file_id = 0; /* Avoid lint warning */
break;
}
return ext_file_id;
}
/*
+---------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_cvt_alpha_for_cmp |
+---------------------------------------------------------------------+
PURPOSE : convert alpha to lower case when not unicode
*/
LOCAL void pb_sim_cvt_alpha_for_cmp ( UBYTE *src,
UBYTE *dst,
UBYTE len )
{
int i;
TRACE_FUNCTION("pb_sim_cvt_alpha_for_cmp()");
if (*src NEQ 0x80) /* 11.11 Annex B 0x80 is the UCS2 indicator */
{
for ( i = 0; i < len; i++ )
dst[i] = (UBYTE)tolower((int)src[i]);
}
else
{
memcpy (dst, src, len);
}
}
/*
+----------------------------------------------------------------------+
| PROJECT : MODULE : PHB |
| STATE : code ROUTINE : pb_sim_get_ext_file_id |
+----------------------------------------------------------------------+
PURPOSE : Returns Extension field ID for the corresponding field ID of a Phonebook.
*/
LOCAL USHORT pb_sim_get_ext_file_id (USHORT field_id)
{
USHORT ext_file_id;
TRACE_FUNCTION("pb_sim_get_ext_file_id()");
/* Get Extension Elementary file ID for the Phonebook type. */
switch(field_id)
{
case SIM_ADN:
case SIM_LND:
case SIM_MSISDN:
ext_file_id = SIM_EXT1;
break;
case SIM_FDN:
ext_file_id = SIM_EXT2;
break;
case SIM_SDN:
ext_file_id = SIM_EXT3;
break;
case SIM_BDN:
ext_file_id = SIM_EXT4;
break;
case SIM_OCI:
ext_file_id = SIM_EXT5;
break;
case FFS_LRN:
ext_file_id = FFS_EXT_LRN;
break;
case FFS_LMN:
ext_file_id = FFS_EXT_LMN;
break;
default:
ext_file_id = 0; /* Avoid lint warning */
break;
}
return ext_file_id;
}
/*
+----------------------------------------------------------------------+
| PROJECT : MODULE : PHB |
| STATE : code ROUTINE : pb_sim_find_free_record |
+----------------------------------------------------------------------+
PURPOSE : Returns free record number for the Phonebook type.
*/
GLOBAL int pb_sim_find_free_record (T_PHB_TYPE type)
{
int db_result;
unsigned i;
USHORT field_id;
TRACE_FUNCTION("pb_sim_find_free_record()");
switch (type)
{
case ECC: /* ECC not stored in DB, special handling */
for (i = 0; i < pbs_data.max_record[ECC]; i++)
{
if (phb_ecc_element[i].phy_idx EQ 0)
return i + 1;
}
return 0; /* No free record found */
case LDN:
case LRN:
case LMN:
return 1; /* For cyclic entries always the first */
default:
/* Get Elementary file ID for the Phonebook type. */
field_id = pb_sim_get_field_id(type);
db_result = db_find_free_record(pbs_data.db_handle, field_id);
if (db_result <= 0)
return 0; /* No free record */
return db_result;
}
}
/*
+-------------------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_get_size_except_tag |
+-------------------------------------------------------------------------------+
PURPOSE : Returns size of data excluding length of tag (alpha identifier)
*/
USHORT pb_sim_get_size_except_tag (USHORT field_id)
{
TRACE_FUNCTION("pb_sim_get_size_except_tag()");
switch(field_id)
{
case SIM_ADN:
case SIM_FDN:
case SIM_BDN:
case SIM_MSISDN:
case SIM_SDN:
return 14; /* 11.11 */
case FFS_LRN:
case FFS_LMN:
case SIM_OCI:
return 27; /* Using EF_OCI, 31.102 4.2.34 */
//case SIM_ICI:
// return 28; /* Using EF_ICI, 31.102 4.2.33 */
default:
TRACE_ERROR("Invalid field ID passed !");
return 0;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_cmpString |
+--------------------------------------------------------------------+
PURPOSE : compare two strings.
if s1 < s2 return value < 0
if s1 = s2 return value = 0
if s1 > s2 return value > 0
*/
static int pb_sim_cmpString ( UBYTE *s1, UBYTE *s2, UBYTE len )
{
int n = 0;
/* TRACE_FUNCTION("pb_sim_cmpString()"); */ /* Called too often to trace */
if ((*s1 EQ 0x80) AND
(*s2 NEQ 0x80) )
{
s1++;
len--;
return pb_sim_cmp2Bytes(s1, s2, len, 1);
}
else if ((*s1 NEQ 0x80) AND
(*s2 EQ 0x80) )
{
s2++;
len--;
return pb_sim_cmp2Bytes(s1, s2, len, 2);
}
else
{
while (*s1 EQ *s2)
{
if (*s1 EQ 0xff)
return 0;
s1++;
s2++;
n++;
if (n EQ len)
return 0;
}
if ((*s1 > *s2) AND (*s1 NEQ 0xff))
return 1;
return -1;
}
}
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_cmp2Bytes |
+--------------------------------------------------------------------+
PURPOSE : compare two strings.
if s1 < s2 return value < 0
if s1 = s2 return value = 0
if s1 > s2 return value > 0
flag = 1, s1 is unicode
flag = 2, s2 is unicode
*/
LOCAL int pb_sim_cmp2Bytes(UBYTE *s1, UBYTE *s2, UBYTE len, UBYTE flag)
{
int n = 0;
/* TRACE_FUNCTION("pb_sim_cmp2Bytes()"); */
if (flag EQ 1)
{
while ( (*s1 EQ 0x00 OR *s1 EQ 0xFF ) AND ( *(s1+1) EQ *s2) )
{
if (*s1 EQ 0xff AND *(s1+1) EQ 0xFF)
return 0;
s1 += 2;
s2++;
n += 2;
if (n >= len)
return 0;
}
if ( ( *s1 > 0 AND *s1 NEQ 0xff ) OR
( !*s1 AND ( *(s1+1) > *s2 ) ) )
return 1;
return -1;
}
if (flag EQ 2)
{
while ((*s2 EQ 0x00 OR *s2 EQ 0xFF) AND (*s1 EQ *(s2+1)))
{
if (*s2 EQ 0xff AND *(s2+1) EQ 0xFF)
return 0;
s1++;
s2 += 2;
n += 2;
if (n >= len)
return 0;
}
if ((*s2 > 0 AND *s2 NEQ 0xff) OR
(!*s2 AND (*(s2+1) > *s1)) )
return -1;
return 1;
}
return -1;
}
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_update_extn_records |
+--------------------------------------------------------------------+
PURPOSE : Update reference count for extension record and
delete if record is not referenced at all.
*/
LOCAL T_PHB_RETURN pb_sim_update_extn_records(USHORT ext_field_id, USHORT rec_num, T_PHB_EXT_REF_TYPE ref_type)
{
BOOL delete_record = FALSE;
int db_result;
/* Depending on the Extension file update the corresponding array. */
if(ref_type EQ DECREMENT)
{
switch(ext_field_id)
{
case SIM_EXT1:
ext1_ref_count[rec_num]--;
if(ext1_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case SIM_EXT2:
ext2_ref_count[rec_num]--;
if(ext2_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case SIM_EXT3:
ext3_ref_count[rec_num]--;
if(ext3_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case SIM_EXT4:
ext4_ref_count[rec_num]--;
if(ext4_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case SIM_EXT5:
ext5_ref_count[rec_num]--;
if(ext5_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case FFS_EXT_LRN:
ext_lrn_ref_count[rec_num]--;
if(ext_lrn_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
case FFS_EXT_LMN:
ext_lmn_ref_count[rec_num]--;
if(ext_lmn_ref_count[rec_num] EQ 0)
delete_record = TRUE;
break;
default:
return PHB_FAIL;
}
}
if(ref_type EQ INCREMENT)
{
switch(ext_field_id)
{
case SIM_EXT1:
ext1_ref_count[rec_num]++;
break;
case SIM_EXT2:
ext2_ref_count[rec_num]++;
break;
case SIM_EXT3:
ext3_ref_count[rec_num]++;
break;
case SIM_EXT4:
ext4_ref_count[rec_num]++;
break;
case SIM_EXT5:
ext5_ref_count[rec_num]++;
break;
case FFS_EXT_LRN:
ext_lrn_ref_count[rec_num]++;
break;
case FFS_EXT_LMN:
ext_lmn_ref_count[rec_num]++;
break;
default:
return PHB_FAIL;
}
}
/* Delete the extension record if it is not referenced. */
if(delete_record EQ TRUE)
{
db_result = db_delete_record(pbs_data.db_handle, ext_field_id, rec_num);
if(db_result < DB_OK)
return PHB_FAIL;
}
return PHB_OK;
}
/*
+--------------------------------------------------------------------+
| PROJECT : MMI-Framework (8417) MODULE : PHB |
| STATE : code ROUTINE : pb_sim_read_ext_record_for_delete |
+--------------------------------------------------------------------+
PURPOSE : Read extension records and update the records.
*/
LOCAL T_PHB_RETURN pb_sim_read_ext_record_for_delete(T_PHB_TYPE type, USHORT field_id, USHORT db_recno)
{
USHORT ext_file_id;
T_DB_INFO_FIELD info_field;
UBYTE buffer[RDM_PHB_DATA_SIZE];
UBYTE data[SIM_MAX_RECORD_SIZE], *ptr;
UBYTE max_tag_len;
UBYTE ext_rcd_num;
T_PHB_RECORD entry;
TRACE_FUNCTION("pb_sim_read_ext_record_for_delete()");
/* Get Extension file for the Phonebook type. */
ext_file_id = pb_sim_get_ext_file(type);
/* Read record from the database. */
if(db_info_field(pbs_data.db_handle, field_id, &info_field) NEQ DB_OK)
return PHB_FAIL;
if(db_read_record(pbs_data.db_handle, field_id, db_recno, 0, info_field.record_size, data) < DB_OK)
return PHB_FAIL;
/* Convert SIM data to the type T_PHB_RECORD. */
ptr = data;
max_tag_len = MINIMUM ((info_field.record_size) - pb_sim_get_size_except_tag(field_id), PHB_MAX_TAG_LEN);
ptr += (info_field.record_size) - pb_sim_get_size_except_tag(field_id);
max_tag_len = (info_field.record_size) - pb_sim_get_size_except_tag(field_id);
++ptr;
++ptr;
ptr += 10;
++ptr;
if (*ptr NEQ 0xFF) /* check for extention records */
{
ext_rcd_num =(UBYTE)*ptr;
if(db_info_field(pbs_data.db_handle, ext_file_id, &info_field) NEQ DB_OK)
return PHB_FAIL;
/* Reset pointer to start location. */
ptr = data;
memset(ptr, 0xFF, info_field.record_size);
if(db_read_record(pbs_data.db_handle, ext_file_id, ext_rcd_num, 0, info_field.record_size, ptr) < DB_OK)
return PHB_FAIL;
if(pb_sim_update_extn_records(ext_file_id, ext_rcd_num, DECREMENT) EQ PHB_FAIL)
return PHB_FAIL;
pb_sim_read_ext(ptr, &entry);
while(*(ptr + 12) NEQ 0xFF) /* check if a further EXT entry exists */
{
memset(ptr, 0xFF, info_field.record_size);
db_read_record(pbs_data.db_handle, ext_file_id, (USHORT)*(ptr+12), 0, info_field.record_size,ptr);
if(pb_sim_update_extn_records(ext_file_id, (USHORT)*(ptr+12), DECREMENT) EQ PHB_FAIL)
return PHB_FAIL;
pb_sim_read_ext(ptr, &entry);
}
}
return PHB_OK;
}
#endif /* #ifdef TI_PS_FFS_PHB */